mirror of https://github.com/nocodb/nocodb
Browse Source
* fix: remove unused code base * fix: enable cleanup * fix: use global variable instead of staticnc-oss/f4dcddf8
Mert E
6 months ago
committed by
GitHub
39 changed files with 58 additions and 11442 deletions
File diff suppressed because it is too large
Load Diff
@ -1,228 +0,0 @@
|
||||
import BaseRender from '../../BaseRender'; |
||||
|
||||
class ExpressXcPolicyGql extends BaseRender { |
||||
/** |
||||
* |
||||
* @param dir |
||||
* @param filename |
||||
* @param ctx |
||||
* @param ctx.tn |
||||
* @param ctx.columns |
||||
* @param ctx.relations |
||||
*/ |
||||
constructor({ dir = '', filename = '', ctx }) { |
||||
super({ dir, filename, ctx }); |
||||
} |
||||
|
||||
/** |
||||
* Prepare variables used in code template |
||||
*/ |
||||
prepare(): any { |
||||
let data = {}; |
||||
|
||||
/* run of simple variable */ |
||||
data = this.ctx; |
||||
|
||||
return data; |
||||
} |
||||
|
||||
getObject() { |
||||
return { |
||||
[`${this.ctx.tn_camelize}List`]: { admin: true, user: true, guest: true }, |
||||
[`${this.ctx.tn_camelize}Read`]: { admin: true, user: true, guest: true }, |
||||
[`${this.ctx.tn_camelize}Create`]: { |
||||
admin: true, |
||||
user: true, |
||||
guest: false, |
||||
}, |
||||
[`${this.ctx.tn_camelize}Update`]: { |
||||
admin: true, |
||||
user: true, |
||||
guest: false, |
||||
}, |
||||
[`${this.ctx.tn_camelize}Delete`]: { |
||||
admin: true, |
||||
user: true, |
||||
guest: false, |
||||
}, |
||||
[`${this.ctx.tn_camelize}Exists`]: { |
||||
admin: true, |
||||
user: true, |
||||
guest: true, |
||||
}, |
||||
[`${this.ctx.tn_camelize}FindOne`]: { |
||||
admin: true, |
||||
user: true, |
||||
guest: true, |
||||
}, |
||||
[`${this.ctx.tn_camelize}Count`]: { |
||||
admin: true, |
||||
user: true, |
||||
guest: true, |
||||
}, |
||||
[`${this.ctx.tn_camelize}Distinct`]: { |
||||
admin: true, |
||||
user: true, |
||||
guest: true, |
||||
}, |
||||
[`${this.ctx.tn_camelize}GroupBy`]: { |
||||
admin: true, |
||||
user: true, |
||||
guest: true, |
||||
}, |
||||
[`${this.ctx.tn_camelize}Aggregate`]: { |
||||
admin: true, |
||||
user: true, |
||||
guest: true, |
||||
}, |
||||
[`${this.ctx.tn_camelize}Distribution`]: { |
||||
admin: true, |
||||
user: true, |
||||
guest: true, |
||||
}, |
||||
[`${this.ctx.tn_camelize}CreateBulk`]: { |
||||
admin: true, |
||||
user: true, |
||||
guest: false, |
||||
}, |
||||
[`${this.ctx.tn_camelize}UpdateBulk`]: { |
||||
admin: true, |
||||
user: true, |
||||
guest: false, |
||||
}, |
||||
[`${this.ctx.tn_camelize}DeleteBulk`]: { |
||||
admin: true, |
||||
user: true, |
||||
guest: false, |
||||
}, |
||||
}; |
||||
} |
||||
|
||||
getFunctions() { |
||||
return { |
||||
[`${this.ctx.tn_camelize}List`]: [ |
||||
` |
||||
async function(args, {req,res,next}){ |
||||
return (await req.model.list(args)).map(o => { |
||||
return new req.gqlType(o); |
||||
}); |
||||
} |
||||
`,
|
||||
], |
||||
[`${this.ctx.tn_camelize}Read`]: [ |
||||
` |
||||
async function(args, {req,res,next}){ |
||||
const data = await req.model.readByPk(args.id); |
||||
return new req.gqlType(data); |
||||
} |
||||
`,
|
||||
], |
||||
[`${this.ctx.tn_camelize}Create`]: [ |
||||
` |
||||
async function(args, {req,res,next}){ |
||||
const data = await req.model.insert(args.data); |
||||
return new req.gqlType(data);
|
||||
}
|
||||
`,
|
||||
], |
||||
[`${this.ctx.tn_camelize}Update`]: [ |
||||
` |
||||
async function(args, {req,res,next}){ |
||||
const data = await req.model.updateByPk(args.id, args.data); |
||||
return data;
|
||||
}
|
||||
`,
|
||||
], |
||||
[`${this.ctx.tn_camelize}Delete`]: [ |
||||
` |
||||
async function(args, {req,res,next}){ |
||||
const data = await req.model.delByPk(args.id); |
||||
return data;
|
||||
}
|
||||
`,
|
||||
], |
||||
[`${this.ctx.tn_camelize}Exists`]: [ |
||||
` |
||||
async function(args, {req,res,next}){ |
||||
const data = await req.model.exists(args.id); |
||||
return data;
|
||||
}
|
||||
`,
|
||||
], |
||||
[`${this.ctx.tn_camelize}FindOne`]: [ |
||||
` |
||||
async function(args, {req,res,next}){ |
||||
const data = await req.model.findOne(args); |
||||
return new req.gqlType(data);
|
||||
}
|
||||
`,
|
||||
], |
||||
[`${this.ctx.tn_camelize}Count`]: [ |
||||
` |
||||
async function(args, {req,res,next}){ |
||||
const data = await req.model.countByPk(args); |
||||
return data.count;
|
||||
}
|
||||
`,
|
||||
], |
||||
[`${this.ctx.tn_camelize}Distinct`]: [ |
||||
` |
||||
async function(args, {req,res,next}){ |
||||
const data = (await req.model.distinct(args)).map(d => new req.gqlType(d)); |
||||
return data;
|
||||
}
|
||||
`,
|
||||
], |
||||
[`${this.ctx.tn_camelize}GroupBy`]: [ |
||||
` |
||||
async function(args, {req,res,next}){ |
||||
const data = await req.model.groupBy(args); |
||||
return data;
|
||||
}
|
||||
`,
|
||||
], |
||||
[`${this.ctx.tn_camelize}Aggregate`]: [ |
||||
` |
||||
async function(args, {req,res,next}){ |
||||
const data = await req.model.aggregate(args); |
||||
return data;
|
||||
}
|
||||
`,
|
||||
], |
||||
[`${this.ctx.tn_camelize}Distribution`]: [ |
||||
` |
||||
async function(args, {req,res,next}){ |
||||
const data = await req.model.distribution(args); |
||||
return data;
|
||||
}
|
||||
`,
|
||||
], |
||||
[`${this.ctx.tn_camelize}CreateBulk`]: [ |
||||
` |
||||
async function(args, {req,res,next}){ |
||||
const data = await req.model.insertb(args.data); |
||||
return data;
|
||||
}
|
||||
`,
|
||||
], |
||||
[`${this.ctx.tn_camelize}UpdateBulk`]: [ |
||||
` |
||||
async function(args, {req,res,next}){ |
||||
const data = await req.model.updateb(args.data); |
||||
return data;
|
||||
}
|
||||
`,
|
||||
], |
||||
[`${this.ctx.tn_camelize}DeleteBulk`]: [ |
||||
` |
||||
async function(args, {req,res,next}){ |
||||
const data = await req.model.delb(args.data); |
||||
return data;
|
||||
}
|
||||
`,
|
||||
], |
||||
}; |
||||
} |
||||
} |
||||
|
||||
export default ExpressXcPolicyGql; |
@ -1,224 +0,0 @@
|
||||
import uniqBy from 'lodash/uniqBy'; |
||||
import BaseRender from '../../BaseRender'; |
||||
import { AGG_DEFAULT_COLS, GROUPBY_DEFAULT_COLS } from './schemaHelp'; |
||||
|
||||
abstract class BaseGqlXcTsSchema extends BaseRender { |
||||
/** |
||||
* |
||||
* @param dir |
||||
* @param filename |
||||
* @param ct |
||||
* @param ctx.tn |
||||
* @param ctx.columns |
||||
* @param ctx.relations |
||||
*/ |
||||
protected constructor({ dir, filename, ctx }) { |
||||
super({ dir, filename, ctx }); |
||||
} |
||||
|
||||
/** |
||||
* Prepare variables used in code template |
||||
*/ |
||||
public prepare(): any { |
||||
const data: any = {}; |
||||
|
||||
data.columns = { |
||||
func: this._renderColumns.bind(this), |
||||
args: this.ctx, |
||||
}; |
||||
|
||||
return data; |
||||
} |
||||
|
||||
/** |
||||
* |
||||
* @param args |
||||
* @param args.columns |
||||
* @param args.relations |
||||
* @returns {string} |
||||
* @private |
||||
*/ |
||||
public _renderColumns(args): string { |
||||
let str = ''; |
||||
|
||||
str += ` |
||||
${this._getInputType(args)}\r\n |
||||
${this._getQuery(args)},\r\n |
||||
${this._getMutation(args)}\r\n |
||||
${this._getType(args)}\r\n |
||||
`;
|
||||
|
||||
str += ''; |
||||
|
||||
return str; |
||||
} |
||||
|
||||
public getString(): string { |
||||
return this._renderColumns(this.ctx); |
||||
} |
||||
|
||||
protected generateManyToManyTypeProps(args: any): string { |
||||
if (!args.manyToMany?.length) { |
||||
return ''; |
||||
} |
||||
let str = '\r\n'; |
||||
for (const mm of args.manyToMany) { |
||||
str += `\t\t${mm._rtn}MMList(where: String,limit: Int, offset: Int, sort: String): [${mm._rtn}]\r\n`; |
||||
} |
||||
return str; |
||||
} |
||||
|
||||
protected generateVirtualTypes(args: any): string { |
||||
if (!args.v?.length) { |
||||
return ''; |
||||
} |
||||
const props = []; |
||||
for (const v of args.v) { |
||||
if (!v.formula && !v.rl) continue; |
||||
props.push(`\t\t${v._cn}: JSON`); |
||||
} |
||||
return props.length ? `\r\n${props.join('\r\n')}\r\n` : ''; |
||||
} |
||||
|
||||
protected _getInputType(args): string { |
||||
let str = `input ${args._tn}Input { \r\n`; |
||||
for (const column of args.columns) { |
||||
if (/\s/.test(column._cn)) { |
||||
console.log(`Skipping ${args.tn}.${column._cn}`); |
||||
} else { |
||||
str += `\t\t${column._cn}: ${this._getGraphqlType(column)},\r\n`; |
||||
} |
||||
} |
||||
str += `\t}`; |
||||
return str; |
||||
} |
||||
|
||||
protected _getQuery(args): string { |
||||
let str = `type Query { \r\n`; |
||||
str += `\t\t${args._tn}List(where: String,condition:Condition${args._tn}, limit: Int, offset: Int, sort: String,conditionGraph: String): [${args._tn}]\r\n`; |
||||
str += `\t\t${args._tn}Read(id:String!): ${args._tn}\r\n`; |
||||
str += `\t\t${args._tn}Exists(id: String!): Boolean\r\n`; |
||||
str += `\t\t${args._tn}FindOne(where: String,condition:Condition${args._tn}): ${args._tn}\r\n`; |
||||
str += `\t\t${args._tn}Count(where: String,condition:Condition${args._tn},conditionGraph: String): Int\r\n`; |
||||
str += `\t\t${args._tn}Distinct(column_name: String, where: String,condition:Condition${args._tn}, limit: Int, offset: Int, sort: String): [${args._tn}]\r\n`; |
||||
str += `\t\t${args._tn}GroupBy(fields: String, having: String, limit: Int, offset: Int, sort: String): [${args._tn}GroupBy]\r\n`; |
||||
str += `\t\t${args._tn}Aggregate(column_name: String!, having: String, limit: Int, offset: Int, sort: String, func: String!): [${args._tn}Aggregate]\r\n`; |
||||
str += `\t\t${args._tn}Distribution(min: Int, max: Int, step: Int, steps: String, column_name: String!): [distribution]\r\n`; |
||||
str += `\t}\r\n`; |
||||
return str; |
||||
} |
||||
|
||||
protected _getMutation(args): string { |
||||
let str = `type Mutation { \r\n`; |
||||
str += `\t\t${args._tn}Create(data:${args._tn}Input): ${args._tn}\r\n`; |
||||
str += `\t\t${args._tn}Update(id:String,data:${args._tn}Input): ${args._tn}\r\n`; // ${args._tn}\r\n`
|
||||
str += `\t\t${args._tn}Delete(id:String): Int\r\n`; // ${args._tn}\r\n`
|
||||
str += `\t\t${args._tn}CreateBulk(data: [${args._tn}Input]): [Int]\r\n`; |
||||
str += `\t\t${args._tn}UpdateBulk(data: [${args._tn}Input]): [Int]\r\n`; |
||||
str += `\t\t${args._tn}DeleteBulk(data: [${args._tn}Input]): [Int]\r\n`; |
||||
str += `\t},\r\n`; |
||||
return str; |
||||
} |
||||
|
||||
protected _getType(args): string { |
||||
let str = `type ${args._tn} { \r\n`; |
||||
let strWhere = `input Condition${args._tn} { \r\n`; |
||||
|
||||
for (const column of args.columns) { |
||||
if (column._cn.split(' ').length > 1) { |
||||
console.log(`Skipping ${args.tn}.${column._cn}`); |
||||
} else { |
||||
str += `\t\t${column._cn.replace(/ /g, '_')}: ${this._getGraphqlType( |
||||
column, |
||||
)},\r\n`;
|
||||
strWhere += `\t\t${column._cn.replace( |
||||
/ /g, |
||||
'_', |
||||
)}: ${this._getGraphqlConditionType(column)},\r\n`;
|
||||
} |
||||
} |
||||
|
||||
let hasManyRelations = args.hasMany; |
||||
if (hasManyRelations.length > 1) { |
||||
hasManyRelations = uniqBy(hasManyRelations, (e) => { |
||||
return [e.tn, e.rtn].join(); |
||||
}); |
||||
} |
||||
|
||||
str += hasManyRelations.length ? `\r\n` : ``; |
||||
// cityList in Country
|
||||
for (const { _tn } of hasManyRelations) { |
||||
const childTable = _tn; |
||||
str += `\t\t${childTable}List(where: String,limit: Int, offset: Int, sort: String): [${childTable}]\r\n`; |
||||
strWhere += `\t\t${childTable}List: Condition${childTable}\r\n`; |
||||
str += `\t\t${childTable}Count: Int\r\n`; |
||||
} |
||||
|
||||
str += this.generateManyToManyTypeProps(args); |
||||
str += this.generateVirtualTypes(args); |
||||
|
||||
let belongsToRelations = args.belongsTo; |
||||
if (belongsToRelations.length > 1) { |
||||
belongsToRelations = uniqBy(belongsToRelations, (e) => { |
||||
return [e.tn, e.rtn].join(); |
||||
}); |
||||
} |
||||
|
||||
str += belongsToRelations.length ? `\r\n` : ``; |
||||
// Country withi city - this is reverse
|
||||
for (const { _rtn } of belongsToRelations) { |
||||
const parentTable = _rtn; |
||||
str += `\t\t${parentTable}Read(id:String): ${parentTable}\r\n`; |
||||
strWhere += `\t\t${parentTable}Read: Condition${parentTable}\r\n`; |
||||
} |
||||
|
||||
str += `\t}\r\n`; |
||||
|
||||
const grpFields = { ...GROUPBY_DEFAULT_COLS }; |
||||
|
||||
str += `type ${args._tn}GroupBy { \r\n`; |
||||
for (const { _cn, ...rest } of args.columns) { |
||||
if (_cn in grpFields) { |
||||
grpFields[_cn] = `\t\t# ${_cn} - clashes with column in table\r\n`; |
||||
} else { |
||||
str += `\t\t${_cn.replace(/ /g, '_')}: ${this._getGraphqlType( |
||||
rest, |
||||
)},\r\n`;
|
||||
} |
||||
} |
||||
str += Object.values(grpFields).join(''); |
||||
str += `\t}\r\n`; |
||||
|
||||
const aggFields = { ...AGG_DEFAULT_COLS }; |
||||
|
||||
str += `type ${args._tn}Aggregate { \r\n`; |
||||
for (const column of args.columns) { |
||||
if (column._cn in aggFields) { |
||||
aggFields[ |
||||
column._cn |
||||
] = `\t\t# ${column._cn} - clashes with column in table\r\n`; |
||||
} else { |
||||
str += `\t\t${column._cn.replace(/ /g, '_')}: ${this._getGraphqlType( |
||||
column, |
||||
)},\r\n`;
|
||||
} |
||||
} |
||||
str += Object.values(aggFields).join(''); |
||||
|
||||
str += `\t}\r\n`; |
||||
strWhere += ` |
||||
_or:[Condition${args._tn}] |
||||
_not:Condition${args._tn} |
||||
_and:[Condition${args._tn}] |
||||
|
||||
\t}\r\n`;
|
||||
|
||||
return `${str}\r\n\r\n${strWhere}`; |
||||
} |
||||
|
||||
protected abstract _getGraphqlType(column: any): string; |
||||
|
||||
protected abstract _getGraphqlConditionType(columnObj): string; |
||||
} |
||||
|
||||
export default BaseGqlXcTsSchema; |
@ -1,28 +0,0 @@
|
||||
import GqlXcSchemaMssql from './GqlXcTsSchemaMssql'; |
||||
import GqlXcTsSchemaMysql from './GqlXcTsSchemaMysql'; |
||||
import GqlXcSchemaOracle from './GqlXcTsSchemaOracle'; |
||||
import GqlXcSchemaPg from './GqlXcTsSchemaPg'; |
||||
import GqlXcSchemaSqlite from './GqlXcTsSchemaSqlite'; |
||||
|
||||
class GqlXcSchemaFactory { |
||||
public static create(connectionConfig, args): any { |
||||
if ( |
||||
connectionConfig.client === 'mysql2' || |
||||
connectionConfig.client === 'mysql' |
||||
) { |
||||
return new GqlXcTsSchemaMysql(args); |
||||
} else if (connectionConfig.client === 'sqlite3') { |
||||
return new GqlXcSchemaSqlite(args); |
||||
} else if (connectionConfig.client === 'mssql') { |
||||
return new GqlXcSchemaMssql(args); |
||||
} else if (connectionConfig.client === 'pg') { |
||||
return new GqlXcSchemaPg(args); |
||||
} else if (connectionConfig.client === 'oracledb') { |
||||
return new GqlXcSchemaOracle(args); |
||||
} |
||||
|
||||
throw new Error('Database not supported'); |
||||
} |
||||
} |
||||
|
||||
export default GqlXcSchemaFactory; |
@ -1,245 +0,0 @@
|
||||
import BaseGqlXcTsSchema from './BaseGqlXcTsSchema'; |
||||
|
||||
class GqlXcTsSchemaMssql extends BaseGqlXcTsSchema { |
||||
/** |
||||
* |
||||
* @param dir |
||||
* @param filename |
||||
* @param ct |
||||
* @param ctx.tn |
||||
* @param ctx.columns |
||||
* @param ctx.relations |
||||
*/ |
||||
constructor({ dir, filename, ctx }) { |
||||
super({ dir, filename, ctx }); |
||||
} |
||||
|
||||
/* |
||||
|
||||
/!** |
||||
* |
||||
* @param args |
||||
* @param args.columns |
||||
* @param args.relations |
||||
* @returns {string} |
||||
* @private |
||||
*!/ |
||||
_renderColumns(args) { |
||||
|
||||
let str = ''; |
||||
|
||||
str += ` |
||||
${this._getInputType(args)}\r\n |
||||
${this._getQuery(args)},\r\n |
||||
${this._getMutation(args)}\r\n |
||||
${this._getType(args)}\r\n |
||||
` |
||||
|
||||
str += ''; |
||||
|
||||
return str; |
||||
|
||||
} |
||||
|
||||
_getInputType(args) { |
||||
let str = `input ${args.tn_camelize}Input { \r\n` |
||||
for (let i = 0; i < args.columns.length; ++i) { |
||||
if (args.columns[i]._cn.split(' ').length > 1) { |
||||
// str += `\t\t${args.columns[i]._cn}: ${this._getGraphqlType(args.columns[i])},\r\n`;
|
||||
} else { |
||||
str += `\t\t${args.columns[i]._cn}: ${this._getGraphqlType(args.columns[i])},\r\n`; |
||||
} |
||||
|
||||
} |
||||
str += `\t}`; |
||||
return str; |
||||
} |
||||
|
||||
_getQuery(args) { |
||||
let str = `type Query { \r\n` |
||||
str += `\t\t${args.tn_camelize}List(where: String,condition:Condition${args.tn_camelize}, limit: Int, offset: Int, sort: String): [${args.tn_camelize}]\r\n` |
||||
str += `\t\t${args.tn_camelize}Read(id:String!): ${args.tn_camelize}\r\n` |
||||
str += `\t\t${args.tn_camelize}Exists(id: String!): Boolean\r\n` |
||||
str += `\t\t${args.tn_camelize}FindOne(where: String,condition:Condition${args.tn_camelize}): ${args.tn_camelize}\r\n` |
||||
str += `\t\t${args.tn_camelize}Count(where: String,condition:Condition${args.tn_camelize}): Int\r\n` |
||||
str += `\t\t${args.tn_camelize}Distinct(column_name: String, where: String,condition:Condition${args.tn_camelize}, limit: Int, offset: Int, sort: String): [${args.tn_camelize}]\r\n` |
||||
str += `\t\t${args.tn_camelize}GroupBy(fields: String, having: String, limit: Int, offset: Int, sort: String): [${args.tn_camelize}GroupBy]\r\n` |
||||
str += `\t\t${args.tn_camelize}Aggregate(column_name: String!, having: String, limit: Int, offset: Int, sort: String, func: String!): [${args.tn_camelize}Aggregate]\r\n` |
||||
str += `\t\t${args.tn_camelize}Distribution(min: Int, max: Int, step: Int, steps: String, column_name: String!): [distribution]\r\n` |
||||
str += `\t}\r\n` |
||||
return str; |
||||
} |
||||
|
||||
_getMutation(args) { |
||||
let str = `type Mutation { \r\n` |
||||
str += `\t\t${args.tn_camelize}Create(data:${args.tn_camelize}Input): ${args.tn_camelize}\r\n` |
||||
str += `\t\t${args.tn_camelize}Update(id:String,data:${args.tn_camelize}Input): Int\r\n` //${args.tn_camelize}\r\n`
|
||||
str += `\t\t${args.tn_camelize}Delete(id:String): Int\r\n`//${args.tn_camelize}\r\n`
|
||||
str += `\t\t${args.tn_camelize}CreateBulk(data: [${args.tn_camelize}Input]): [Int]\r\n` |
||||
str += `\t\t${args.tn_camelize}UpdateBulk(data: [${args.tn_camelize}Input]): [Int]\r\n` |
||||
str += `\t\t${args.tn_camelize}DeleteBulk(data: [${args.tn_camelize}Input]): [Int]\r\n` |
||||
str += `\t},\r\n` |
||||
return str; |
||||
} |
||||
|
||||
_getType(args) { |
||||
|
||||
let str = `type ${args.tn_camelize} { \r\n` |
||||
let strWhere = `input Condition${args.tn_camelize} { \r\n` |
||||
|
||||
for (let i = 0; i < args.columns.length; ++i) { |
||||
str += `\t\t${args.columns[i]._cn}: ${this._getGraphqlType(args.columns[i])},\r\n`; |
||||
strWhere += `\t\t${args.columns[i]._cn}: ${this._getGraphqlConditionType(args.columns[i])},\r\n`; |
||||
} |
||||
|
||||
let hasManyRelations = args.relations.filter(r => r.rtn === args.tn); |
||||
if (hasManyRelations.length > 1) |
||||
hasManyRelations = lodash.uniqBy(hasManyRelations, function (e) { |
||||
return [e.tn, e.rtn].join(); |
||||
}); |
||||
|
||||
str += hasManyRelations.length ? `\r\n` : ``; |
||||
// cityList in Country
|
||||
for (let i = 0; i < hasManyRelations.length; ++i) { |
||||
let childTable = inflection.camelize(hasManyRelations[i]._tn) |
||||
str += `\t\t${childTable}List: [${childTable}]\r\n`; |
||||
strWhere += `\t\t${childTable}List: Condition${childTable}\r\n`; |
||||
str += `\t\t${childTable}Count: Int\r\n`; |
||||
} |
||||
|
||||
str += this.generateManyToManyTypeProps(args); |
||||
|
||||
let belongsToRelations = args.relations.filter(r => r.tn === args.tn); |
||||
if (belongsToRelations.length > 1) |
||||
belongsToRelations = lodash.uniqBy(belongsToRelations, function (e) { |
||||
return [e.tn, e.rtn].join(); |
||||
}); |
||||
|
||||
str += belongsToRelations.length ? `\r\n` : ``; |
||||
// Country withi city - this is reverse
|
||||
for (let i = 0; i < belongsToRelations.length; ++i) { |
||||
let parentTable = inflection.camelize(belongsToRelations[i]._rtn) |
||||
str += `\t\t${parentTable}Read(id:String): ${parentTable}\r\n`; |
||||
strWhere += `\t\t${parentTable}Read: Condition${parentTable}\r\n`; |
||||
} |
||||
|
||||
str += `\t}\r\n` |
||||
|
||||
|
||||
const grpFields = Object.assign({}, GROUPBY_DEFAULT_COLS); |
||||
|
||||
str += `type ${args.tn_camelize}GroupBy { \r\n` |
||||
for (let i = 0; i < args.columns.length; ++i) { |
||||
if (args.columns[i]._cn in grpFields) { |
||||
grpFields[args.columns[i]._cn] = `\t\t# ${args.columns[i]._cn} - clashes with column in table\r\n`; |
||||
} else { |
||||
str += `\t\t${args.columns[i]._cn}: ${this._getGraphqlType(args.columns[i])},\r\n`; |
||||
} |
||||
} |
||||
str += Object.values(grpFields).join(''); |
||||
str += `\t}\r\n` |
||||
|
||||
|
||||
const aggFields = Object.assign({}, AGG_DEFAULT_COLS); |
||||
|
||||
str += `type ${args.tn_camelize}Aggregate { \r\n` |
||||
for (let i = 0; i < args.columns.length; ++i) { |
||||
if (args.columns[i]._cn in aggFields) { |
||||
aggFields[args.columns[i]._cn] = `\t\t# ${args.columns[i]._cn} - clashes with column in table\r\n`; |
||||
} else { |
||||
str += `\t\t${args.columns[i]._cn}: ${this._getGraphqlType(args.columns[i])},\r\n`; |
||||
} |
||||
} |
||||
|
||||
str += Object.values(aggFields).join(''); |
||||
|
||||
str += `\t}\r\n` |
||||
strWhere += ` |
||||
_or:[Condition${args.tn_camelize}] |
||||
_not:Condition${args.tn_camelize} |
||||
_and:[Condition${args.tn_camelize}] |
||||
|
||||
\t}\r\n` |
||||
|
||||
|
||||
return `${str}\r\n\r\n${strWhere}`; |
||||
} |
||||
*/ |
||||
|
||||
_getGraphqlType(columnObj): any { |
||||
switch (columnObj.dt) { |
||||
case 'smallint': |
||||
case 'int': |
||||
case 'tinyint': |
||||
case 'bigint': |
||||
return 'Int'; |
||||
break; |
||||
|
||||
case 'numeric': |
||||
case 'money': |
||||
case 'real': |
||||
case 'decimal': |
||||
case 'float': |
||||
return 'Float'; |
||||
break; |
||||
|
||||
case 'binary': |
||||
case 'bit': |
||||
return 'Boolean'; |
||||
break; |
||||
|
||||
case 'char': |
||||
case 'date': |
||||
case 'datetime': |
||||
case 'datetime2': |
||||
case 'datetimeoffset': |
||||
case 'heirarchyid': |
||||
case 'image': |
||||
case 'nchar': |
||||
case 'ntext': |
||||
case 'nvarchar': |
||||
case 'smalldatetime': |
||||
case 'smallmoney': |
||||
case 'sql_variant': |
||||
case 'sysname': |
||||
case 'text': |
||||
case 'time': |
||||
case 'timestamp': |
||||
case 'uniqueidentifier': |
||||
case 'varbinary': |
||||
case 'xml': |
||||
case 'varchar': |
||||
default: |
||||
return 'String'; |
||||
break; |
||||
|
||||
case 'geography': |
||||
case 'geometry': |
||||
case 'json': |
||||
return 'JSON'; |
||||
} |
||||
} |
||||
|
||||
_getGraphqlConditionType(columnObj): any { |
||||
switch (this._getGraphqlType(columnObj.dt)) { |
||||
case 'Int': |
||||
return 'ConditionInt'; |
||||
case 'Float': |
||||
return 'ConditionFloat'; |
||||
case 'Boolean': |
||||
return 'ConditionBoolean'; |
||||
case 'String': |
||||
return 'ConditionString'; |
||||
case '[String]': |
||||
return 'ConditionString'; |
||||
case 'JSON': |
||||
return 'ConditionString'; |
||||
} |
||||
} |
||||
|
||||
/* getString() { |
||||
return this._renderColumns(this.ctx); |
||||
}*/ |
||||
} |
||||
|
||||
export default GqlXcTsSchemaMssql; |
@ -1,269 +0,0 @@
|
||||
import BaseGqlXcTsSchema from './BaseGqlXcTsSchema'; |
||||
|
||||
class GqlXcTsSchemaMysql extends BaseGqlXcTsSchema { |
||||
/** |
||||
* |
||||
* @param dir |
||||
* @param filename |
||||
* @param ct |
||||
* @param ctx.tn |
||||
* @param ctx.columns |
||||
* @param ctx.relations |
||||
*/ |
||||
constructor({ dir, filename, ctx }) { |
||||
super({ dir, filename, ctx }); |
||||
} |
||||
|
||||
/*/!** |
||||
* |
||||
* @param args |
||||
* @param args.columns |
||||
* @param args.relations |
||||
* @returns {string} |
||||
* @private |
||||
*!/ |
||||
_renderColumns(args) { |
||||
|
||||
let str = ''; |
||||
|
||||
str += ` |
||||
${this._getInputType(args)}\r\n |
||||
${this._getQuery(args)},\r\n |
||||
${this._getMutation(args)}\r\n |
||||
${this._getType(args)}\r\n |
||||
` |
||||
str += ''; |
||||
|
||||
return str; |
||||
|
||||
} |
||||
|
||||
_getInputType(args) { |
||||
let str = `input ${args.tn_camelize}Input { \r\n` |
||||
for (let i = 0; i < args.columns.length; ++i) { |
||||
if (args.columns[i]._cn.split(' ').length > 1) { |
||||
// str += `\t\t${args.columns[i]._cn}: ${this._getGraphqlType(args.columns[i])},\r\n`;
|
||||
} else { |
||||
str += `\t\t${args.columns[i]._cn}: ${this._getGraphqlType(args.columns[i])},\r\n`; |
||||
} |
||||
|
||||
} |
||||
str += `\t}`; |
||||
return str; |
||||
} |
||||
|
||||
_getQuery(args) { |
||||
let str = `type Query { \r\n` |
||||
str += `\t\t${args.tn_camelize}List(where: String,condition:Condition${args.tn_camelize}, limit: Int, offset: Int, sort: String, conditionGraph: String): [${args.tn_camelize}]\r\n` |
||||
str += `\t\t${args.tn_camelize}Read(id:String!): ${args.tn_camelize}\r\n` |
||||
str += `\t\t${args.tn_camelize}Exists(id: String!): Boolean\r\n` |
||||
str += `\t\t${args.tn_camelize}FindOne(where: String!,condition:Condition${args.tn_camelize}): ${args.tn_camelize}\r\n` |
||||
str += `\t\t${args.tn_camelize}Count(where: String!,condition:Condition${args.tn_camelize},conditionGraph: String): Int\r\n` |
||||
str += `\t\t${args.tn_camelize}Distinct(column_name: String, where: String,condition:Condition${args.tn_camelize}, limit: Int, offset: Int, sort: String): [${args.tn_camelize}]\r\n` |
||||
str += `\t\t${args.tn_camelize}GroupBy(fields: String, having: String, limit: Int, offset: Int, sort: String): [${args.tn_camelize}GroupBy]\r\n` |
||||
str += `\t\t${args.tn_camelize}Aggregate(column_name: String!, having: String, limit: Int, offset: Int, sort: String, func: String!): [${args.tn_camelize}Aggregate]\r\n` |
||||
str += `\t\t${args.tn_camelize}Distribution(min: Int, max: Int, step: Int, steps: String, column_name: String!): [distribution]\r\n` |
||||
str += `\t}\r\n` |
||||
return str; |
||||
} |
||||
|
||||
_getMutation(args) { |
||||
if (args.type === 'view') return ''; |
||||
let str = `type Mutation { \r\n` |
||||
str += `\t\t${args.tn_camelize}Create(data:${args.tn_camelize}Input): ${args.tn_camelize}\r\n` |
||||
str += `\t\t${args.tn_camelize}Update(id:String,data:${args.tn_camelize}Input): Int\r\n` //${args.tn_camelize}\r\n`
|
||||
str += `\t\t${args.tn_camelize}Delete(id:String): Int\r\n`//${args.tn_camelize}\r\n`
|
||||
str += `\t\t${args.tn_camelize}CreateBulk(data: [${args.tn_camelize}Input]): [Int]\r\n` |
||||
str += `\t\t${args.tn_camelize}UpdateBulk(data: [${args.tn_camelize}Input]): [Int]\r\n` |
||||
str += `\t\t${args.tn_camelize}DeleteBulk(data: [${args.tn_camelize}Input]): [Int]\r\n` |
||||
str += `\t},\r\n` |
||||
return str; |
||||
} |
||||
|
||||
_getType(args) { |
||||
|
||||
let str = `type ${args.tn_camelize} { \r\n` |
||||
let strWhere = `input Condition${args.tn_camelize} { \r\n` |
||||
|
||||
for (let i = 0; i < args.columns.length; ++i) { |
||||
// todo: handle column name contains whitespace
|
||||
if (args.columns[i]._cn.split(' ').length > 1) { |
||||
// str += `\t\t${args.columns[i]._cn}: ${this._getGraphqlType(args.columns[i])},\r\n`;
|
||||
} else { |
||||
str += `\t\t${args.columns[i]._cn}: ${this._getGraphqlType(args.columns[i])},\r\n`; |
||||
strWhere += `\t\t${args.columns[i]._cn}: ${this._getGraphqlConditionType(args.columns[i])},\r\n`; |
||||
} |
||||
} |
||||
|
||||
let hasManyRelations = args.relations.filter(r => r.rtn === args.tn); |
||||
if (hasManyRelations.length > 1) |
||||
hasManyRelations = lodash.uniqBy(hasManyRelations, function (e) { |
||||
return [e.tn, e.rtn].join(); |
||||
}); |
||||
|
||||
str += hasManyRelations.length ? `\r\n` : ``; |
||||
// cityList in Country
|
||||
for (let i = 0; i < hasManyRelations.length; ++i) { |
||||
let childTable = inflection.camelize(hasManyRelations[i]._tn) |
||||
str += `\t\t${childTable}List: [${childTable}]\r\n`; |
||||
strWhere += `\t\t${childTable}List: Condition${childTable}\r\n`; |
||||
str += `\t\t${childTable}Count: Int\r\n`; |
||||
} |
||||
|
||||
|
||||
str+= this.generateManyToManyTypeProps(args); |
||||
|
||||
let belongsToRelations = args.relations.filter(r => r.tn === args.tn); |
||||
if (belongsToRelations.length > 1) |
||||
belongsToRelations = lodash.uniqBy(belongsToRelations, function (e) { |
||||
return [e.tn, e.rtn].join(); |
||||
}); |
||||
|
||||
str += belongsToRelations.length ? `\r\n` : ``; |
||||
// Country withi city - this is reverse
|
||||
for (let i = 0; i < belongsToRelations.length; ++i) { |
||||
let parentTable = inflection.camelize(belongsToRelations[i]._rtn) |
||||
str += `\t\t${parentTable}Read(id:String): ${parentTable}\r\n`; |
||||
strWhere += `\t\t${parentTable}Read: Condition${parentTable}\r\n`; |
||||
} |
||||
|
||||
|
||||
str += `\t}\r\n` |
||||
|
||||
|
||||
const grpFields = Object.assign({}, GROUPBY_DEFAULT_COLS); |
||||
|
||||
str += `type ${args.tn_camelize}GroupBy { \r\n` |
||||
for (let i = 0; i < args.columns.length; ++i) { |
||||
if (args.columns[i]._cn in grpFields) { |
||||
grpFields[args.columns[i]._cn] = `\t\t# ${args.columns[i]._cn} - clashes with column in table\r\n`; |
||||
} else { |
||||
// todo: handle column name contains whitespace
|
||||
if (args.columns[i]._cn.split(' ').length > 1) { |
||||
// str += `\t\t${args.columns[i]._cn}: ${this._getGraphqlType(args.columns[i])},\r\n`;
|
||||
} else { |
||||
str += `\t\t${args.columns[i]._cn}: ${this._getGraphqlType(args.columns[i])},\r\n`; |
||||
} |
||||
} |
||||
} |
||||
str += Object.values(grpFields).join(''); |
||||
str += `\t}\r\n` |
||||
|
||||
const aggFields = Object.assign({}, AGG_DEFAULT_COLS); |
||||
|
||||
str += `type ${args.tn_camelize}Aggregate { \r\n` |
||||
for (let i = 0; i < args.columns.length; ++i) { |
||||
if (args.columns[i]._cn in aggFields) { |
||||
aggFields[args.columns[i]._cn] = `\t\t# ${args.columns[i]._cn} - clashes with column in table\r\n`; |
||||
} else { |
||||
// todo: handle column name contains whitespace
|
||||
if (args.columns[i]._cn.split(' ').length > 1) { |
||||
// str += `\t\t${args.columns[i]._cn}: ${this._getGraphqlType(args.columns[i])},\r\n`;
|
||||
} else { |
||||
str += `\t\t${args.columns[i]._cn}: ${this._getGraphqlType(args.columns[i])},\r\n`; |
||||
} |
||||
} |
||||
} |
||||
|
||||
str += Object.values(aggFields).join(''); |
||||
|
||||
str += `\t}\r\n` |
||||
strWhere += ` |
||||
_or:[Condition${args.tn_camelize}] |
||||
_not:Condition${args.tn_camelize} |
||||
_and:[Condition${args.tn_camelize}] |
||||
|
||||
\t}\r\n` |
||||
|
||||
|
||||
return `${str}\r\n\r\n${strWhere}`; |
||||
} |
||||
*/ |
||||
|
||||
protected _getGraphqlType(columnObj): string { |
||||
switch (columnObj.dt) { |
||||
case 'tinyint': |
||||
case 'smallint': |
||||
case 'mediumint': |
||||
case 'bigint': |
||||
case 'serial': |
||||
case 'int': |
||||
return 'Int'; |
||||
break; |
||||
|
||||
case 'float': |
||||
case 'decimal': |
||||
case 'double': |
||||
case 'real': |
||||
return 'Float'; |
||||
break; |
||||
|
||||
case 'bit': |
||||
case 'boolean': |
||||
return 'Boolean'; |
||||
|
||||
case 'date': |
||||
case 'datetime': |
||||
case 'timestamp': |
||||
case 'time': |
||||
case 'year': |
||||
return 'String'; |
||||
break; |
||||
|
||||
case 'char': |
||||
case 'varchar': |
||||
case 'nchar': |
||||
case 'text': |
||||
case 'tinytext': |
||||
case 'mediumtext': |
||||
case 'longtext': |
||||
case 'binary': |
||||
case 'varbinary': |
||||
case 'blob': |
||||
case 'tinyblob': |
||||
case 'mediumblob': |
||||
case 'longblob': |
||||
case 'enum': |
||||
return 'String'; |
||||
break; |
||||
|
||||
case 'set': |
||||
return 'JSON'; |
||||
break; |
||||
|
||||
case 'geometry': |
||||
case 'point': |
||||
case 'linestring': |
||||
case 'polygon': |
||||
case 'multipoint': |
||||
case 'multilinestring': |
||||
case 'multipolygon': |
||||
case 'json': |
||||
default: |
||||
return 'JSON'; |
||||
break; |
||||
} |
||||
} |
||||
|
||||
protected _getGraphqlConditionType(columnObj): any { |
||||
switch (this._getGraphqlType(columnObj.dt)) { |
||||
case 'Int': |
||||
return 'ConditionInt'; |
||||
case 'Float': |
||||
return 'ConditionFloat'; |
||||
case 'Boolean': |
||||
return 'ConditionBoolean'; |
||||
case 'String': |
||||
case 'JSON': |
||||
return 'ConditionString'; |
||||
case '[String]': |
||||
return 'ConditionString'; |
||||
} |
||||
} |
||||
|
||||
/*getString() { |
||||
return this._renderColumns(this.ctx); |
||||
}*/ |
||||
} |
||||
|
||||
export default GqlXcTsSchemaMysql; |
@ -1,253 +0,0 @@
|
||||
import BaseGqlXcTsSchema from './BaseGqlXcTsSchema'; |
||||
|
||||
class GqlXcSchemaOracle extends BaseGqlXcTsSchema { |
||||
/** |
||||
* |
||||
* @param dir |
||||
* @param filename |
||||
* @param ct |
||||
* @param ctx.tn |
||||
* @param ctx.columns |
||||
* @param ctx.relations |
||||
*/ |
||||
constructor({ dir, filename, ctx }) { |
||||
super({ dir, filename, ctx }); |
||||
} |
||||
|
||||
/*/!** |
||||
* Prepare variables used in code template |
||||
*!/ |
||||
prepare() { |
||||
|
||||
const data:any = {}; |
||||
|
||||
/!* run of simple variable *!/ |
||||
data.tn = this.ctx.tn_camelize; |
||||
|
||||
data.columns = { |
||||
func: this._renderColumns.bind(this), |
||||
args: this.ctx |
||||
}; |
||||
|
||||
return data; |
||||
|
||||
} |
||||
|
||||
|
||||
/!** |
||||
* |
||||
* @param args |
||||
* @param args.columns |
||||
* @param args.relations |
||||
* @returns {string} |
||||
* @private |
||||
*!/ |
||||
_renderColumns(args) { |
||||
|
||||
let str = ''; |
||||
|
||||
str += ` |
||||
${this._getInputType(args)}\r\n |
||||
${this._getQuery(args)},\r\n |
||||
${this._getMutation(args)}\r\n |
||||
${this._getType(args)}\r\n |
||||
` |
||||
|
||||
str += ''; |
||||
|
||||
return str; |
||||
|
||||
} |
||||
|
||||
_getInputType(args) { |
||||
let str = `input ${args.tn_camelize}Input { \r\n` |
||||
for (let i = 0; i < args.columns.length; ++i) { |
||||
if (args.columns[i]._cn.split(' ').length > 1) { |
||||
// str += `\t\t${args.columns[i]._cn}: ${this._getGraphqlType(args.columns[i])},\r\n`;
|
||||
} else { |
||||
str += `\t\t${args.columns[i]._cn}: ${this._getGraphqlType(args.columns[i])},\r\n`; |
||||
} |
||||
|
||||
} |
||||
str += `\t}`; |
||||
return str; |
||||
} |
||||
|
||||
_getQuery(args) { |
||||
let str = `type Query { \r\n` |
||||
str += `\t\t${args.tn_camelize}List(where: String,condition:Condition${args.tn_camelize}, limit: Int, offset: Int, sort: String): [${args.tn_camelize}]\r\n` |
||||
str += `\t\t${args.tn_camelize}Read(id:String!): ${args.tn_camelize}\r\n` |
||||
str += `\t\t${args.tn_camelize}Exists(id: String!): Boolean\r\n` |
||||
str += `\t\t${args.tn_camelize}FindOne(where: String,,condition:Condition${args.tn_camelize}): ${args.tn_camelize}\r\n` |
||||
str += `\t\t${args.tn_camelize}Count(where: String,condition:Condition${args.tn_camelize}): Int\r\n` |
||||
str += `\t\t${args.tn_camelize}Distinct(column_name: String, where: String,condition:Condition${args.tn_camelize}, limit: Int, offset: Int, sort: String): [${args.tn_camelize}]\r\n` |
||||
str += `\t\t${args.tn_camelize}GroupBy(fields: String, having: String, limit: Int, offset: Int, sort: String): [${args.tn_camelize}GroupBy]\r\n` |
||||
str += `\t\t${args.tn_camelize}Aggregate(column_name: String!, having: String, limit: Int, offset: Int, sort: String, func: String!): [${args.tn_camelize}Aggregate]\r\n` |
||||
str += `\t\t${args.tn_camelize}Distribution(min: Int, max: Int, step: Int, steps: String, column_name: String!): [distribution]\r\n` |
||||
str += `\t}\r\n` |
||||
return str; |
||||
} |
||||
|
||||
_getMutation(args) { |
||||
let str = `type Mutation { \r\n` |
||||
str += `\t\t${args.tn_camelize}Create(data:${args.tn_camelize}Input): ${args.tn_camelize}\r\n` |
||||
str += `\t\t${args.tn_camelize}Update(id:String,data:${args.tn_camelize}Input): Int\r\n` //${args.tn_camelize}\r\n`
|
||||
str += `\t\t${args.tn_camelize}Delete(id:String): Int\r\n`//${args.tn_camelize}\r\n`
|
||||
str += `\t\t${args.tn_camelize}CreateBulk(data: [${args.tn_camelize}Input]): [Int]\r\n` |
||||
str += `\t\t${args.tn_camelize}UpdateBulk(data: [${args.tn_camelize}Input]): [Int]\r\n` |
||||
str += `\t\t${args.tn_camelize}DeleteBulk(data: [${args.tn_camelize}Input]): [Int]\r\n` |
||||
str += `\t},\r\n` |
||||
return str; |
||||
} |
||||
|
||||
_getType(args) { |
||||
|
||||
let str = `type ${args.tn_camelize} { \r\n` |
||||
let strWhere = `input Condition${args.tn_camelize} { \r\n` |
||||
|
||||
for (let i = 0; i < args.columns.length; ++i) { |
||||
str += `\t\t${args.columns[i]._cn}: ${this._getGraphqlType(args.columns[i])},\r\n`; |
||||
strWhere += `\t\t${args.columns[i]._cn}: ${this._getGraphqlConditionType(args.columns[i])},\r\n`; |
||||
} |
||||
|
||||
let hasManyRelations = args.relations.filter(r => r.rtn === args.tn); |
||||
if (hasManyRelations.length > 1) |
||||
hasManyRelations = lodash.uniqBy(hasManyRelations, function (e) { |
||||
return [e.tn, e.rtn].join(); |
||||
}); |
||||
|
||||
str += hasManyRelations.length ? `\r\n` : ``; |
||||
// cityList in Country
|
||||
for (let i = 0; i < hasManyRelations.length; ++i) { |
||||
let childTable = inflection.camelize(hasManyRelations[i]._tn) |
||||
str += `\t\t${childTable}List: [${childTable}]\r\n`; |
||||
strWhere += `\t\t${childTable}List: Condition${childTable}\r\n`; |
||||
str += `\t\t${childTable}Count: Int\r\n`; |
||||
} |
||||
|
||||
str+= this.generateManyToManyTypeProps(args); |
||||
|
||||
let belongsToRelations = args.relations.filter(r => r.tn === args.tn); |
||||
if (belongsToRelations.length > 1) |
||||
belongsToRelations = lodash.uniqBy(belongsToRelations, function (e) { |
||||
return [e.tn, e.rtn].join(); |
||||
}); |
||||
|
||||
str += belongsToRelations.length ? `\r\n` : ``; |
||||
// Country withi city - this is reverse
|
||||
for (let i = 0; i < belongsToRelations.length; ++i) { |
||||
let parentTable = inflection.camelize(belongsToRelations[i]._rtn) |
||||
str += `\t\t${parentTable}Read(id:String): ${parentTable}\r\n`; |
||||
strWhere += `\t\t${parentTable}Read: Condition${parentTable}\r\n`; |
||||
} |
||||
|
||||
str += `\t}\r\n` |
||||
|
||||
|
||||
const grpFields = Object.assign({}, GROUPBY_DEFAULT_COLS); |
||||
|
||||
str += `type ${args.tn_camelize}GroupBy { \r\n` |
||||
for (let i = 0; i < args.columns.length; ++i) { |
||||
if (args.columns[i]._cn in grpFields) { |
||||
grpFields[args.columns[i]._cn] = `\t\t# ${args.columns[i]._cn} - clashes with column in table\r\n`; |
||||
} else { |
||||
str += `\t\t${args.columns[i]._cn}: ${this._getGraphqlType(args.columns[i])},\r\n`; |
||||
} |
||||
} |
||||
str += Object.values(grpFields).join(''); |
||||
str += `\t}\r\n` |
||||
|
||||
const aggFields = Object.assign({}, AGG_DEFAULT_COLS); |
||||
|
||||
str += `type ${args.tn_camelize}Aggregate { \r\n` |
||||
for (let i = 0; i < args.columns.length; ++i) { |
||||
if (args.columns[i]._cn in aggFields) { |
||||
aggFields[args.columns[i]._cn] = `\t\t# ${args.columns[i]._cn} - clashes with column in table\r\n`; |
||||
} else { |
||||
str += `\t\t${args.columns[i]._cn}: ${this._getGraphqlType(args.columns[i])},\r\n`; |
||||
} |
||||
} |
||||
|
||||
str += Object.values(aggFields).join(''); |
||||
|
||||
str += `\t}\r\n` |
||||
strWhere += ` |
||||
_or:[Condition${args.tn_camelize}] |
||||
_not:Condition${args.tn_camelize} |
||||
_and:[Condition${args.tn_camelize}] |
||||
|
||||
\t}\r\n` |
||||
|
||||
|
||||
return `${str}\r\n\r\n${strWhere}`; |
||||
} |
||||
*/ |
||||
|
||||
protected _getGraphqlType(columnObj): any { |
||||
switch (columnObj.dt) { |
||||
case 'char': |
||||
case 'nchar': |
||||
case 'nvarchar2': |
||||
case 'varchar2': |
||||
case 'long': |
||||
case 'raw': |
||||
case 'long raw': |
||||
return 'String'; |
||||
break; |
||||
|
||||
case 'number': |
||||
case 'numeric': |
||||
case 'float': |
||||
case 'dec': |
||||
case 'real': |
||||
case 'decimal': |
||||
case 'double precision': |
||||
return 'Float'; |
||||
break; |
||||
case 'integer': |
||||
case 'int': |
||||
case 'smallint': |
||||
return 'Int'; |
||||
break; |
||||
case 'date': |
||||
case 'timestamp': |
||||
case 'timestamp with time zone': |
||||
case 'timestamp with local time zone': |
||||
case 'interval year to month': |
||||
case 'interval day to second': |
||||
case 'bfile': |
||||
case 'blob': |
||||
case 'clob': |
||||
case 'nclob': |
||||
return 'String'; |
||||
break; |
||||
case 'rowid': |
||||
case 'urowid': |
||||
return 'Int'; |
||||
break; |
||||
default: |
||||
return 'String'; |
||||
break; |
||||
} |
||||
} |
||||
|
||||
protected _getGraphqlConditionType(columnObj): any { |
||||
switch (this._getGraphqlType(columnObj.dt)) { |
||||
case 'Int': |
||||
return 'ConditionInt'; |
||||
case 'Float': |
||||
return 'ConditionFloat'; |
||||
case 'Boolean': |
||||
return 'ConditionBoolean'; |
||||
case 'String': |
||||
return 'ConditionString'; |
||||
case '[String]': |
||||
return 'ConditionString'; |
||||
} |
||||
} |
||||
/*getString(){ |
||||
return this._renderColumns(this.ctx); |
||||
}*/ |
||||
} |
||||
|
||||
export default GqlXcSchemaOracle; |
@ -1,325 +0,0 @@
|
||||
import BaseGqlXcTsSchema from './BaseGqlXcTsSchema'; |
||||
|
||||
class GqlXcSchemaPg extends BaseGqlXcTsSchema { |
||||
/** |
||||
* |
||||
* @param dir |
||||
* @param filename |
||||
* @param ct |
||||
* @param ctx.tn |
||||
* @param ctx.columns |
||||
* @param ctx.relations |
||||
*/ |
||||
constructor({ dir, filename, ctx }) { |
||||
super({ dir, filename, ctx }); |
||||
} |
||||
|
||||
/* /!** |
||||
* |
||||
* @param args |
||||
* @param args.columns |
||||
* @param args.relations |
||||
* @returns {string} |
||||
* @private |
||||
*!/ |
||||
_renderColumns(args) { |
||||
|
||||
let str = ''; |
||||
|
||||
str += ` |
||||
${this._getInputType(args)}\r\n |
||||
${this._getQuery(args)},\r\n |
||||
${this._getMutation(args)}\r\n |
||||
${this._getType(args)}\r\n |
||||
` |
||||
|
||||
str += ''; |
||||
|
||||
return str; |
||||
|
||||
}*/ |
||||
|
||||
/* _getInputType(args) { |
||||
let str = `input ${args.tn_camelize}Input { \r\n` |
||||
for (let i = 0; i < args.columns.length; ++i) { |
||||
if (args.columns[i]._cn.split(' ').length > 1) { |
||||
console.log(`Skipping ${args.tn}.${args.columns[i]._cn}`); |
||||
} else { |
||||
str += `\t\t${args.columns[i]._cn.replace(/ /g, '_')}: ${this._getGraphqlType(args.columns[i])},\r\n`; |
||||
} |
||||
|
||||
} |
||||
str += `\t}`; |
||||
return str; |
||||
}*/ |
||||
|
||||
/* _getQuery(args) { |
||||
let str = `type Query { \r\n` |
||||
str += `\t\t${args.tn_camelize}List(where: String,condition:Condition${args.tn_camelize}, limit: Int, offset: Int, sort: String): [${args.tn_camelize}]\r\n` |
||||
str += `\t\t${args.tn_camelize}Read(id:String!): ${args.tn_camelize}\r\n` |
||||
str += `\t\t${args.tn_camelize}Exists(id: String!): Boolean\r\n` |
||||
str += `\t\t${args.tn_camelize}FindOne(where: String,condition:Condition${args.tn_camelize}): ${args.tn_camelize}\r\n` |
||||
str += `\t\t${args.tn_camelize}Count(where: String,condition:Condition${args.tn_camelize}): Int\r\n` |
||||
str += `\t\t${args.tn_camelize}Distinct(column_name: String, where: String,condition:Condition${args.tn_camelize}, limit: Int, offset: Int, sort: String): [${args.tn_camelize}]\r\n` |
||||
str += `\t\t${args.tn_camelize}GroupBy(fields: String, having: String, limit: Int, offset: Int, sort: String): [${args.tn_camelize}GroupBy]\r\n` |
||||
str += `\t\t${args.tn_camelize}Aggregate(column_name: String!, having: String, limit: Int, offset: Int, sort: String, func: String!): [${args.tn_camelize}Aggregate]\r\n` |
||||
str += `\t\t${args.tn_camelize}Distribution(min: Int, max: Int, step: Int, steps: String, column_name: String!): [distribution]\r\n` |
||||
str += `\t}\r\n` |
||||
return str; |
||||
}*/ |
||||
|
||||
/* _getMutation(args) { |
||||
let str = `type Mutation { \r\n` |
||||
str += `\t\t${args.tn_camelize}Create(data:${args.tn_camelize}Input): ${args.tn_camelize}\r\n` |
||||
str += `\t\t${args.tn_camelize}Update(id:String,data:${args.tn_camelize}Input): Int\r\n` //${args.tn_camelize}\r\n`
|
||||
str += `\t\t${args.tn_camelize}Delete(id:String): Int\r\n`//${args.tn_camelize}\r\n`
|
||||
str += `\t\t${args.tn_camelize}CreateBulk(data: [${args.tn_camelize}Input]): [Int]\r\n` |
||||
str += `\t\t${args.tn_camelize}UpdateBulk(data: [${args.tn_camelize}Input]): [Int]\r\n` |
||||
str += `\t\t${args.tn_camelize}DeleteBulk(data: [${args.tn_camelize}Input]): [Int]\r\n` |
||||
str += `\t},\r\n` |
||||
return str; |
||||
}*/ |
||||
|
||||
/* _getType(args) { |
||||
|
||||
let str = `type ${args.tn_camelize} { \r\n` |
||||
let strWhere = `input Condition${args.tn_camelize} { \r\n` |
||||
|
||||
for (let i = 0; i < args.columns.length; ++i) { |
||||
if (args.columns[i]._cn.split(' ').length > 1) { |
||||
console.log(`Skipping ${args.tn}.${args.columns[i]._cn}`); |
||||
} else { |
||||
str += `\t\t${args.columns[i]._cn.replace(/ /g, '_')}: ${this._getGraphqlType(args.columns[i])},\r\n`; |
||||
strWhere += `\t\t${args.columns[i]._cn.replace(/ /g, '_')}: ${this._getGraphqlConditionType(args.columns[i])},\r\n`; |
||||
} |
||||
|
||||
} |
||||
|
||||
let hasManyRelations = args.relations.filter(r => r.rtn === args.tn); |
||||
if (hasManyRelations.length > 1) |
||||
hasManyRelations = lodash.uniqBy(hasManyRelations, function (e) { |
||||
return [e.tn, e.rtn].join(); |
||||
}); |
||||
|
||||
str += hasManyRelations.length ? `\r\n` : ``; |
||||
// cityList in Country
|
||||
for (let i = 0; i < hasManyRelations.length; ++i) { |
||||
let childTable = inflection.camelize(hasManyRelations[i]._tn) |
||||
str += `\t\t${childTable}List: [${childTable}]\r\n`; |
||||
strWhere += `\t\t${childTable}List: Condition${childTable}\r\n`; |
||||
str += `\t\t${childTable}Count: Int\r\n`; |
||||
} |
||||
|
||||
|
||||
str+= this.generateManyToManyTypeProps(args); |
||||
|
||||
let belongsToRelations = args.relations.filter(r => r.tn === args.tn); |
||||
if (belongsToRelations.length > 1) |
||||
belongsToRelations = lodash.uniqBy(belongsToRelations, function (e) { |
||||
return [e.tn, e.rtn].join(); |
||||
}); |
||||
|
||||
str += belongsToRelations.length ? `\r\n` : ``; |
||||
// Country withi city - this is reverse
|
||||
for (let i = 0; i < belongsToRelations.length; ++i) { |
||||
let parentTable = inflection.camelize(belongsToRelations[i]._rtn) |
||||
str += `\t\t${parentTable}Read(id:String): ${parentTable}\r\n`; |
||||
strWhere += `\t\t${parentTable}Read: Condition${parentTable}\r\n`; |
||||
} |
||||
|
||||
str += `\t}\r\n` |
||||
|
||||
const grpFields = Object.assign({}, GROUPBY_DEFAULT_COLS); |
||||
|
||||
str += `type ${args.tn_camelize}GroupBy { \r\n` |
||||
for (let i = 0; i < args.columns.length; ++i) { |
||||
if (args.columns[i]._cn in grpFields) { |
||||
grpFields[args.columns[i]._cn] = `\t\t# ${args.columns[i]._cn} - clashes with column in table\r\n`; |
||||
} else { |
||||
str += `\t\t${args.columns[i]._cn.replace(/ /g, '_')}: ${this._getGraphqlType(args.columns[i])},\r\n`; |
||||
} |
||||
} |
||||
str += Object.values(grpFields).join(''); |
||||
str += `\t}\r\n` |
||||
|
||||
const aggFields = Object.assign({}, AGG_DEFAULT_COLS); |
||||
|
||||
str += `type ${args.tn_camelize}Aggregate { \r\n` |
||||
for (let i = 0; i < args.columns.length; ++i) { |
||||
if (args.columns[i]._cn in aggFields) { |
||||
aggFields[args.columns[i]._cn] = `\t\t# ${args.columns[i]._cn} - clashes with column in table\r\n`; |
||||
} else { |
||||
str += `\t\t${args.columns[i]._cn.replace(/ /g, '_')}: ${this._getGraphqlType(args.columns[i])},\r\n`; |
||||
} |
||||
} |
||||
str += Object.values(aggFields).join(''); |
||||
|
||||
str += `\t}\r\n` |
||||
strWhere += ` |
||||
_or:[Condition${args.tn_camelize}] |
||||
_not:Condition${args.tn_camelize} |
||||
_and:[Condition${args.tn_camelize}] |
||||
|
||||
\t}\r\n` |
||||
|
||||
|
||||
return `${str}\r\n\r\n${strWhere}`; |
||||
}*/ |
||||
|
||||
_getGraphqlType(columnObj) { |
||||
switch (columnObj.dt) { |
||||
case 'int': |
||||
case 'integer': |
||||
case 'bigint': |
||||
case 'bigserial': |
||||
case 'char': |
||||
case 'int2': |
||||
case 'int4': |
||||
case 'int8': |
||||
case 'int4range': |
||||
case 'int8range': |
||||
case 'serial': |
||||
case 'serial2': |
||||
case 'smallint': |
||||
case 'smallserial': |
||||
case 'serial8': |
||||
if (columnObj.dtx === 'ARRAY') { |
||||
return '[Int]'; |
||||
} |
||||
return 'Int'; |
||||
break; |
||||
|
||||
case 'bit': |
||||
case 'bool': |
||||
case 'boolean': |
||||
if (columnObj.dtx === 'ARRAY') { |
||||
return '[Boolean]'; |
||||
} |
||||
return 'Boolean'; |
||||
break; |
||||
|
||||
case 'money': |
||||
case 'real': |
||||
case 'float4': |
||||
case 'float8': |
||||
if (columnObj.dtx === 'ARRAY') { |
||||
return '[Float]'; |
||||
} |
||||
return 'Float'; |
||||
break; |
||||
|
||||
case 'json': |
||||
case 'jsonb': |
||||
case 'anyenum': |
||||
case 'anynonarray': |
||||
case 'path': |
||||
case 'point': |
||||
case 'polygon': |
||||
if (columnObj.dtx === 'ARRAY') { |
||||
return '[JSON]'; |
||||
} |
||||
return 'JSON'; |
||||
|
||||
case 'character': |
||||
case 'uuid': |
||||
case 'date': |
||||
case 'double precision': |
||||
case 'event_trigger': |
||||
case 'fdw_handler': |
||||
case 'character varying': |
||||
case 'text': |
||||
case 'time': |
||||
case 'time without time zone': |
||||
case 'timestamp': |
||||
case 'timestamp without time zone': |
||||
case 'timestamptz': |
||||
case 'timestamp with time zone': |
||||
case 'timetz': |
||||
case 'time with time zone': |
||||
case 'daterange': |
||||
case 'gtsvector': |
||||
case 'index_am_handler': |
||||
case 'anyrange': |
||||
case 'box': |
||||
case 'bpchar': |
||||
case 'bytea': |
||||
case 'cid': |
||||
case 'cidr': |
||||
case 'circle': |
||||
case 'cstring': |
||||
case 'inet': |
||||
case 'internal': |
||||
case 'interval': |
||||
case 'language_handler': |
||||
case 'line': |
||||
case 'lsec': |
||||
case 'macaddr': |
||||
case 'name': |
||||
case 'numeric': |
||||
case 'numrange': |
||||
case 'oid': |
||||
case 'opaque': |
||||
case 'pg_ddl_command': |
||||
case 'pg_lsn': |
||||
case 'pg_node_tree': |
||||
case 'record': |
||||
case 'refcursor': |
||||
case 'regclass': |
||||
case 'regconfig': |
||||
case 'regdictionary': |
||||
case 'regnamespace': |
||||
case 'regoper': |
||||
case 'regoperator': |
||||
case 'regproc': |
||||
case 'regpreocedure': |
||||
case 'regrole': |
||||
case 'regtype': |
||||
case 'reltime': |
||||
case 'smgr': |
||||
case 'tid': |
||||
case 'tinterval': |
||||
case 'trigger': |
||||
case 'tsm_handler': |
||||
case 'tsquery': |
||||
case 'tsrange': |
||||
case 'tstzrange': |
||||
case 'tsvector': |
||||
case 'txid_snapshot': |
||||
case 'unknown': |
||||
case 'void': |
||||
case 'xid': |
||||
case 'xml': |
||||
default: |
||||
if (columnObj.dtx === 'ARRAY') { |
||||
return '[String]'; |
||||
} |
||||
return 'String'; |
||||
break; |
||||
} |
||||
} |
||||
|
||||
protected _getGraphqlConditionType(columnObj): any { |
||||
switch (this._getGraphqlType(columnObj.dt)) { |
||||
case 'Int': |
||||
return 'ConditionInt'; |
||||
case 'Float': |
||||
return 'ConditionFloat'; |
||||
case 'Boolean': |
||||
return 'ConditionBoolean'; |
||||
case 'String': |
||||
return 'ConditionString'; |
||||
case '[String]': |
||||
return 'ConditionString'; |
||||
case '[JSON]': |
||||
return 'ConditionString'; |
||||
case 'JSON': |
||||
return 'ConditionString'; |
||||
} |
||||
} |
||||
|
||||
/* getString(){ |
||||
return this._renderColumns(this.ctx); |
||||
}*/ |
||||
} |
||||
|
||||
export default GqlXcSchemaPg; |
@ -1,231 +0,0 @@
|
||||
import BaseGqlXcTsSchema from './BaseGqlXcTsSchema'; |
||||
|
||||
class GqlXcSchemaSqlite extends BaseGqlXcTsSchema { |
||||
/** |
||||
* |
||||
* @param dir |
||||
* @param filename |
||||
* @param ct |
||||
* @param ctx.tn |
||||
* @param ctx.columns |
||||
* @param ctx.relations |
||||
*/ |
||||
constructor({ dir, filename, ctx }) { |
||||
super({ dir, filename, ctx }); |
||||
} |
||||
|
||||
/*/!** |
||||
* |
||||
* @param args |
||||
* @param args.columns |
||||
* @param args.relations |
||||
* @returns {string} |
||||
* @private |
||||
*!/ |
||||
public _renderColumns(args): string { |
||||
|
||||
let str = ''; |
||||
|
||||
str += ` |
||||
${this._getInputType(args)}\r\n |
||||
${this._getQuery(args)},\r\n |
||||
${this._getMutation(args)}\r\n |
||||
${this._getType(args)}\r\n |
||||
` |
||||
|
||||
str += ''; |
||||
|
||||
return str; |
||||
|
||||
}*/ |
||||
|
||||
protected _getGraphqlType(columnObj): any { |
||||
switch (columnObj.dt) { |
||||
case 'int': |
||||
case 'integer': |
||||
case 'tinyint': |
||||
case 'smallint': |
||||
case 'mediumint': |
||||
case 'bigint': |
||||
case 'int2': |
||||
case 'int8': |
||||
return 'Int'; |
||||
break; |
||||
|
||||
case 'character': |
||||
case 'blob sub_type text': |
||||
case 'blob': |
||||
return 'String'; |
||||
break; |
||||
|
||||
case 'real': |
||||
case 'double': |
||||
case 'double precision': |
||||
case 'float': |
||||
case 'numeric': |
||||
return 'Float'; |
||||
break; |
||||
|
||||
case 'boolean': |
||||
return 'Boolean'; |
||||
break; |
||||
|
||||
case 'date': |
||||
case 'datetime': |
||||
case 'text': |
||||
case 'varchar': |
||||
case 'timestamp': |
||||
return 'String'; |
||||
break; |
||||
|
||||
default: |
||||
return 'String'; |
||||
break; |
||||
} |
||||
} |
||||
|
||||
protected _getGraphqlConditionType(columnObj): any { |
||||
switch (this._getGraphqlType(columnObj.dt)) { |
||||
case 'Int': |
||||
return 'ConditionInt'; |
||||
case 'Float': |
||||
return 'ConditionFloat'; |
||||
case 'Boolean': |
||||
return 'ConditionBoolean'; |
||||
case 'String': |
||||
return 'ConditionString'; |
||||
case '[String]': |
||||
return 'ConditionString'; |
||||
} |
||||
} |
||||
|
||||
/* |
||||
public getString(): string { |
||||
return this._renderColumns(this.ctx); |
||||
} |
||||
*/ |
||||
/* |
||||
protected _getInputType(args): string { |
||||
let str = `input ${args.tn_camelize}Input { \r\n` |
||||
for (const column of args.columns) { |
||||
if (column._cn.split(' ').length > 1) { |
||||
// str += `\t\t${column._cn}: ${this._getGraphqlType(column)},\r\n`;
|
||||
} else { |
||||
str += `\t\t${column._cn}: ${this._getGraphqlType(column)},\r\n`; |
||||
} |
||||
} |
||||
str += `\t}`; |
||||
return str; |
||||
} |
||||
|
||||
protected _getQuery(args): string { |
||||
let str = `type Query { \r\n` |
||||
str += `\t\t${args.tn_camelize}List(where: String,condition:Condition${args.tn_camelize}, limit: Int, offset: Int, sort: String): [${args.tn_camelize}]\r\n` |
||||
str += `\t\t${args.tn_camelize}Read(id:String!): ${args.tn_camelize}\r\n` |
||||
str += `\t\t${args.tn_camelize}Exists(id: String!): Boolean\r\n` |
||||
str += `\t\t${args.tn_camelize}FindOne(where: String,condition:Condition${args.tn_camelize}): ${args.tn_camelize}\r\n` |
||||
str += `\t\t${args.tn_camelize}Count(where: String,condition:Condition${args.tn_camelize}): Int\r\n` |
||||
str += `\t\t${args.tn_camelize}Distinct(column_name: String, where: String,condition:Condition${args.tn_camelize}, limit: Int, offset: Int, sort: String): [${args.tn_camelize}]\r\n` |
||||
str += `\t\t${args.tn_camelize}GroupBy(fields: String, having: String, limit: Int, offset: Int, sort: String): [${args.tn_camelize}GroupBy]\r\n` |
||||
str += `\t\t${args.tn_camelize}Aggregate(column_name: String!, having: String, limit: Int, offset: Int, sort: String, func: String!): [${args.tn_camelize}Aggregate]\r\n` |
||||
str += `\t\t${args.tn_camelize}Distribution(min: Int, max: Int, step: Int, steps: String, column_name: String!): [distribution]\r\n` |
||||
str += `\t}\r\n` |
||||
return str; |
||||
} |
||||
|
||||
protected _getMutation(args): string { |
||||
let str = `type Mutation { \r\n` |
||||
str += `\t\t${args.tn_camelize}Create(data:${args.tn_camelize}Input): ${args.tn_camelize}\r\n` |
||||
str += `\t\t${args.tn_camelize}Update(id:String,data:${args.tn_camelize}Input): Int\r\n` // ${args.tn_camelize}\r\n`
|
||||
str += `\t\t${args.tn_camelize}Delete(id:String): Int\r\n`// ${args.tn_camelize}\r\n`
|
||||
str += `\t\t${args.tn_camelize}CreateBulk(data: [${args.tn_camelize}Input]): [Int]\r\n` |
||||
str += `\t\t${args.tn_camelize}UpdateBulk(data: [${args.tn_camelize}Input]): [Int]\r\n` |
||||
str += `\t\t${args.tn_camelize}DeleteBulk(data: [${args.tn_camelize}Input]): [Int]\r\n` |
||||
str += `\t},\r\n` |
||||
return str; |
||||
} |
||||
|
||||
protected _getType(args): string { |
||||
|
||||
let str = `type ${args.tn_camelize} { \r\n` |
||||
let strWhere = `input Condition${args.tn_camelize} { \r\n` |
||||
|
||||
for (const column of args.columns.length) { |
||||
str += `\t\t${column._cn}: ${this._getGraphqlType(column)},\r\n`; |
||||
strWhere += `\t\t${column._cn.replace(/ /g, '_')}: ${this._getGraphqlConditionType(column)},\r\n`; |
||||
} |
||||
|
||||
let hasManyRelations = args.relations.filter(r => r.rtn === args.tn); |
||||
if (hasManyRelations.length > 1) { |
||||
hasManyRelations = lodash.uniqBy(hasManyRelations, (e) => { |
||||
return [e.tn, e.rtn].join(); |
||||
}); |
||||
} |
||||
str += hasManyRelations.length ? `\r\n` : ``; |
||||
// cityList in Country
|
||||
for (const {_tn} of hasManyRelations.length) { |
||||
const childTable = inflection.camelize(_tn) |
||||
str += `\t\t${childTable}List: [${childTable}]\r\n`; |
||||
strWhere += `\t\t${childTable}List: Condition${childTable}\r\n`; |
||||
str += `\t\t${childTable}Count: Int\r\n`; |
||||
} |
||||
|
||||
str += this.generateManyToManyTypeProps(args); |
||||
|
||||
let belongsToRelations = args.relations.filter(r => r.tn === args.tn); |
||||
if (belongsToRelations.length > 1) { |
||||
belongsToRelations = lodash.uniqBy(belongsToRelations, (e) => { |
||||
return [e.tn, e.rtn].join(); |
||||
}); |
||||
} |
||||
|
||||
str += belongsToRelations.length ? `\r\n` : ``; |
||||
// Country withi city - this is reverse
|
||||
for (const {_rtn} of belongsToRelations.length) { |
||||
const parentTable = inflection.camelize(_rtn) |
||||
str += `\t\t${parentTable}Read(id:String): ${parentTable}\r\n`; |
||||
strWhere += `\t\t${parentTable}Read: Condition${parentTable}\r\n`; |
||||
} |
||||
|
||||
str += `\t}\r\n` |
||||
|
||||
const grpFields = {...GROUPBY_DEFAULT_COLS}; |
||||
|
||||
str += `type ${args.tn_camelize}GroupBy { \r\n` |
||||
for (let i = 0; i < args.columns.length; ++i) { |
||||
if (args.columns[i]._cn in grpFields) { |
||||
grpFields[args.columns[i]._cn] = `\t\t# ${args.columns[i]._cn} - clashes with column in table\r\n`; |
||||
} else { |
||||
str += `\t\t${args.columns[i]._cn}: ${this._getGraphqlType(args.columns[i])},\r\n`; |
||||
} |
||||
} |
||||
str += Object.values(grpFields).join(''); |
||||
str += `\t}\r\n`; |
||||
|
||||
const aggFields = {...AGG_DEFAULT_COLS}; |
||||
|
||||
str += `type ${args.tn_camelize}Aggregate { \r\n` |
||||
for (let i = 0; i < args.columns.length; ++i) { |
||||
if (args.columns[i]._cn in aggFields) { |
||||
aggFields[args.columns[i]._cn] = `\t\t# ${args.columns[i]._cn} - clashes with column in table\r\n`; |
||||
} else { |
||||
str += `\t\t${args.columns[i]._cn}: ${this._getGraphqlType(args.columns[i])},\r\n`; |
||||
} |
||||
} |
||||
|
||||
str += Object.values(aggFields).join(''); |
||||
|
||||
str += `\t}\r\n` |
||||
strWhere += ` |
||||
_or:[Condition${args.tn_camelize}] |
||||
_not:Condition${args.tn_camelize} |
||||
_and:[Condition${args.tn_camelize}] |
||||
|
||||
\t}\r\n` |
||||
|
||||
|
||||
return `${str}\r\n\r\n${strWhere}`; |
||||
}*/ |
||||
} |
||||
|
||||
export default GqlXcSchemaSqlite; |
@ -1,13 +0,0 @@
|
||||
const AGG_DEFAULT_COLS = { |
||||
count: `\t\tcount: Int,\r\n`, |
||||
avg: `\t\tavg: Float,\r\n`, |
||||
min: `\t\tmin: Float,\r\n`, |
||||
max: `\t\tmax: Int,\r\n`, |
||||
sum: `\t\tsum: Float\r\n`, |
||||
}; |
||||
|
||||
const GROUPBY_DEFAULT_COLS = { |
||||
count: `\t\tcount: Int,\r\n`, |
||||
}; |
||||
|
||||
export { AGG_DEFAULT_COLS, GROUPBY_DEFAULT_COLS }; |
@ -1,788 +0,0 @@
|
||||
import BaseRender from '../../BaseRender'; |
||||
import SwaggerTypes from './SwaggerTypes'; |
||||
|
||||
class SwaggerXc extends BaseRender { |
||||
/** |
||||
* |
||||
* @param dir |
||||
* @param filename |
||||
* @param ct |
||||
* @param ctx.tn |
||||
* @param ctx.columns |
||||
* @param ctx.relations |
||||
*/ |
||||
constructor({ dir = '', filename = '', ctx }: any) { |
||||
super({ dir, filename, ctx }); |
||||
} |
||||
|
||||
/** |
||||
* Prepare variables used in code template |
||||
*/ |
||||
prepare() { |
||||
let data: any = {}; |
||||
|
||||
/* run of simple variable */ |
||||
data = this.ctx; |
||||
data.paths = {}; |
||||
|
||||
data.definitions = { |
||||
func: this._renderDefinitions.bind(this), |
||||
args: { |
||||
tn: this.ctx.tn, |
||||
columns: this.ctx.columns, |
||||
relations: this.ctx.relations, |
||||
dbType: this.ctx.dbType, |
||||
}, |
||||
}; |
||||
|
||||
return data; |
||||
} |
||||
|
||||
/** |
||||
* |
||||
* @param args |
||||
* @param args.columns |
||||
* @param args.relations |
||||
* @returns {string} |
||||
* @private |
||||
*/ |
||||
_renderDefinitions(args) { |
||||
const obj = this.getDefenitions(args); |
||||
|
||||
return JSON.stringify(obj); |
||||
} |
||||
|
||||
getDefenitions(args) { |
||||
const obj = { |
||||
[args._tn]: { |
||||
type: 'object', |
||||
properties: {}, |
||||
}, |
||||
[`${args._tn}Nested`]: { |
||||
type: 'object', |
||||
properties: {}, |
||||
}, |
||||
}; |
||||
|
||||
let properties = obj[args._tn].properties; |
||||
|
||||
for (const column of args.columns) { |
||||
const field: any = {}; |
||||
|
||||
SwaggerTypes.setSwaggerType(column, field, args.dbType); |
||||
|
||||
if (column.rqd) { |
||||
field.nullable = false; |
||||
} |
||||
|
||||
if (column.ai) { |
||||
field.readOnly = true; |
||||
} |
||||
|
||||
properties[column._cn] = field; |
||||
} |
||||
|
||||
properties = Object.assign(obj[`${args._tn}Nested`].properties, properties); |
||||
for (const column of args.v || []) { |
||||
const field: any = {}; |
||||
field.readOnly = true; |
||||
let _cn = column._cn; |
||||
|
||||
if (column.mm) { |
||||
field.type = 'array'; |
||||
field.items = { |
||||
$ref: `#/definitions/${column.mm?._rtn}`, |
||||
}; |
||||
_cn = `${column.mm?._rtn}MMList`; |
||||
} else if (column.hm) { |
||||
field.type = 'array'; |
||||
field.items = { |
||||
$ref: `#/definitions/${column.hm?._tn}`, |
||||
}; |
||||
field.$ref = `#/definitions/${column.hm?._tn}`; |
||||
_cn = `${column.hm?._tn}List`; |
||||
} else if (column.bt) { |
||||
field.$ref = `#/definitions/${column.bt?._rtn}`; |
||||
_cn = `${column.bt?._rtn}Read`; |
||||
} |
||||
|
||||
properties[_cn] = field; |
||||
} |
||||
|
||||
return obj; |
||||
} |
||||
|
||||
getObject() { |
||||
return { |
||||
tags: [ |
||||
{ |
||||
name: `${this.ctx._tn}`, |
||||
description: `Everything about your ${this.ctx._tn}`, |
||||
}, |
||||
], |
||||
paths: { |
||||
[`/nc/${this.ctx.base_id}/api/${this.ctx.routeVersionLetter}/${this.ctx._tn}`]: |
||||
{ |
||||
post: { |
||||
tags: [`${this.ctx._tn}`], |
||||
summary: `Add a new ${this.ctx._tn}`, |
||||
description: '', |
||||
operationId: `add${this.ctx._tn}`, |
||||
consumes: ['application/json'], |
||||
produces: ['application/json'], |
||||
parameters: [ |
||||
{ |
||||
in: 'body', |
||||
name: 'body', |
||||
description: `${this.ctx._tn} object that needs to add`, |
||||
required: true, |
||||
schema: { |
||||
$ref: `#/definitions/${this.ctx._tn}`, |
||||
}, |
||||
}, |
||||
], |
||||
responses: { |
||||
'405': { |
||||
description: 'Invalid input', |
||||
}, |
||||
}, |
||||
}, |
||||
get: { |
||||
tags: [`${this.ctx._tn}`], |
||||
summary: 'Get list', |
||||
description: '', |
||||
operationId: `get${this.ctx._tn}`, |
||||
consumes: ['application/json'], |
||||
produces: ['application/json'], |
||||
parameters: [ |
||||
{ |
||||
in: 'query', |
||||
name: 'fields', |
||||
type: 'string', |
||||
description: 'Comma separated fields from the model', |
||||
}, |
||||
{ |
||||
in: 'query', |
||||
name: 'bt', |
||||
type: 'string', |
||||
description: 'Comma separated parent table names(Belongs To)', |
||||
}, |
||||
{ |
||||
in: 'query', |
||||
name: 'hm', |
||||
type: 'string', |
||||
description: 'Comma separated child table names(Has Many)', |
||||
}, |
||||
{ |
||||
in: 'query', |
||||
name: 'mm', |
||||
type: 'string', |
||||
description: |
||||
'Comma separated child table names(Many to Many)', |
||||
}, |
||||
{ |
||||
in: 'query', |
||||
name: 'where', |
||||
type: 'string', |
||||
description: 'Where expression', |
||||
}, |
||||
{ |
||||
in: 'query', |
||||
name: 'limit', |
||||
description: 'Page size limit', |
||||
type: 'integer', |
||||
format: 'int64', |
||||
}, |
||||
{ |
||||
in: 'query', |
||||
name: 'offset', |
||||
description: 'Pagination offset', |
||||
type: 'integer', |
||||
format: 'int64', |
||||
}, |
||||
{ |
||||
in: 'query', |
||||
name: 'sort', |
||||
description: 'Comma separated sort fields', |
||||
type: 'string', |
||||
}, |
||||
], |
||||
responses: { |
||||
'405': { |
||||
description: 'Invalid input', |
||||
}, |
||||
'200': { |
||||
description: 'successful operation', |
||||
schema: { |
||||
type: 'array', |
||||
items: { |
||||
$ref: `#/definitions/${this.ctx._tn}Nested`, |
||||
}, |
||||
}, |
||||
}, |
||||
}, |
||||
}, |
||||
}, |
||||
[`/nc/${this.ctx.base_id}/api/${this.ctx.routeVersionLetter}/${this.ctx._tn}/{${this.ctx._tn}Id}`]: |
||||
{ |
||||
get: { |
||||
tags: [`${this.ctx._tn}`], |
||||
summary: `Find ${this.ctx._tn} by ID`, |
||||
description: `Returns a single ${this.ctx._tn}`, |
||||
operationId: `get${this.ctx._tn}ById`, |
||||
produces: ['application/json'], |
||||
parameters: [ |
||||
{ |
||||
name: `${this.ctx._tn}Id`, |
||||
in: 'path', |
||||
description: `ID of ${this.ctx._tn} to return. In case of composite key provide keys separated by ___`, |
||||
required: true, |
||||
type: 'string', |
||||
}, |
||||
{ |
||||
in: 'query', |
||||
name: 'bt', |
||||
type: 'string', |
||||
description: 'Comma separated parent table names(Belongs To)', |
||||
}, |
||||
{ |
||||
in: 'query', |
||||
name: 'hm', |
||||
type: 'string', |
||||
description: 'Comma separated child table names(Has Many)', |
||||
}, |
||||
{ |
||||
in: 'query', |
||||
name: 'mm', |
||||
type: 'string', |
||||
description: |
||||
'Comma separated child table names(Many to Many)', |
||||
}, |
||||
], |
||||
responses: { |
||||
'200': { |
||||
description: 'successful operation', |
||||
schema: { |
||||
$ref: `#/definitions/${this.ctx._tn}Nested`, |
||||
}, |
||||
}, |
||||
'400': { |
||||
description: 'Invalid ID supplied', |
||||
}, |
||||
'404': { |
||||
description: `${this.ctx._tn} not found`, |
||||
}, |
||||
}, |
||||
}, |
||||
put: { |
||||
tags: [`${this.ctx._tn}`], |
||||
summary: `Updates a ${this.ctx._tn}`, |
||||
description: '', |
||||
operationId: `update${this.ctx._tn}`, |
||||
consumes: ['application/json'], |
||||
produces: ['application/json'], |
||||
parameters: [ |
||||
{ |
||||
name: `${this.ctx._tn}Id`, |
||||
in: 'path', |
||||
description: `ID of ${this.ctx._tn} to return. In case of composite key provide keys separated by ___`, |
||||
required: true, |
||||
type: 'string', |
||||
}, |
||||
{ |
||||
in: 'body', |
||||
name: 'body', |
||||
description: `${this.ctx._tn} object that needs to be added to the store`, |
||||
required: true, |
||||
schema: { |
||||
$ref: `#/definitions/${this.ctx._tn}`, |
||||
}, |
||||
}, |
||||
], |
||||
responses: { |
||||
'405': { |
||||
description: 'Invalid input', |
||||
}, |
||||
}, |
||||
}, |
||||
delete: { |
||||
tags: [`${this.ctx._tn}`], |
||||
summary: `Deletes a ${this.ctx._tn}`, |
||||
description: '', |
||||
operationId: `delete${this.ctx._tn}`, |
||||
produces: ['application/json'], |
||||
parameters: [ |
||||
{ |
||||
name: `${this.ctx._tn}Id`, |
||||
in: 'path', |
||||
description: `ID of ${this.ctx._tn} to return. In case of composite key provide keys separated by ___`, |
||||
required: true, |
||||
type: 'string', |
||||
}, |
||||
], |
||||
responses: { |
||||
'400': { |
||||
description: 'Invalid ID supplied', |
||||
}, |
||||
'404': { |
||||
description: `${this.ctx._tn} not found`, |
||||
}, |
||||
}, |
||||
}, |
||||
}, |
||||
|
||||
[`/nc/${this.ctx.base_id}/api/${this.ctx.routeVersionLetter}/${this.ctx._tn}/bulk`]: |
||||
{ |
||||
post: { |
||||
tags: [`${this.ctx._tn}`], |
||||
summary: `Bulk ${this.ctx._tn} insert`, |
||||
description: '', |
||||
operationId: `bulk${this.ctx._tn}Insert`, |
||||
consumes: ['application/json'], |
||||
produces: ['application/json'], |
||||
parameters: [ |
||||
{ |
||||
in: 'body', |
||||
name: 'body', |
||||
description: `${this.ctx._tn} objects`, |
||||
required: true, |
||||
schema: { |
||||
type: 'array', |
||||
items: { |
||||
$ref: `#/definitions/${this.ctx._tn}`, |
||||
}, |
||||
}, |
||||
}, |
||||
], |
||||
responses: { |
||||
'405': { |
||||
description: 'Invalid input', |
||||
}, |
||||
}, |
||||
}, |
||||
put: { |
||||
tags: [`${this.ctx._tn}`], |
||||
summary: `Bulk ${this.ctx._tn} update`, |
||||
description: '', |
||||
operationId: `bulk${this.ctx._tn}Update`, |
||||
consumes: ['application/json'], |
||||
produces: ['application/json'], |
||||
parameters: [ |
||||
{ |
||||
in: 'body', |
||||
name: 'body', |
||||
description: `${this.ctx._tn} objects with id`, |
||||
required: true, |
||||
schema: { |
||||
type: 'array', |
||||
items: { |
||||
$ref: `#/definitions/${this.ctx._tn}`, |
||||
}, |
||||
}, |
||||
}, |
||||
], |
||||
responses: { |
||||
'405': { |
||||
description: 'Invalid input', |
||||
}, |
||||
}, |
||||
}, |
||||
delete: { |
||||
tags: [`${this.ctx._tn}`], |
||||
summary: `Bulk ${this.ctx._tn} delete`, |
||||
description: '', |
||||
operationId: `bulk${this.ctx._tn}Delete`, |
||||
produces: ['application/json'], |
||||
parameters: [ |
||||
{ |
||||
in: 'body', |
||||
name: 'body', |
||||
description: `${this.ctx._tn} objects contains id`, |
||||
required: true, |
||||
schema: { |
||||
type: 'array', |
||||
items: { |
||||
$ref: `#/definitions/${this.ctx._tn}`, |
||||
}, |
||||
}, |
||||
}, |
||||
], |
||||
responses: { |
||||
'400': { |
||||
description: 'Invalid ID supplied', |
||||
}, |
||||
'404': { |
||||
description: `${this.ctx._tn} not found`, |
||||
}, |
||||
}, |
||||
}, |
||||
}, |
||||
[`/nc/${this.ctx.base_id}/api/${this.ctx.routeVersionLetter}/${this.ctx._tn}/findOne`]: |
||||
{ |
||||
get: { |
||||
tags: [`${this.ctx._tn}`], |
||||
summary: 'Get first one from filtered data', |
||||
description: '', |
||||
operationId: `findOne${this.ctx._tn}`, |
||||
consumes: ['application/json'], |
||||
produces: ['application/json'], |
||||
parameters: [ |
||||
{ |
||||
in: 'query', |
||||
name: 'fields', |
||||
type: 'string', |
||||
description: 'Comma separated fields from the model', |
||||
}, |
||||
{ |
||||
in: 'query', |
||||
name: 'where', |
||||
type: 'string', |
||||
description: 'Where expression', |
||||
}, |
||||
{ |
||||
in: 'query', |
||||
name: 'limit', |
||||
description: 'Page size limit', |
||||
type: 'integer', |
||||
format: 'int64', |
||||
}, |
||||
{ |
||||
in: 'query', |
||||
name: 'offset', |
||||
description: 'Pagination offset', |
||||
type: 'integer', |
||||
format: 'int64', |
||||
}, |
||||
{ |
||||
in: 'query', |
||||
name: 'sort', |
||||
description: 'Comma separated sort fields', |
||||
type: 'string', |
||||
}, |
||||
], |
||||
responses: { |
||||
'405': { |
||||
description: 'Invalid input', |
||||
}, |
||||
'200': { |
||||
description: 'successful operation', |
||||
schema: { |
||||
$ref: `#/definitions/${this.ctx._tn}`, |
||||
}, |
||||
}, |
||||
}, |
||||
}, |
||||
}, |
||||
[`/nc/${this.ctx.base_id}/api/${this.ctx.routeVersionLetter}/${this.ctx._tn}/{${this.ctx._tn}Id}/exists`]: |
||||
{ |
||||
get: { |
||||
tags: [`${this.ctx._tn}`], |
||||
summary: `Check ${this.ctx._tn} with provided ID exists`, |
||||
description: `Returns a single ${this.ctx._tn}`, |
||||
operationId: `check${this.ctx._tn}Exists`, |
||||
produces: ['application/json'], |
||||
parameters: [ |
||||
{ |
||||
name: `${this.ctx._tn}Id`, |
||||
in: 'path', |
||||
description: `ID of ${this.ctx._tn} to return. In case of composite key provide keys separated by ___`, |
||||
required: true, |
||||
type: 'string', |
||||
}, |
||||
], |
||||
responses: { |
||||
'200': { |
||||
description: 'successful operation', |
||||
schema: { |
||||
type: 'boolean', |
||||
}, |
||||
}, |
||||
}, |
||||
}, |
||||
}, |
||||
[`/nc/${this.ctx.base_id}/api/${this.ctx.routeVersionLetter}/${this.ctx._tn}/count`]: |
||||
{ |
||||
get: { |
||||
tags: [`${this.ctx._tn}`], |
||||
summary: `Get ${this.ctx._tn} count`, |
||||
operationId: `get${this.ctx._tn}Count`, |
||||
consumes: ['application/json'], |
||||
produces: ['application/json'], |
||||
parameters: [ |
||||
{ |
||||
in: 'query', |
||||
name: 'where', |
||||
type: 'string', |
||||
description: 'Where expression', |
||||
}, |
||||
], |
||||
responses: { |
||||
'405': { |
||||
description: 'Invalid input', |
||||
}, |
||||
'200': { |
||||
description: 'successful operation', |
||||
schema: { |
||||
type: 'object', |
||||
}, |
||||
}, |
||||
}, |
||||
}, |
||||
}, |
||||
[`/nc/${this.ctx.base_id}/api/${this.ctx.routeVersionLetter}/${this.ctx._tn}/groupby`]: |
||||
{ |
||||
get: { |
||||
tags: [`${this.ctx._tn}`], |
||||
summary: 'Group by column', |
||||
description: '', |
||||
operationId: `${this.ctx._tn}GroupByColumn`, |
||||
consumes: ['application/json'], |
||||
produces: ['application/json'], |
||||
parameters: [ |
||||
{ |
||||
in: 'query', |
||||
name: 'column_name', |
||||
type: 'string', |
||||
description: 'Column name', |
||||
}, |
||||
{ |
||||
in: 'query', |
||||
name: 'where', |
||||
type: 'string', |
||||
description: 'Where expression', |
||||
}, |
||||
{ |
||||
in: 'query', |
||||
name: 'limit', |
||||
description: 'Page size limit', |
||||
type: 'integer', |
||||
format: 'int64', |
||||
}, |
||||
{ |
||||
in: 'query', |
||||
name: 'offset', |
||||
description: 'Pagination offset', |
||||
type: 'integer', |
||||
format: 'int64', |
||||
}, |
||||
{ |
||||
in: 'query', |
||||
name: 'sort', |
||||
description: 'Comma separated sort fieldst', |
||||
type: 'string', |
||||
}, |
||||
], |
||||
responses: { |
||||
'405': { |
||||
description: 'Invalid input', |
||||
}, |
||||
'200': { |
||||
description: 'successful operation', |
||||
schema: { |
||||
$ref: `#/definitions/${this.ctx._tn}`, |
||||
}, |
||||
}, |
||||
}, |
||||
}, |
||||
}, |
||||
[`/nc/${this.ctx.base_id}/api/${this.ctx.routeVersionLetter}/${this.ctx._tn}/distribution`]: |
||||
{ |
||||
get: { |
||||
tags: [`${this.ctx._tn}`], |
||||
summary: '', |
||||
description: '', |
||||
operationId: `${this.ctx._tn}Distribution`, |
||||
consumes: ['application/json'], |
||||
produces: ['application/json'], |
||||
parameters: [ |
||||
{ |
||||
in: 'query', |
||||
name: 'column_name', |
||||
type: 'string', |
||||
description: 'Column name', |
||||
}, |
||||
{ |
||||
in: 'query', |
||||
name: 'min', |
||||
description: 'min value', |
||||
type: 'integer', |
||||
format: 'int64', |
||||
}, |
||||
{ |
||||
in: 'query', |
||||
name: 'max', |
||||
description: 'max value', |
||||
type: 'integer', |
||||
format: 'int64', |
||||
}, |
||||
{ |
||||
in: 'query', |
||||
name: 'step', |
||||
description: 'step value', |
||||
type: 'integer', |
||||
format: 'int64', |
||||
}, |
||||
{ |
||||
in: 'query', |
||||
name: 'steps', |
||||
description: 'steps value', |
||||
type: 'integer', |
||||
format: 'int64', |
||||
}, |
||||
{ |
||||
in: 'query', |
||||
name: 'func', |
||||
description: 'comma separated aggregation functions', |
||||
type: 'string', |
||||
}, |
||||
], |
||||
responses: { |
||||
'405': { |
||||
description: 'Invalid input', |
||||
}, |
||||
'200': { |
||||
description: 'successful operation', |
||||
schema: { |
||||
type: 'array', |
||||
items: { |
||||
type: 'object', |
||||
}, |
||||
}, |
||||
}, |
||||
}, |
||||
}, |
||||
}, |
||||
[`/nc/${this.ctx.base_id}/api/${this.ctx.routeVersionLetter}/${this.ctx._tn}/distinct`]: |
||||
{ |
||||
get: { |
||||
tags: [`${this.ctx._tn}`], |
||||
summary: 'Get first one from filtered data', |
||||
description: '', |
||||
operationId: `${this.ctx._tn}Distinct`, |
||||
consumes: ['application/json'], |
||||
produces: ['application/json'], |
||||
parameters: [ |
||||
{ |
||||
in: 'query', |
||||
name: 'column_name', |
||||
type: 'string', |
||||
description: 'Column name', |
||||
}, |
||||
{ |
||||
in: 'query', |
||||
name: 'where', |
||||
type: 'string', |
||||
description: 'Where expression', |
||||
}, |
||||
{ |
||||
in: 'query', |
||||
name: 'limit', |
||||
description: 'Page size limit', |
||||
type: 'integer', |
||||
format: 'int64', |
||||
}, |
||||
{ |
||||
in: 'query', |
||||
name: 'offset', |
||||
description: 'Pagination offset', |
||||
type: 'integer', |
||||
format: 'int64', |
||||
}, |
||||
{ |
||||
in: 'query', |
||||
name: 'sort', |
||||
description: 'Comma separated sort fields', |
||||
type: 'string', |
||||
}, |
||||
], |
||||
responses: { |
||||
'405': { |
||||
description: 'Invalid input', |
||||
}, |
||||
'200': { |
||||
description: 'successful operation', |
||||
schema: { |
||||
type: 'array', |
||||
items: { |
||||
type: 'object', |
||||
}, |
||||
}, |
||||
}, |
||||
}, |
||||
}, |
||||
}, |
||||
[`/nc/${this.ctx.base_id}/api/${this.ctx.routeVersionLetter}/${this.ctx._tn}/aggregate`]: |
||||
{ |
||||
get: { |
||||
tags: [`${this.ctx._tn}`], |
||||
summary: 'Get first one from filtered data', |
||||
description: '', |
||||
operationId: `${this.ctx._tn}Aggregate`, |
||||
consumes: ['application/json'], |
||||
produces: ['application/json'], |
||||
parameters: [ |
||||
{ |
||||
in: 'query', |
||||
name: 'column_name', |
||||
type: 'string', |
||||
description: 'Column name', |
||||
}, |
||||
{ |
||||
in: 'query', |
||||
name: 'func', |
||||
type: 'string', |
||||
description: 'Comma separated aggregate functions', |
||||
}, |
||||
{ |
||||
in: 'query', |
||||
name: 'having', |
||||
type: 'string', |
||||
description: 'Having expression', |
||||
}, |
||||
{ |
||||
in: 'query', |
||||
name: 'fields', |
||||
type: 'string', |
||||
description: 'Comma separated fields from the model', |
||||
}, |
||||
{ |
||||
in: 'query', |
||||
name: 'limit', |
||||
description: 'Page size limit', |
||||
type: 'integer', |
||||
format: 'int64', |
||||
}, |
||||
{ |
||||
in: 'query', |
||||
name: 'offset', |
||||
description: 'Pagination offset', |
||||
type: 'integer', |
||||
format: 'int64', |
||||
}, |
||||
{ |
||||
in: 'query', |
||||
name: 'sort', |
||||
description: 'Comma separated sort fields', |
||||
type: 'string', |
||||
}, |
||||
], |
||||
responses: { |
||||
'405': { |
||||
description: 'Invalid input', |
||||
}, |
||||
'200': { |
||||
description: 'successful operation', |
||||
schema: { |
||||
$ref: `#/definitions/${this.ctx._tn}`, |
||||
}, |
||||
}, |
||||
}, |
||||
}, |
||||
}, |
||||
}, |
||||
definitions: this.getDefenitions(this.ctx), |
||||
}; |
||||
} |
||||
} |
||||
|
||||
export default SwaggerXc; |
@ -1,119 +0,0 @@
|
||||
import BaseRender from '../../BaseRender'; |
||||
|
||||
class SwaggerXcBt extends BaseRender { |
||||
/** |
||||
* |
||||
* @param dir |
||||
* @param filename |
||||
* @param ct |
||||
* @param ctx.tn |
||||
* @param ctx.columns |
||||
* @param ctx.relations |
||||
*/ |
||||
constructor({ dir, filename, ctx }: any) { |
||||
super({ dir, filename, ctx }); |
||||
} |
||||
|
||||
/** |
||||
* Prepare variables used in code template |
||||
*/ |
||||
prepare() { |
||||
let data: any = {}; |
||||
|
||||
/* run of simple variable */ |
||||
data = this.ctx; |
||||
|
||||
data.definitions = { |
||||
func: this._renderDefinitions.bind(this), |
||||
args: { |
||||
tn: this.ctx.tn, |
||||
columns: this.ctx.columns, |
||||
relations: this.ctx.relations, |
||||
}, |
||||
}; |
||||
|
||||
return data; |
||||
} |
||||
|
||||
/** |
||||
* |
||||
* @param args |
||||
* @param args.columns |
||||
* @param args.relations |
||||
* @returns {string} |
||||
* @private |
||||
*/ |
||||
_renderDefinitions(_args) { |
||||
const obj = {}; |
||||
|
||||
return JSON.stringify(obj); |
||||
} |
||||
|
||||
getObject() { |
||||
return { |
||||
tags: [ |
||||
{ |
||||
name: `${this.ctx._tn}BelongsTo${this.ctx._rtn || this.ctx.rtn}`, |
||||
description: 'Everything about belongs to relation', |
||||
}, |
||||
], |
||||
paths: { |
||||
[`/nc/${this.ctx.base_id}/api/${this.ctx.routeVersionLetter}/${ |
||||
this.ctx._tn |
||||
}/belongs/${this.ctx._rtn || this.ctx.rtn}`]: {
|
||||
get: { |
||||
tags: [`${this.ctx._tn}BelongsTo${this.ctx._rtn || this.ctx.rtn}`], |
||||
summary: `Get ${this.ctx._tn} list with ${ |
||||
this.ctx._rtn || this.ctx.rtn |
||||
} parent`,
|
||||
description: '', |
||||
operationId: `${this.ctx._tn}WithParent`, |
||||
produces: ['application/json'], |
||||
parameters: [ |
||||
{ |
||||
in: 'query', |
||||
name: 'where', |
||||
type: 'String', |
||||
description: 'Where expression', |
||||
}, |
||||
{ |
||||
in: 'query', |
||||
name: 'limit', |
||||
description: 'Page size limit', |
||||
type: 'integer', |
||||
format: 'int64', |
||||
}, |
||||
{ |
||||
in: 'query', |
||||
name: 'offset', |
||||
description: 'Pagination offset', |
||||
type: 'integer', |
||||
format: 'int64', |
||||
}, |
||||
{ |
||||
in: 'query', |
||||
name: 'sort', |
||||
description: 'Sort parameter', |
||||
type: 'string', |
||||
}, |
||||
], |
||||
responses: { |
||||
'200': { |
||||
description: 'successful operation', |
||||
schema: { |
||||
type: 'array', |
||||
items: { |
||||
type: 'object', |
||||
}, |
||||
}, |
||||
}, |
||||
}, |
||||
}, |
||||
}, |
||||
}, |
||||
definitions: {}, |
||||
}; |
||||
} |
||||
} |
||||
|
||||
export default SwaggerXcBt; |
@ -1,484 +0,0 @@
|
||||
import BaseRender from '../../BaseRender'; |
||||
|
||||
class SwaggerXcHm extends BaseRender { |
||||
/** |
||||
* |
||||
* @param dir |
||||
* @param filename |
||||
* @param ct |
||||
* @param ctx.tn |
||||
* @param ctx.columns |
||||
* @param ctx.relations |
||||
*/ |
||||
constructor({ dir, filename, ctx }: any) { |
||||
super({ dir, filename, ctx }); |
||||
} |
||||
|
||||
/** |
||||
* Prepare variables used in code template |
||||
*/ |
||||
prepare() { |
||||
let data: any = {}; |
||||
|
||||
/* run of simple variable */ |
||||
data = this.ctx; |
||||
|
||||
data.definitions = { |
||||
func: this._renderDefinitions.bind(this), |
||||
args: { |
||||
tn: this.ctx.tn, |
||||
columns: this.ctx.columns, |
||||
relations: this.ctx.relations, |
||||
}, |
||||
}; |
||||
|
||||
return data; |
||||
} |
||||
|
||||
/** |
||||
* |
||||
* @param args |
||||
* @param args.columns |
||||
* @param args.relations |
||||
* @returns {string} |
||||
* @private |
||||
*/ |
||||
_renderDefinitions(_args) { |
||||
const obj = {}; |
||||
|
||||
return JSON.stringify(obj); |
||||
} |
||||
|
||||
getObject() { |
||||
return { |
||||
tags: [ |
||||
{ |
||||
name: `${this.ctx._tn}HasMany${this.ctx._ctn}`, |
||||
description: 'Everything about has many relation', |
||||
}, |
||||
], |
||||
paths: { |
||||
[`/nc/${this.ctx.base_id}/api/${this.ctx.routeVersionLetter}/${this.ctx._tn}/has/${this.ctx._ctn}`]: |
||||
{ |
||||
get: { |
||||
tags: [`${this.ctx._tn}HasMany${this.ctx._ctn}`], |
||||
summary: `Get ${this.ctx._tn} list with ${this.ctx._ctn} children`, |
||||
description: '', |
||||
operationId: `${this.ctx._tn}HasMany${this.ctx._ctn}List`, |
||||
produces: ['application/json'], |
||||
parameters: [ |
||||
{ |
||||
in: 'query', |
||||
name: 'fields', |
||||
type: 'String', |
||||
description: 'Comma separated fields of model', |
||||
}, |
||||
{ |
||||
in: 'query', |
||||
name: 'where', |
||||
type: 'String', |
||||
description: 'Where expression', |
||||
}, |
||||
{ |
||||
in: 'query', |
||||
name: 'limit', |
||||
description: 'page size limit', |
||||
type: 'integer', |
||||
format: 'int64', |
||||
}, |
||||
{ |
||||
in: 'query', |
||||
name: 'offset', |
||||
description: 'pagination offset', |
||||
type: 'integer', |
||||
format: 'int64', |
||||
}, |
||||
{ |
||||
in: 'query', |
||||
name: 'sort', |
||||
description: 'sort parameter', |
||||
type: 'string', |
||||
}, |
||||
], |
||||
responses: { |
||||
'200': { |
||||
description: 'successful operation', |
||||
schema: { |
||||
type: 'array', |
||||
items: { |
||||
type: 'object', |
||||
}, |
||||
}, |
||||
}, |
||||
}, |
||||
}, |
||||
}, |
||||
[`/nc/${this.ctx.base_id}/api/${this.ctx.routeVersionLetter}/${this.ctx._tn}/{${this.ctx._tn}Id}/${this.ctx._ctn}`]: |
||||
{ |
||||
get: { |
||||
tags: [`${this.ctx._tn}HasMany${this.ctx._ctn}`], |
||||
summary: `Find ${this.ctx._ctn} list by parent ${this.ctx._tn} id`, |
||||
description: `Returns a single ${this.ctx._tn}`, |
||||
operationId: `get${this.ctx._ctn}By${this.ctx._tn}Id`, |
||||
produces: ['application/json'], |
||||
parameters: [ |
||||
{ |
||||
name: `${this.ctx._tn}Id`, |
||||
in: 'path', |
||||
description: `ID of ${this.ctx._tn} to return`, |
||||
required: true, |
||||
type: 'integer', |
||||
format: 'int64', |
||||
}, |
||||
{ |
||||
in: 'query', |
||||
name: 'fields', |
||||
type: 'String', |
||||
description: 'Comma separated fields of model', |
||||
}, |
||||
{ |
||||
in: 'query', |
||||
name: 'where', |
||||
type: 'String', |
||||
description: 'Where expression', |
||||
}, |
||||
{ |
||||
in: 'query', |
||||
name: 'limit', |
||||
description: 'page size limit', |
||||
type: 'integer', |
||||
format: 'int64', |
||||
}, |
||||
{ |
||||
in: 'query', |
||||
name: 'offset', |
||||
description: 'pagination offset', |
||||
type: 'integer', |
||||
format: 'int64', |
||||
}, |
||||
{ |
||||
in: 'query', |
||||
name: 'sort', |
||||
description: 'sort parameter', |
||||
type: 'string', |
||||
}, |
||||
], |
||||
responses: { |
||||
'200': { |
||||
description: 'successful operation', |
||||
schema: { |
||||
type: 'array', |
||||
items: 'object', |
||||
}, |
||||
}, |
||||
'400': { |
||||
description: 'Invalid ID supplied', |
||||
}, |
||||
'404': { |
||||
description: `${this.ctx._tn} not found`, |
||||
}, |
||||
}, |
||||
}, |
||||
post: { |
||||
tags: [`${this.ctx._tn}HasMany${this.ctx._ctn}`], |
||||
summary: `Insert ${this.ctx._ctn} under a parent ${this.ctx._tn}`, |
||||
description: `Returns a single ${this.ctx._tn}`, |
||||
operationId: `insert${this.ctx._ctn}By${this.ctx._tn}Id`, |
||||
consumes: ['application/json'], |
||||
produces: ['application/json'], |
||||
parameters: [ |
||||
{ |
||||
in: 'body', |
||||
name: 'body', |
||||
description: `${this.ctx._ctn} object to insert`, |
||||
required: true, |
||||
schema: { |
||||
type: 'object', |
||||
}, |
||||
}, |
||||
{ |
||||
name: `${this.ctx._tn}Id`, |
||||
in: 'path', |
||||
description: `ID of ${this.ctx._tn} to return`, |
||||
required: true, |
||||
type: 'integer', |
||||
format: 'int64', |
||||
}, |
||||
], |
||||
responses: { |
||||
'200': { |
||||
description: 'successful operation', |
||||
schema: { |
||||
type: 'object', |
||||
}, |
||||
}, |
||||
}, |
||||
}, |
||||
}, |
||||
[`/nc/${this.ctx.base_id}/api/${this.ctx.routeVersionLetter}/${this.ctx._tn}/{${this.ctx._tn}Id}/${this.ctx._ctn}/{${this.ctx._ctn}Id}`]: |
||||
{ |
||||
get: { |
||||
tags: [`${this.ctx._tn}HasMany${this.ctx._ctn}`], |
||||
summary: `Get by ${this.ctx._ctn} id parent ${this.ctx._tn} id`, |
||||
description: `Returns a single ${this.ctx._tn}`, |
||||
operationId: `get${this.ctx._ctn}ByIdAnd${this.ctx._tn}Id`, |
||||
produces: ['application/json'], |
||||
parameters: [ |
||||
{ |
||||
name: `${this.ctx._tn}Id`, |
||||
in: 'path', |
||||
description: `ID of parent ${this.ctx._tn}`, |
||||
required: true, |
||||
type: 'integer', |
||||
format: 'int64', |
||||
}, |
||||
{ |
||||
name: `${this.ctx._ctn}Id`, |
||||
in: 'path', |
||||
description: `ID of ${this.ctx._ctn}`, |
||||
required: true, |
||||
type: 'integer', |
||||
format: 'int64', |
||||
}, |
||||
], |
||||
responses: { |
||||
'200': { |
||||
description: 'successful operation', |
||||
schema: { |
||||
type: 'array', |
||||
items: 'object', |
||||
}, |
||||
}, |
||||
}, |
||||
}, |
||||
delete: { |
||||
tags: [`${this.ctx._tn}HasMany${this.ctx._ctn}`], |
||||
summary: `Delete by ${this.ctx._ctn} id parent ${this.ctx._tn} id`, |
||||
description: `Returns a single ${this.ctx._tn}`, |
||||
operationId: `delete${this.ctx._ctn}ByIdAnd${this.ctx._tn}Id`, |
||||
produces: ['application/json'], |
||||
parameters: [ |
||||
{ |
||||
name: `${this.ctx._tn}Id`, |
||||
in: 'path', |
||||
description: `ID of parent ${this.ctx._tn}`, |
||||
required: true, |
||||
type: 'integer', |
||||
format: 'int64', |
||||
}, |
||||
{ |
||||
name: `${this.ctx._ctn}Id`, |
||||
in: 'path', |
||||
description: `ID of c${this.ctx._ctn}`, |
||||
required: true, |
||||
type: 'integer', |
||||
format: 'int64', |
||||
}, |
||||
], |
||||
responses: { |
||||
'200': { |
||||
description: 'successful operation', |
||||
}, |
||||
}, |
||||
}, |
||||
put: { |
||||
tags: [`${this.ctx._tn}HasMany${this.ctx._ctn}`], |
||||
summary: `Update ${this.ctx._ctn} under a parent ${this.ctx._tn}`, |
||||
description: `Returns a single ${this.ctx._tn}`, |
||||
operationId: `update${this.ctx._ctn}ByIdAnd${this.ctx._tn}Id`, |
||||
consumes: ['application/json'], |
||||
produces: ['application/json'], |
||||
parameters: [ |
||||
{ |
||||
in: 'body', |
||||
name: 'body', |
||||
description: `${this.ctx._ctn} object to insert`, |
||||
required: true, |
||||
schema: { |
||||
type: 'object', |
||||
}, |
||||
}, |
||||
{ |
||||
name: `${this.ctx._tn}Id`, |
||||
in: 'path', |
||||
description: `ID of ${this.ctx._tn} to return`, |
||||
required: true, |
||||
type: 'integer', |
||||
format: 'int64', |
||||
}, |
||||
{ |
||||
name: `${this.ctx._ctn}Id`, |
||||
in: 'path', |
||||
description: `ID of ${this.ctx._ctn}`, |
||||
required: true, |
||||
type: 'integer', |
||||
format: 'int64', |
||||
}, |
||||
], |
||||
responses: { |
||||
'200': { |
||||
description: 'successful operation', |
||||
schema: { |
||||
type: 'object', |
||||
}, |
||||
}, |
||||
}, |
||||
}, |
||||
}, |
||||
[`/nc/${this.ctx.base_id}/api/${this.ctx.routeVersionLetter}/${this.ctx._tn}/{${this.ctx._tn}Id}/${this.ctx._ctn}/{${this.ctx._ctn}Id}/exists`]: |
||||
{ |
||||
get: { |
||||
tags: [`${this.ctx._tn}HasMany${this.ctx._ctn}`], |
||||
summary: `Check row exists by ${this.ctx._ctn} id and parent ${this.ctx._tn} id`, |
||||
description: '', |
||||
operationId: `exists${this.ctx._ctn}ByIdAnd${this.ctx._tn}Id`, |
||||
produces: ['application/json'], |
||||
parameters: [ |
||||
{ |
||||
name: `${this.ctx._tn}Id`, |
||||
in: 'path', |
||||
description: `ID of parent ${this.ctx._tn}`, |
||||
required: true, |
||||
type: 'integer', |
||||
format: 'int64', |
||||
}, |
||||
{ |
||||
name: `${this.ctx._ctn}Id`, |
||||
in: 'path', |
||||
description: `ID of ${this.ctx._ctn}`, |
||||
required: true, |
||||
type: 'integer', |
||||
format: 'int64', |
||||
}, |
||||
], |
||||
responses: { |
||||
'200': { |
||||
description: 'successful operation', |
||||
schema: { |
||||
type: 'boolean', |
||||
}, |
||||
}, |
||||
}, |
||||
}, |
||||
}, |
||||
[`/nc/${this.ctx.base_id}/api/${this.ctx.routeVersionLetter}/${this.ctx._tn}/{${this.ctx._tn}Id}/${this.ctx._ctn}/findOne`]: |
||||
{ |
||||
get: { |
||||
tags: [`${this.ctx._tn}HasMany${this.ctx._ctn}`], |
||||
summary: `Find one ${this.ctx._ctn} by parent ${this.ctx._tn} id and filters`, |
||||
description: '', |
||||
operationId: `findOne${this.ctx._ctn}By${this.ctx._tn}Id`, |
||||
produces: ['application/json'], |
||||
parameters: [ |
||||
{ |
||||
name: `${this.ctx._tn}Id`, |
||||
in: 'path', |
||||
description: `ID of parent ${this.ctx._tn}`, |
||||
required: true, |
||||
type: 'integer', |
||||
format: 'int64', |
||||
}, |
||||
{ |
||||
in: 'query', |
||||
name: 'fields', |
||||
type: 'String', |
||||
description: 'Comma separated fields of model', |
||||
}, |
||||
{ |
||||
in: 'query', |
||||
name: 'where', |
||||
type: 'String', |
||||
description: 'Where expression', |
||||
}, |
||||
{ |
||||
in: 'query', |
||||
name: 'limit', |
||||
description: 'page size limit', |
||||
type: 'integer', |
||||
format: 'int64', |
||||
}, |
||||
{ |
||||
in: 'query', |
||||
name: 'offset', |
||||
description: 'pagination offset', |
||||
type: 'integer', |
||||
format: 'int64', |
||||
}, |
||||
{ |
||||
in: 'query', |
||||
name: 'sort', |
||||
description: 'sort parameter', |
||||
type: 'string', |
||||
}, |
||||
], |
||||
responses: { |
||||
'200': { |
||||
description: 'successful operation', |
||||
schema: { |
||||
type: 'object', |
||||
}, |
||||
}, |
||||
}, |
||||
}, |
||||
}, |
||||
[`/nc/${this.ctx.base_id}/api/${this.ctx.routeVersionLetter}/${this.ctx._tn}/{${this.ctx._tn}Id}/${this.ctx._ctn}/count`]: |
||||
{ |
||||
get: { |
||||
tags: [`${this.ctx._tn}HasMany${this.ctx._ctn}`], |
||||
summary: `Get ${this.ctx._ctn} count by parent id and filter`, |
||||
description: '', |
||||
operationId: `getCountWithin${this.ctx._tn}Id`, |
||||
produces: ['application/json'], |
||||
parameters: [ |
||||
{ |
||||
name: `${this.ctx._tn}Id`, |
||||
in: 'path', |
||||
description: `ID of parent ${this.ctx._tn}`, |
||||
required: true, |
||||
type: 'integer', |
||||
format: 'int64', |
||||
}, |
||||
{ |
||||
in: 'query', |
||||
name: 'where', |
||||
type: 'String', |
||||
description: 'Where expression', |
||||
}, |
||||
{ |
||||
in: 'query', |
||||
name: 'limit', |
||||
description: 'page size limit', |
||||
type: 'integer', |
||||
format: 'int64', |
||||
}, |
||||
{ |
||||
in: 'query', |
||||
name: 'offset', |
||||
description: 'pagination offset', |
||||
type: 'integer', |
||||
format: 'int64', |
||||
}, |
||||
{ |
||||
in: 'query', |
||||
name: 'sort', |
||||
description: 'sort parameter', |
||||
type: 'string', |
||||
}, |
||||
], |
||||
responses: { |
||||
'200': { |
||||
description: 'successful operation', |
||||
schema: { |
||||
type: 'object', |
||||
}, |
||||
}, |
||||
}, |
||||
}, |
||||
}, |
||||
}, |
||||
definitions: {}, |
||||
}; |
||||
} |
||||
} |
||||
|
||||
export default SwaggerXcHm; |
@ -1,367 +0,0 @@
|
||||
import BaseRender from '../../BaseRender'; |
||||
|
||||
class ExpressXcTsRoutes extends BaseRender { |
||||
/** |
||||
* |
||||
* @param dir |
||||
* @param filename |
||||
* @param ct |
||||
* @param ctx.tn |
||||
* @param ctx.columns |
||||
* @param ctx.relations |
||||
*/ |
||||
constructor({ dir, filename, ctx }: any) { |
||||
super({ dir, filename, ctx }); |
||||
} |
||||
|
||||
/** |
||||
* Prepare variables used in code template |
||||
*/ |
||||
prepare() { |
||||
let data: any = {}; |
||||
|
||||
/* run of simple variable */ |
||||
data = this.ctx; |
||||
|
||||
return data; |
||||
} |
||||
|
||||
getObject() { |
||||
const ejsData: any = this.prepare(); |
||||
const routes = [ |
||||
{ |
||||
path: `/api/${this.ctx.routeVersionLetter}/${ejsData._tn}`, |
||||
type: 'get', |
||||
handler: ['list'], |
||||
acl: { |
||||
admin: true, |
||||
user: true, |
||||
guest: true, |
||||
}, |
||||
functions: [ |
||||
` |
||||
async function(req, res){ |
||||
const data = await req.model.list(req.query); |
||||
res.json(data); |
||||
} |
||||
`,
|
||||
], |
||||
}, |
||||
{ |
||||
path: `/api/${this.ctx.routeVersionLetter}/${ejsData._tn}/findOne`, |
||||
type: 'get', |
||||
handler: ['findOne'], |
||||
acl: { |
||||
admin: true, |
||||
user: true, |
||||
guest: true, |
||||
}, |
||||
functions: [ |
||||
` |
||||
async function(req, res){ |
||||
const data = await req.model.findOne(req.query); |
||||
res.json(data); |
||||
} |
||||
`,
|
||||
], |
||||
}, |
||||
{ |
||||
path: `/api/${this.ctx.routeVersionLetter}/${ejsData._tn}/m2mNotChildren/:assoc/:pid`, |
||||
type: 'get', |
||||
handler: ['m2mNotChildren'], |
||||
acl: { |
||||
admin: true, |
||||
user: true, |
||||
guest: true, |
||||
}, |
||||
functions: [ |
||||
` |
||||
`,
|
||||
], |
||||
}, |
||||
{ |
||||
path: `/api/${this.ctx.routeVersionLetter}/${ejsData._tn}/groupby/:column_name`, |
||||
type: 'get', |
||||
handler: ['groupby'], |
||||
acl: { |
||||
admin: true, |
||||
user: true, |
||||
guest: true, |
||||
}, |
||||
functions: [ |
||||
` |
||||
async function(req, res){ |
||||
const data = await req.model.groupBy({ |
||||
...req.params, |
||||
...req.query |
||||
}); |
||||
res.json(data); |
||||
} |
||||
`,
|
||||
], |
||||
}, |
||||
{ |
||||
path: `/api/${this.ctx.routeVersionLetter}/${ejsData._tn}/count`, |
||||
type: 'get', |
||||
handler: ['count'], |
||||
acl: { |
||||
admin: true, |
||||
user: true, |
||||
guest: true, |
||||
}, |
||||
functions: [ |
||||
` |
||||
async function(req, res){ |
||||
const data = await req.model.countByPk({ |
||||
...req.query |
||||
}); |
||||
res.json(data); |
||||
} |
||||
`,
|
||||
], |
||||
}, |
||||
{ |
||||
path: `/api/${this.ctx.routeVersionLetter}/${ejsData._tn}/bulk`, |
||||
type: 'post', |
||||
handler: ['bulkInsert'], |
||||
acl: { |
||||
admin: true, |
||||
user: true, |
||||
guest: false, |
||||
}, |
||||
functions: [ |
||||
` |
||||
async function(req, res){ |
||||
const data = await req.model.insertb(req.body); |
||||
res.json(data); |
||||
} |
||||
`,
|
||||
], |
||||
}, |
||||
{ |
||||
path: `/api/${this.ctx.routeVersionLetter}/${ejsData._tn}/bulk`, |
||||
type: 'put', |
||||
handler: ['bulkUpdate'], |
||||
acl: { |
||||
admin: true, |
||||
user: true, |
||||
guest: false, |
||||
}, |
||||
functions: [ |
||||
` |
||||
async function(req, res){ |
||||
const data = await req.model.updateb(req.body); |
||||
res.json(data); |
||||
} |
||||
`,
|
||||
], |
||||
}, |
||||
{ |
||||
path: `/api/${this.ctx.routeVersionLetter}/${ejsData._tn}/bulk`, |
||||
type: 'delete', |
||||
handler: ['bulkDelete'], |
||||
acl: { |
||||
admin: true, |
||||
user: true, |
||||
guest: false, |
||||
}, |
||||
functions: [ |
||||
` |
||||
async function(req, res){ |
||||
const data = await req.model.delb(req.body) |
||||
res.json(data); |
||||
} |
||||
`,
|
||||
], |
||||
}, |
||||
{ |
||||
path: `/api/${this.ctx.routeVersionLetter}/${ejsData._tn}/:id/exists`, |
||||
type: 'get', |
||||
handler: ['exists'], |
||||
acl: { |
||||
admin: true, |
||||
user: true, |
||||
guest: false, |
||||
}, |
||||
functions: [ |
||||
` |
||||
async function(req, res){ |
||||
const data = await req.model.exists(req.params.id); |
||||
res.json(data); |
||||
} |
||||
`,
|
||||
], |
||||
}, |
||||
{ |
||||
path: `/api/${this.ctx.routeVersionLetter}/${ejsData._tn}/distinct`, |
||||
type: 'get', |
||||
handler: ['distinct'], |
||||
acl: { |
||||
admin: true, |
||||
user: true, |
||||
guest: true, |
||||
}, |
||||
functions: [ |
||||
` |
||||
async function(req, res){ |
||||
const data = await req.model.distinct({ |
||||
...req.query |
||||
}); |
||||
res.json(data); |
||||
} |
||||
`,
|
||||
], |
||||
}, |
||||
{ |
||||
path: `/api/${this.ctx.routeVersionLetter}/${ejsData._tn}/distribute`, |
||||
type: 'get', |
||||
handler: ['distribute'], |
||||
acl: { |
||||
admin: true, |
||||
user: true, |
||||
guest: true, |
||||
}, |
||||
functions: [ |
||||
` |
||||
async function(req, res){ |
||||
const data = await req.model.distribution({ |
||||
...req.query |
||||
}); |
||||
res.json(data); |
||||
} |
||||
`,
|
||||
], |
||||
}, |
||||
{ |
||||
path: `/api/${this.ctx.routeVersionLetter}/${ejsData._tn}/aggregate`, |
||||
type: 'get', |
||||
handler: ['aggregate'], |
||||
acl: { |
||||
admin: true, |
||||
user: true, |
||||
guest: true, |
||||
}, |
||||
functions: [ |
||||
` |
||||
async function(req, res){ |
||||
const data = await req.model.aggregate({ |
||||
...req.params, |
||||
...req.query |
||||
}); |
||||
res.json(data); |
||||
} |
||||
`,
|
||||
], |
||||
}, |
||||
{ |
||||
path: `/api/${this.ctx.routeVersionLetter}/${ejsData._tn}/groupby`, |
||||
type: 'get', |
||||
handler: ['groupby'], |
||||
acl: { |
||||
admin: true, |
||||
user: true, |
||||
guest: true, |
||||
}, |
||||
functions: [ |
||||
` |
||||
async function(req, res){ |
||||
const data = await req.model.groupBy({ |
||||
...req.params, |
||||
...req.query |
||||
}); |
||||
res.json(data); |
||||
} |
||||
`,
|
||||
], |
||||
}, |
||||
{ |
||||
path: `/api/${this.ctx.routeVersionLetter}/${ejsData._tn}/:id`, |
||||
type: 'get', |
||||
handler: ['get'], |
||||
acl: { |
||||
admin: true, |
||||
user: true, |
||||
guest: true, |
||||
}, |
||||
functions: [ |
||||
` |
||||
async function(req, res){ |
||||
const data = await req.model.readByPk(req.params.id); |
||||
res.json(data); |
||||
} |
||||
`,
|
||||
], |
||||
}, |
||||
{ |
||||
path: `/api/${this.ctx.routeVersionLetter}/${ejsData._tn}`, |
||||
type: 'post', |
||||
handler: ['create'], |
||||
acl: { |
||||
admin: true, |
||||
user: true, |
||||
guest: false, |
||||
}, |
||||
functions: [ |
||||
` |
||||
async function(req, res){ |
||||
const data = await req.model.insert(req.body, null, req); |
||||
res.json(data); |
||||
} |
||||
`,
|
||||
], |
||||
}, |
||||
{ |
||||
path: `/api/${this.ctx.routeVersionLetter}/${ejsData._tn}/:id`, |
||||
type: 'put', |
||||
handler: ['update'], |
||||
acl: { |
||||
admin: true, |
||||
user: true, |
||||
guest: false, |
||||
}, |
||||
functions: [ |
||||
` |
||||
async function(req, res){ |
||||
const data = await req.model.updateByPk(req.params.id, req.body, null, req); |
||||
res.json(data); |
||||
} |
||||
`,
|
||||
], |
||||
}, |
||||
{ |
||||
path: `/api/${this.ctx.routeVersionLetter}/${ejsData._tn}/:id`, |
||||
type: 'delete', |
||||
handler: ['delete'], |
||||
acl: { |
||||
admin: true, |
||||
user: true, |
||||
guest: false, |
||||
}, |
||||
functions: [ |
||||
` |
||||
async function(req, res){ |
||||
const data = await req.model.delByPk(req.params.id, null, req); |
||||
res.json(data); |
||||
} |
||||
`,
|
||||
], |
||||
}, |
||||
]; |
||||
|
||||
if (this.ctx.type === 'view') { |
||||
return routes.filter( |
||||
({ type, handler }) => |
||||
type === 'get' && |
||||
!handler.includes('exists') && |
||||
!handler.includes('get'), |
||||
); |
||||
} |
||||
return routes; |
||||
} |
||||
|
||||
getObjectWithoutFunctions() { |
||||
return this.getObject().map(({ functions, ...rest }) => rest); |
||||
} |
||||
} |
||||
|
||||
export default ExpressXcTsRoutes; |
@ -1,61 +0,0 @@
|
||||
import BaseRender from '../../BaseRender'; |
||||
|
||||
class ExpressXcTsRoutesBt extends BaseRender { |
||||
/** |
||||
* |
||||
* @param dir |
||||
* @param filename |
||||
* @param ct |
||||
* @param ctx.tn |
||||
* @param ctx.columns |
||||
* @param ctx.relations |
||||
*/ |
||||
constructor({ dir, filename, ctx }: any) { |
||||
super({ dir, filename, ctx }); |
||||
} |
||||
|
||||
/** |
||||
* Prepare variables used in code template |
||||
*/ |
||||
prepare() { |
||||
let data: any = {}; |
||||
|
||||
/* run of simple variable */ |
||||
data = this.ctx; |
||||
|
||||
return data; |
||||
} |
||||
|
||||
getObject() { |
||||
const ejsData = this.prepare(); |
||||
return [ |
||||
{ |
||||
path: `/api/${this.ctx.routeVersionLetter}/${ejsData._tn}/belongs/${ejsData._rtn}`, |
||||
type: 'get', |
||||
handler: ['list'], |
||||
acl: { |
||||
admin: true, |
||||
user: true, |
||||
guest: true, |
||||
}, |
||||
functions: [ |
||||
` |
||||
async function(req, res){ |
||||
const data = await req.childModel.belongsTo({ |
||||
parents: req.parentModel.tn, |
||||
...req.query |
||||
}); |
||||
res.json(data); |
||||
} |
||||
`,
|
||||
], |
||||
}, |
||||
]; |
||||
} |
||||
|
||||
getObjectWithoutFunctions() { |
||||
return this.getObject().map(({ functions, ...rest }) => rest); |
||||
} |
||||
} |
||||
|
||||
export default ExpressXcTsRoutesBt; |
@ -1,239 +0,0 @@
|
||||
import BaseRender from '../../BaseRender'; |
||||
|
||||
class ExpressXcTsRoutesHm extends BaseRender { |
||||
/** |
||||
* |
||||
* @param dir |
||||
* @param filename |
||||
* @param ct |
||||
* @param ctx.tn |
||||
* @param ctx.columns |
||||
* @param ctx.relations |
||||
*/ |
||||
constructor({ dir, filename, ctx }: any) { |
||||
super({ dir, filename, ctx }); |
||||
} |
||||
|
||||
/** |
||||
* Prepare variables used in code template |
||||
*/ |
||||
public prepare(): any { |
||||
let data = {}; |
||||
|
||||
/* run of simple variable */ |
||||
data = this.ctx; |
||||
|
||||
return data; |
||||
} |
||||
|
||||
public getObject() { |
||||
const ejsData: any = this.prepare(); |
||||
return [ |
||||
{ |
||||
path: `/api/${this.ctx.routeVersionLetter}/${ejsData._tn}/has/:childs`, // ${ejsData._ctn}
|
||||
type: 'get', |
||||
handler: ['hasManyList'], |
||||
acl: { |
||||
admin: true, |
||||
user: true, |
||||
guest: true, |
||||
}, |
||||
functions: [ |
||||
` |
||||
async function(req, res){ |
||||
const data = await req.parentModel.hasManyList({ |
||||
...req.query, |
||||
childs: req.childModel.tn |
||||
}); |
||||
res.json(data); |
||||
} |
||||
`,
|
||||
], |
||||
}, |
||||
{ |
||||
path: `/api/v1/${ejsData._tn}/:parentId/${ejsData._ctn}`, |
||||
type: 'get', |
||||
handler: ['list'], |
||||
acl: { |
||||
admin: true, |
||||
user: true, |
||||
guest: true, |
||||
}, |
||||
functions: [ |
||||
` |
||||
async function(req, res){ |
||||
const data = await req.parentModel.hasManyChildren({ |
||||
child: req.childModel.tn, |
||||
...req.params, |
||||
...req.query |
||||
}) |
||||
res.json(data); |
||||
} |
||||
`,
|
||||
], |
||||
}, |
||||
{ |
||||
path: `/api/v1/${ejsData._tn}/:parentId/${ejsData._ctn}`, |
||||
type: 'post', |
||||
handler: ['create'], |
||||
acl: { |
||||
admin: true, |
||||
user: true, |
||||
guest: false, |
||||
}, |
||||
functions: [ |
||||
` |
||||
async function(req, res){ |
||||
const data = await req.childModel.insertByFk({ |
||||
parentId: req.params.parentId, |
||||
parentTableName: req.parentModel.tn, |
||||
data: req.body |
||||
}); |
||||
res.json(data); |
||||
} |
||||
`,
|
||||
], |
||||
}, |
||||
{ |
||||
path: `/api/v1/${ejsData._tn}/:parentId/${ejsData._ctn}/findOne`, |
||||
type: 'get', |
||||
handler: ['findOne'], |
||||
acl: { |
||||
admin: true, |
||||
user: true, |
||||
guest: true, |
||||
}, |
||||
functions: [ |
||||
` |
||||
async function(req, res){ |
||||
const data = await req.childModel.findOneByFk({ |
||||
parentId: req.params.parentId, |
||||
parentTableName: req.parentModel.tn, |
||||
...req.query |
||||
}); |
||||
res.json(data); |
||||
} |
||||
`,
|
||||
], |
||||
}, |
||||
{ |
||||
path: `/api/v1/${ejsData._tn}/:parentId/${ejsData._ctn}/count`, |
||||
type: 'get', |
||||
handler: ['count'], |
||||
acl: { |
||||
admin: true, |
||||
user: true, |
||||
guest: true, |
||||
}, |
||||
functions: [ |
||||
` |
||||
async function(req, res){ |
||||
const data = await req.childModel.countByFk({ |
||||
parentId: req.params.parentId, |
||||
parentTableName: req.parentModel.tn, |
||||
...req.query |
||||
}); |
||||
res.json(data); |
||||
} |
||||
`,
|
||||
], |
||||
}, |
||||
{ |
||||
path: `/api/v1/${ejsData._tn}/:parentId/${ejsData._ctn}/:id`, |
||||
type: 'get', |
||||
handler: ['read'], |
||||
acl: { |
||||
admin: true, |
||||
user: true, |
||||
guest: true, |
||||
}, |
||||
functions: [ |
||||
` |
||||
async function(req, res){ |
||||
const data = await req.childModel.readByFk({ |
||||
parentId: req.params.parentId, |
||||
parentTableName: req.parentModel.tn, |
||||
id: req.params.id |
||||
}); |
||||
res.json(data); |
||||
} |
||||
`,
|
||||
], |
||||
}, |
||||
{ |
||||
path: `/api/v1/${ejsData._tn}/:parentId/${ejsData._ctn}/:id`, |
||||
type: 'put', |
||||
handler: ['update'], |
||||
acl: { |
||||
admin: true, |
||||
user: true, |
||||
guest: false, |
||||
}, |
||||
functions: [ |
||||
` |
||||
async function(req, res){ |
||||
const data = await req.childModel.updateByFk({ |
||||
parentId: req.params.parentId, |
||||
parentTableName: req.parentModel.tn, |
||||
id: req.params.id, |
||||
data: req.body |
||||
}); |
||||
res.json(data); |
||||
} |
||||
`,
|
||||
], |
||||
}, |
||||
{ |
||||
path: `/api/v1/${ejsData._tn}/:parentId/${ejsData._ctn}/:id`, |
||||
type: 'delete', |
||||
handler: ['delete'], |
||||
acl: { |
||||
admin: true, |
||||
user: true, |
||||
guest: false, |
||||
}, |
||||
functions: [ |
||||
` |
||||
async function(req, res){ |
||||
const data = await req.childModel.delByFk({ |
||||
parentId: req.params.parentId, |
||||
parentTableName: req.parentModel.tn, |
||||
id: req.params.id |
||||
}); |
||||
res.json(data); |
||||
} |
||||
`,
|
||||
], |
||||
}, |
||||
{ |
||||
path: `/api/v1/${ejsData._tn}/:parentId/${ejsData._ctn}/:id/exists`, |
||||
type: 'get', |
||||
handler: ['exists'], |
||||
acl: { |
||||
admin: true, |
||||
user: true, |
||||
guest: true, |
||||
}, |
||||
functions: [ |
||||
` |
||||
async function(req, res){ |
||||
const data = await req.childModel.existsByFk({ |
||||
parentId: req.params.parentId, |
||||
parentTableName: req.parentModel.tn, |
||||
id: req.params.id, |
||||
...req.query |
||||
}); |
||||
res.json(data); |
||||
} |
||||
`,
|
||||
], |
||||
}, |
||||
]; |
||||
} |
||||
|
||||
public getObjectWithoutFunctions() { |
||||
return this.getObject().map(({ functions, ...rest }) => rest); |
||||
} |
||||
} |
||||
|
||||
export default ExpressXcTsRoutesHm; |
File diff suppressed because it is too large
Load Diff
@ -1,37 +0,0 @@
|
||||
export default class SqlMigrator { |
||||
protected base: any; |
||||
|
||||
constructor() { |
||||
this.base = null; |
||||
} |
||||
|
||||
init(_project = null) {} |
||||
|
||||
// migrationsInit() {
|
||||
//
|
||||
// }
|
||||
//
|
||||
// migrationsCreate() {
|
||||
//
|
||||
// }
|
||||
//
|
||||
// migrationsList() {
|
||||
//
|
||||
// }
|
||||
//
|
||||
// migrationsUp() {
|
||||
//
|
||||
// }
|
||||
//
|
||||
// migrationsDown() {
|
||||
//
|
||||
// }
|
||||
//
|
||||
// migrationsStatus() {
|
||||
//
|
||||
// }
|
||||
//
|
||||
// migrationsDelete() {
|
||||
//
|
||||
// }
|
||||
} |
@ -1,19 +0,0 @@
|
||||
import KnexMigrator from './KnexMigrator'; |
||||
|
||||
export default class SqlMigratorFactory { |
||||
static create(args) { |
||||
switch (args.client) { |
||||
case 'mysql': |
||||
case 'mysql2': |
||||
case 'pg': |
||||
case 'oracledb': |
||||
case 'mssql': |
||||
case 'sqlite3': |
||||
return new KnexMigrator(); |
||||
break; |
||||
default: |
||||
throw new Error('Database not supported'); |
||||
break; |
||||
} |
||||
} |
||||
} |
@ -1,171 +0,0 @@
|
||||
import fs from 'fs'; |
||||
import { promisify } from 'util'; |
||||
import { defaultConnectionConfig } from '../nc-config'; |
||||
import type { Knex } from 'knex'; |
||||
import SqlClientFactory from '~/db/sql-client/lib/SqlClientFactory'; |
||||
import { XKnex } from '~/db/CustomKnex'; |
||||
// import type { NcConfig } from '~/interface/config';
|
||||
// import type NcMetaIO from '~/meta/NcMetaIO';
|
||||
|
||||
export default class NcConnectionMgr { |
||||
private static connectionRefs: { |
||||
[baseId: string]: { |
||||
[env: string]: { |
||||
[dbAlias: string]: XKnex; |
||||
}; |
||||
}; |
||||
} = {}; |
||||
|
||||
private static metaKnex: any; |
||||
|
||||
public static setXcMeta(ncMeta: any) { |
||||
this.metaKnex = ncMeta; |
||||
} |
||||
|
||||
public static delete({ |
||||
dbAlias = 'db', |
||||
env = '_noco', |
||||
baseId, |
||||
}: { |
||||
dbAlias: string; |
||||
env: string; |
||||
baseId: string; |
||||
}) { |
||||
// todo: ignore meta bases
|
||||
if (this.connectionRefs?.[baseId]?.[env]?.[dbAlias]) { |
||||
try { |
||||
const conn = this.connectionRefs[baseId][env][dbAlias]; |
||||
conn.destroy(); |
||||
delete this.connectionRefs[baseId][env][dbAlias]; |
||||
} catch (e) { |
||||
console.log(e); |
||||
} |
||||
} |
||||
} |
||||
|
||||
public static async get({ |
||||
dbAlias = 'db', |
||||
env = '_noco', |
||||
config, |
||||
baseId, |
||||
}: { |
||||
dbAlias: string; |
||||
env: string; |
||||
config: any; |
||||
baseId: string; |
||||
}): Promise<XKnex> { |
||||
if (this.connectionRefs?.[baseId]?.[env]?.[dbAlias]) { |
||||
return this.connectionRefs?.[baseId]?.[env]?.[dbAlias]; |
||||
} |
||||
this.connectionRefs[baseId] = this.connectionRefs[baseId] || {}; |
||||
this.connectionRefs[baseId][env] = this.connectionRefs[baseId][env] || {}; |
||||
if (config?.prefix && this.metaKnex) { |
||||
this.connectionRefs[baseId][env][dbAlias] = this.metaKnex?.knex; |
||||
} else { |
||||
const connectionConfig = this.getConnectionConfig(config, env, dbAlias); |
||||
|
||||
if ( |
||||
connectionConfig?.connection?.ssl && |
||||
typeof connectionConfig?.connection?.ssl === 'object' |
||||
) { |
||||
if ( |
||||
connectionConfig.connection.ssl.caFilePath && |
||||
!connectionConfig.connection.ssl.ca |
||||
) { |
||||
connectionConfig.connection.ssl.ca = ( |
||||
await promisify(fs.readFile)( |
||||
connectionConfig.connection.ssl.caFilePath, |
||||
) |
||||
).toString(); |
||||
delete connectionConfig.connection.ssl.caFilePath; |
||||
} |
||||
if ( |
||||
connectionConfig.connection.ssl.keyFilePath && |
||||
!connectionConfig.connection.ssl.key |
||||
) { |
||||
connectionConfig.connection.ssl.key = ( |
||||
await promisify(fs.readFile)( |
||||
connectionConfig.connection.ssl.keyFilePath, |
||||
) |
||||
).toString(); |
||||
delete connectionConfig.connection.ssl.keyFilePath; |
||||
} |
||||
if ( |
||||
connectionConfig.connection.ssl.certFilePath && |
||||
!connectionConfig.connection.ssl.cert |
||||
) { |
||||
connectionConfig.connection.ssl.cert = ( |
||||
await promisify(fs.readFile)( |
||||
connectionConfig.connection.ssl.certFilePath, |
||||
) |
||||
).toString(); |
||||
delete connectionConfig.connection.ssl.certFilePath; |
||||
} |
||||
} |
||||
|
||||
const isSqlite = connectionConfig?.client === 'sqlite3'; |
||||
|
||||
if (connectionConfig?.connection?.port) { |
||||
connectionConfig.connection.port = +connectionConfig.connection.port; |
||||
} |
||||
|
||||
this.connectionRefs[baseId][env][dbAlias] = XKnex( |
||||
isSqlite |
||||
? (connectionConfig.connection as Knex.Config) |
||||
: ({ |
||||
...connectionConfig, |
||||
connection: { |
||||
...defaultConnectionConfig, |
||||
...connectionConfig.connection, |
||||
typeCast(_field, next) { |
||||
const res = next(); |
||||
if (res instanceof Buffer) { |
||||
return [...res] |
||||
.map((v) => ('00' + v.toString(16)).slice(-2)) |
||||
.join(''); |
||||
} |
||||
return res; |
||||
}, |
||||
}, |
||||
} as any), |
||||
); |
||||
if (isSqlite) { |
||||
this.connectionRefs[baseId][env][dbAlias] |
||||
.raw(`PRAGMA journal_mode=WAL;`) |
||||
.then(() => {}); |
||||
} |
||||
} |
||||
return this.connectionRefs[baseId][env][dbAlias]; |
||||
} |
||||
|
||||
private static getConnectionConfig( |
||||
config: any, |
||||
env: string, |
||||
dbAlias: string, |
||||
) { |
||||
return config?.envs?.[env]?.db?.find((db) => db?.meta?.dbAlias === dbAlias); |
||||
} |
||||
|
||||
public static async getSqlClient({ |
||||
baseId, |
||||
dbAlias = 'db', |
||||
env = '_noco', |
||||
config, |
||||
}: { |
||||
dbAlias: string; |
||||
env: string; |
||||
config: any; |
||||
baseId: string; |
||||
}) { |
||||
const knex = this.get({ |
||||
dbAlias, |
||||
env, |
||||
config, |
||||
baseId, |
||||
}); |
||||
return SqlClientFactory.create({ |
||||
knex, |
||||
...this.getConnectionConfig(config, env, dbAlias), |
||||
}); |
||||
} |
||||
} |
@ -1,14 +0,0 @@
|
||||
import { UITypes } from 'nocodb-sdk'; |
||||
import type { NcUpgraderCtx } from './NcUpgrader'; |
||||
import { MetaTable } from '~/utils/globals'; |
||||
|
||||
// The Count and AutoNumber types are removed
|
||||
// so convert all existing Count and AutoNumber fields to Number type
|
||||
export default async function (ctx: NcUpgraderCtx) { |
||||
// directly update uidt of all existing Count and AutoNumber fields to Number
|
||||
await ctx.ncMeta.knex |
||||
.update({ uidt: UITypes.Number }) |
||||
.where({ uidt: UITypes.Count }) |
||||
.orWhere({ uidt: UITypes.AutoNumber }) |
||||
.table(MetaTable.COLUMNS); |
||||
} |
@ -1,18 +0,0 @@
|
||||
import type { NcUpgraderCtx } from './NcUpgrader'; |
||||
|
||||
export default async function (ctx: NcUpgraderCtx) { |
||||
const bases = await ctx.ncMeta.baseList(); |
||||
|
||||
for (const base of bases) { |
||||
const baseConfig = JSON.parse(base.config); |
||||
|
||||
const envVal = baseConfig.envs?.dev; |
||||
baseConfig.workingEnv = '_noco'; |
||||
|
||||
if (envVal) { |
||||
baseConfig.envs._noco = envVal; |
||||
delete baseConfig.envs.dev; |
||||
} |
||||
await ctx.ncMeta.baseUpdate(base?.id, baseConfig); |
||||
} |
||||
} |
@ -1,11 +0,0 @@
|
||||
import type { NcUpgraderCtx } from './NcUpgrader'; |
||||
|
||||
export default async function (ctx: NcUpgraderCtx) { |
||||
const bases = await ctx.ncMeta.baseList(); |
||||
|
||||
for (const base of bases) { |
||||
const baseConfig = JSON.parse(base.config); |
||||
baseConfig.env = '_noco'; |
||||
await ctx.ncMeta.baseUpdate(base?.id, baseConfig); |
||||
} |
||||
} |
@ -1,47 +0,0 @@
|
||||
import { OrgUserRoles } from 'nocodb-sdk'; |
||||
import { NC_APP_SETTINGS } from '../constants'; |
||||
import type { NcUpgraderCtx } from './NcUpgrader'; |
||||
import Store from '~/models/Store'; |
||||
import { MetaTable, RootScopes } from '~/utils/globals'; |
||||
|
||||
/** Upgrader for upgrading roles */ |
||||
export default async function ({ ncMeta }: NcUpgraderCtx) { |
||||
const users = await ncMeta.metaList2( |
||||
RootScopes.ROOT, |
||||
RootScopes.ROOT, |
||||
MetaTable.USERS, |
||||
); |
||||
|
||||
for (const user of users) { |
||||
user.roles = user.roles |
||||
.split(',') |
||||
.map((r) => { |
||||
// update old role names with new roles
|
||||
if (r === 'user') { |
||||
return OrgUserRoles.CREATOR; |
||||
} else if (r === 'user-new') { |
||||
return OrgUserRoles.VIEWER; |
||||
} |
||||
return r; |
||||
}) |
||||
.join(','); |
||||
await ncMeta.metaUpdate( |
||||
RootScopes.ROOT, |
||||
RootScopes.ROOT, |
||||
MetaTable.USERS, |
||||
{ roles: user.roles }, |
||||
user.id, |
||||
); |
||||
} |
||||
|
||||
// set invite only signup if user have environment variable set
|
||||
if (process.env.NC_INVITE_ONLY_SIGNUP) { |
||||
await Store.saveOrUpdate( |
||||
{ |
||||
value: '{ "invite_only_signup": true }', |
||||
key: NC_APP_SETTINGS, |
||||
}, |
||||
ncMeta, |
||||
); |
||||
} |
||||
} |
File diff suppressed because it is too large
Load Diff
@ -1,612 +0,0 @@
|
||||
import debug from 'debug'; |
||||
import { Router } from 'express'; |
||||
import inflection from 'inflection'; |
||||
import ncModelsOrderUpgrader from './jobs/ncModelsOrderUpgrader'; |
||||
import ncParentModelTitleUpgrader from './jobs/ncParentModelTitleUpgrader'; |
||||
import ncRemoveDuplicatedRelationRows from './jobs/ncRemoveDuplicatedRelationRows'; |
||||
import type NcProjectBuilder from './NcProjectBuilder'; |
||||
import type { XKnex } from '~/db/CustomKnex'; |
||||
import type { BaseModelSql } from '~/db/BaseModelSql'; |
||||
import type { MetaService } from '~/meta/meta.service'; |
||||
import type Noco from '~/Noco'; |
||||
import type { MysqlClient, PgClient, SqlClient } from 'nc-help'; |
||||
import type { DbConfig, NcConfig } from '~/interface/config'; |
||||
import ModelXcMetaFactory from '~/db/sql-mgr/code/models/xc/ModelXcMetaFactory'; |
||||
import NcConnectionMgr from '~/utils/common/NcConnectionMgr'; |
||||
import { RootScopes } from '~/utils/globals'; |
||||
|
||||
const log = debug('nc:api:source'); |
||||
|
||||
export default abstract class BaseApiBuilder<T extends Noco> { |
||||
public abstract readonly type: string; |
||||
|
||||
public get knex(): XKnex { |
||||
return this.sqlClient?.knex || this.dbDriver; |
||||
} |
||||
|
||||
public get prefix() { |
||||
return this.baseBuilder?.prefix; |
||||
} |
||||
|
||||
public get apiType(): string { |
||||
return this.connectionConfig?.meta?.api?.type; |
||||
} |
||||
|
||||
public get apiPrefix(): string { |
||||
return this.connectionConfig?.meta?.api?.prefix; |
||||
} |
||||
|
||||
public get dbAlias(): any { |
||||
return this.connectionConfig?.meta?.dbAlias; |
||||
} |
||||
|
||||
public get router(): Router { |
||||
if (!this.apiRouter) { |
||||
this.baseLog(`router : Initializing builder router`); |
||||
this.apiRouter = Router(); |
||||
// (this.app as any).router.use('/', this.apiRouter)
|
||||
(this.baseBuilder as any).router.use('/', this.apiRouter); |
||||
} |
||||
return this.apiRouter; |
||||
} |
||||
|
||||
public get routeVersionLetter(): string { |
||||
return this.connectionConfig?.meta?.api?.prefix || 'v1'; |
||||
} |
||||
|
||||
protected get baseId(): string { |
||||
return this.baseBuilder?.id; |
||||
} |
||||
|
||||
public get xcModels() { |
||||
return this.models; |
||||
} |
||||
|
||||
public get client() { |
||||
return this.connectionConfig?.client; |
||||
} |
||||
|
||||
public readonly app: T; |
||||
|
||||
public hooks: { |
||||
[tableName: string]: { |
||||
[key: string]: Array<{ |
||||
event: string; |
||||
url: string; |
||||
[key: string]: any; |
||||
}>; |
||||
}; |
||||
}; |
||||
|
||||
public formViews: { |
||||
[tableName: string]: any; |
||||
}; |
||||
|
||||
protected tablesCount = 0; |
||||
protected relationsCount = 0; |
||||
protected viewsCount = 0; |
||||
protected functionsCount = 0; |
||||
protected proceduresCount = 0; |
||||
|
||||
protected baseBuilder: NcProjectBuilder; |
||||
|
||||
protected models: { [key: string]: BaseModelSql }; |
||||
|
||||
protected metas: { [key: string]: NcMetaData }; |
||||
|
||||
protected sqlClient: MysqlClient | PgClient | SqlClient | any; |
||||
|
||||
protected dbDriver: XKnex; |
||||
protected config: NcConfig; |
||||
protected connectionConfig: DbConfig; |
||||
|
||||
protected procedureOrFunctionAcls: { |
||||
[name: string]: { [role: string]: boolean }; |
||||
}; |
||||
protected xcMeta: MetaService; |
||||
|
||||
private apiRouter: Router; |
||||
|
||||
constructor( |
||||
app: T, |
||||
baseBuilder: NcProjectBuilder, |
||||
config: NcConfig, |
||||
connectionConfig: DbConfig, |
||||
) { |
||||
this.models = {}; |
||||
this.app = app; |
||||
this.config = config; |
||||
this.connectionConfig = connectionConfig; |
||||
this.metas = {}; |
||||
this.procedureOrFunctionAcls = {}; |
||||
this.hooks = {}; |
||||
this.formViews = {}; |
||||
this.baseBuilder = baseBuilder; |
||||
} |
||||
|
||||
public getDbType(): any { |
||||
return this.connectionConfig.client; |
||||
} |
||||
|
||||
public getDbName(): any { |
||||
return (this.connectionConfig.connection as any)?.database; |
||||
} |
||||
|
||||
public getDbAlias(): any { |
||||
return this.connectionConfig?.meta?.dbAlias; |
||||
} |
||||
|
||||
public async getSqlClient() { |
||||
return NcConnectionMgr.getSqlClient({ |
||||
dbAlias: this.dbAlias, |
||||
env: this.config.env, |
||||
config: this.config, |
||||
baseId: this.baseId, |
||||
}); |
||||
} |
||||
|
||||
public async xcUpgrade(): Promise<any> { |
||||
const NC_VERSIONS = [ |
||||
{ name: '0009000', handler: null }, |
||||
{ name: '0009044', handler: this.ncUpManyToMany.bind(this) }, |
||||
{ name: '0083006', handler: ncModelsOrderUpgrader }, |
||||
{ name: '0083007', handler: ncParentModelTitleUpgrader }, |
||||
{ name: '0083008', handler: ncRemoveDuplicatedRelationRows }, |
||||
{ name: '0084002', handler: this.ncUpAddNestedResolverArgs.bind(this) }, |
||||
]; |
||||
if (!(await this.xcMeta?.knex?.schema?.hasTable?.('nc_store'))) { |
||||
return; |
||||
} |
||||
this.baseLog(`xcUpgrade : Getting configuration from meta database`); |
||||
|
||||
const config = await this.xcMeta.metaGet( |
||||
this.baseId, |
||||
this.dbAlias, |
||||
'nc_store', |
||||
{ key: 'NC_CONFIG' }, |
||||
); |
||||
|
||||
if (config) { |
||||
const configObj: NcConfig = JSON.parse(config.value); |
||||
if (configObj.version !== process.env.NC_VERSION) { |
||||
for (const version of NC_VERSIONS) { |
||||
// compare current version and old version
|
||||
if (version.name > configObj.version) { |
||||
this.baseLog( |
||||
`xcUpgrade : Upgrading '%s' => '%s'`, |
||||
configObj.version, |
||||
version.name, |
||||
); |
||||
await version?.handler?.(<NcBuilderUpgraderCtx>{ |
||||
xcMeta: this.xcMeta, |
||||
builder: this, |
||||
dbAlias: this.dbAlias, |
||||
baseId: this.baseId, |
||||
}); |
||||
|
||||
// update version in meta after each upgrade
|
||||
configObj.version = version.name; |
||||
await this.xcMeta.metaUpdate( |
||||
context.workspace_id, |
||||
context.base_id, |
||||
'nc_store', |
||||
{ |
||||
value: JSON.stringify(configObj), |
||||
}, |
||||
{ |
||||
key: 'NC_CONFIG', |
||||
}, |
||||
); |
||||
|
||||
// todo: backup data
|
||||
} |
||||
if (version.name === process.env.NC_VERSION) { |
||||
break; |
||||
} |
||||
} |
||||
configObj.version = process.env.NC_VERSION; |
||||
await this.xcMeta.metaUpdate( |
||||
context.workspace_id, |
||||
context.base_id, |
||||
'nc_store', |
||||
{ |
||||
value: JSON.stringify(configObj), |
||||
}, |
||||
{ |
||||
key: 'NC_CONFIG', |
||||
}, |
||||
); |
||||
} |
||||
} else { |
||||
this.baseLog(`xcUpgrade : Inserting config to meta database`); |
||||
const configObj: NcConfig = JSON.parse(JSON.stringify(this.config)); |
||||
delete configObj.envs; |
||||
const isOld = ( |
||||
await this.xcMeta.metaList2(context.workspace_id, context.base_id, 'nc_models') |
||||
)?.length; |
||||
configObj.version = isOld ? '0009000' : process.env.NC_VERSION; |
||||
await this.xcMeta.metaInsert2( |
||||
context.workspace_id, |
||||
context.base_id, |
||||
'nc_store', |
||||
{ |
||||
key: 'NC_CONFIG', |
||||
value: JSON.stringify(configObj), |
||||
dbAlias: this.dbAlias, |
||||
}, |
||||
true, |
||||
); |
||||
if (isOld) { |
||||
await this.xcUpgrade(); |
||||
} |
||||
} |
||||
} |
||||
|
||||
public getProjectId(): string { |
||||
return this.baseId; |
||||
} |
||||
|
||||
public async init(): Promise<void> { |
||||
await this.xcUpgrade(); |
||||
} |
||||
|
||||
protected async initDbDriver(): Promise<void> { |
||||
this.dbDriver = await NcConnectionMgr.get({ |
||||
dbAlias: this.dbAlias, |
||||
env: this.config.env, |
||||
config: this.config, |
||||
baseId: this.baseId, |
||||
}); |
||||
this.sqlClient = await NcConnectionMgr.getSqlClient({ |
||||
dbAlias: this.dbAlias, |
||||
env: this.config.env, |
||||
config: this.config, |
||||
baseId: this.baseId, |
||||
}); |
||||
} |
||||
|
||||
private baseLog(str, ...args): void { |
||||
log(`${this.dbAlias} : ${str}`, ...args); |
||||
} |
||||
|
||||
protected generateContextForTable( |
||||
tn: string, |
||||
columns: any[], |
||||
relations, |
||||
hasMany: any[], |
||||
belongsTo: any[], |
||||
type = 'table', |
||||
tableNameAlias?: string, |
||||
): any { |
||||
this.baseLog(`generateContextForTable : '%s' %s`, tn, type); |
||||
|
||||
for (const col of columns) { |
||||
col._cn = col._cn || this.getColumnNameAlias(col); |
||||
} |
||||
|
||||
// tslint:disable-next-line:variable-name
|
||||
const _tn = tableNameAlias || this.getTableNameAlias(tn); |
||||
|
||||
const ctx = { |
||||
dbType: this.connectionConfig.client, |
||||
tn, |
||||
_tn, |
||||
tn_camelize: inflection.camelize(_tn), |
||||
tn_camelize_low: inflection.camelize(_tn, true), |
||||
columns, |
||||
relations, |
||||
hasMany, |
||||
belongsTo, |
||||
dbAlias: '', |
||||
routeVersionLetter: this.routeVersionLetter, |
||||
type, |
||||
base_id: this.baseId, |
||||
}; |
||||
return ctx; |
||||
} |
||||
|
||||
private getColumnNameAlias(col, tableName?: string) { |
||||
return ( |
||||
this.metas?.[tableName]?.columns?.find((c) => c.cn === col.cn)?._cn || |
||||
col._cn || |
||||
this.getInflectedName(col.cn, this.connectionConfig?.meta?.inflection?.cn) |
||||
); |
||||
} |
||||
|
||||
// table alias functions
|
||||
protected getInflectedName(_name: string, inflectionFns: string): string { |
||||
let name = _name; |
||||
if (process.env.NC_INFLECTION) { |
||||
inflectionFns = 'camelize'; |
||||
} |
||||
|
||||
if (inflectionFns && inflectionFns !== 'none') { |
||||
name = inflectionFns |
||||
.split(',') |
||||
.reduce((out, fn) => inflection?.[fn]?.(out) || out, name); |
||||
} |
||||
return this.apiType === 'graphql' ? name.replace(/[^_\da-z]/gi, '_') : name; |
||||
} |
||||
|
||||
protected async ncUpAddNestedResolverArgs(_ctx: any): Promise<any> {} |
||||
|
||||
protected getTableNameAlias(tableName: string) { |
||||
let tn = tableName; |
||||
if (this.metas?.[tn]?._tn) { |
||||
return this.metas?.[tn]?._tn; |
||||
} |
||||
|
||||
if (this.baseBuilder?.prefix) { |
||||
tn = tn.replace(this.baseBuilder?.prefix, ''); |
||||
} |
||||
|
||||
const modifiedTableName = tn?.replace(/^(?=\d+)/, 'ISN___'); |
||||
return this.getInflectedName( |
||||
modifiedTableName, |
||||
this.connectionConfig?.meta?.inflection?.tn, |
||||
); |
||||
} |
||||
|
||||
protected async ncUpManyToMany(_ctx: any): Promise<any> { |
||||
const models = await this.xcMeta.metaList2(context.workspace_id, context.base_id, 'nc_models', { |
||||
fields: ['meta'], |
||||
condition: { |
||||
type: 'table', |
||||
}, |
||||
}); |
||||
if (!models.length) { |
||||
return; |
||||
} |
||||
const metas = []; |
||||
// add virtual columns for relations
|
||||
for (const metaObj of models) { |
||||
const meta = JSON.parse(metaObj.meta); |
||||
metas.push(meta); |
||||
const ctx = this.generateContextForTable( |
||||
meta.tn, |
||||
meta.columns, |
||||
[], |
||||
meta.hasMany, |
||||
meta.belongsTo, |
||||
meta.type, |
||||
meta._tn, |
||||
); |
||||
// generate virtual columns
|
||||
meta.v = ModelXcMetaFactory.create(this.connectionConfig, { |
||||
dir: '', |
||||
ctx, |
||||
filename: '', |
||||
}).getVirtualColumns(); |
||||
// set default display values
|
||||
ModelXcMetaFactory.create( |
||||
this.connectionConfig, |
||||
{}, |
||||
).mapDefaultDisplayValue(meta.columns); |
||||
// update meta
|
||||
await this.xcMeta.metaUpdate( |
||||
context.workspace_id, |
||||
context.base_id, |
||||
'nc_models', |
||||
{ |
||||
meta: JSON.stringify(meta), |
||||
}, |
||||
{ title: meta.tn }, |
||||
); |
||||
} |
||||
|
||||
// generate many to many relations an columns
|
||||
await this.getManyToManyRelations({ localMetas: metas }); |
||||
return metas; |
||||
} |
||||
|
||||
protected async getManyToManyRelations({ |
||||
parent = null, |
||||
child = null, |
||||
localMetas = null, |
||||
} = {}): Promise<Set<any>> { |
||||
const metas = new Set<any>(); |
||||
const assocMetas = new Set<any>(); |
||||
|
||||
if (localMetas) { |
||||
for (const meta of localMetas) { |
||||
this.metas[meta.tn] = meta; |
||||
} |
||||
} |
||||
|
||||
for (const meta of Object.values(this.metas)) { |
||||
// check if table is a Bridge table(or Associative Table) by checking
|
||||
// number of foreign keys and columns
|
||||
if (meta.belongsTo?.length === 2 && meta.columns.length < 5) { |
||||
if ( |
||||
parent && |
||||
child && |
||||
!( |
||||
[parent, child].includes(meta.belongsTo[0].rtn) && |
||||
[parent, child].includes(meta.belongsTo[1].rtn) |
||||
) |
||||
) { |
||||
continue; |
||||
} |
||||
|
||||
const tableMetaA = this.metas[meta.belongsTo[0].rtn]; |
||||
const tableMetaB = this.metas[meta.belongsTo[1].rtn]; |
||||
|
||||
/* // remove hasmany relation with associate table from tables |
||||
tableMetaA.hasMany.splice(tableMetaA.hasMany.findIndex(hm => hm.tn === meta.tn), 1) |
||||
tableMetaB.hasMany.splice(tableMetaB.hasMany.findIndex(hm => hm.tn === meta.tn), 1)*/ |
||||
|
||||
// add manytomany data under metadata of both linked tables
|
||||
tableMetaA.manyToMany = tableMetaA.manyToMany || []; |
||||
if (tableMetaA.manyToMany.every((mm) => mm.vtn !== meta.tn)) { |
||||
tableMetaA.manyToMany.push({ |
||||
tn: tableMetaA.tn, |
||||
cn: meta.belongsTo[0].rcn, |
||||
vtn: meta.tn, |
||||
vcn: meta.belongsTo[0].cn, |
||||
vrcn: meta.belongsTo[1].cn, |
||||
rtn: meta.belongsTo[1].rtn, |
||||
rcn: meta.belongsTo[1].rcn, |
||||
_tn: tableMetaA._tn, |
||||
_cn: meta.belongsTo[0]._rcn, |
||||
_rtn: meta.belongsTo[1]._rtn, |
||||
_rcn: meta.belongsTo[1]._rcn, |
||||
}); |
||||
metas.add(tableMetaA); |
||||
} |
||||
// ignore if A & B are same table
|
||||
if (tableMetaB !== tableMetaA) { |
||||
tableMetaB.manyToMany = tableMetaB.manyToMany || []; |
||||
if (tableMetaB.manyToMany.every((mm) => mm.vtn !== meta.tn)) { |
||||
tableMetaB.manyToMany.push({ |
||||
tn: tableMetaB.tn, |
||||
cn: meta.belongsTo[1].rcn, |
||||
vtn: meta.tn, |
||||
vcn: meta.belongsTo[1].cn, |
||||
vrcn: meta.belongsTo[0].cn, |
||||
rtn: meta.belongsTo[0].rtn, |
||||
rcn: meta.belongsTo[0].rcn, |
||||
_tn: tableMetaB._tn, |
||||
_cn: meta.belongsTo[1]._rcn, |
||||
_rtn: meta.belongsTo[0]._rtn, |
||||
_rcn: meta.belongsTo[0]._rcn, |
||||
}); |
||||
metas.add(tableMetaB); |
||||
} |
||||
} |
||||
assocMetas.add(meta); |
||||
} |
||||
} |
||||
|
||||
// Update metadata of tables which have manytomany relation
|
||||
// and recreate basemodel with new meta information
|
||||
for (const meta of metas) { |
||||
let queryParams; |
||||
|
||||
// update showfields on new many to many relation create
|
||||
if (parent && child) { |
||||
try { |
||||
queryParams = JSON.parse( |
||||
( |
||||
await this.xcMeta.metaGet( |
||||
this.baseId, |
||||
this.dbAlias, |
||||
'nc_models', |
||||
{ title: meta.tn }, |
||||
) |
||||
).query_params, |
||||
); |
||||
} catch (e) { |
||||
// ignore
|
||||
} |
||||
} |
||||
|
||||
meta.v = [ |
||||
...meta.v.filter( |
||||
(vc) => !(vc.hm && meta.manyToMany.some((mm) => vc.hm.tn === mm.vtn)), |
||||
), |
||||
// todo: ignore duplicate m2m relations
|
||||
// todo: optimize, just compare associative table(Vtn)
|
||||
...meta.manyToMany |
||||
.filter( |
||||
(v, i) => |
||||
!meta.v.some( |
||||
(v1) => |
||||
v1.mm && |
||||
((v1.mm.tn === v.tn && v.rtn === v1.mm.rtn) || |
||||
(v1.mm.rtn === v.tn && v.tn === v1.mm.rtn)) && |
||||
v.vtn === v1.mm.vtn, |
||||
) && |
||||
// ignore duplicate
|
||||
!meta.manyToMany.some( |
||||
(v1, i1) => |
||||
i1 !== i && |
||||
v1.tn === v.tn && |
||||
v.rtn === v1.rtn && |
||||
v.vtn === v1.vtn, |
||||
), |
||||
) |
||||
.map((mm) => { |
||||
if ( |
||||
queryParams?.showFields && |
||||
!(`${mm._tn} <=> ${mm._rtn}` in queryParams.showFields) |
||||
) { |
||||
queryParams.showFields[`${mm._tn} <=> ${mm._rtn}`] = true; |
||||
} |
||||
|
||||
return { |
||||
mm, |
||||
_cn: `${mm._tn} <=> ${mm._rtn}`, |
||||
}; |
||||
}), |
||||
]; |
||||
await this.xcMeta.metaUpdate( |
||||
context.workspace_id, |
||||
context.base_id, |
||||
'nc_models', |
||||
{ |
||||
meta: JSON.stringify(meta), |
||||
...(queryParams ? { query_params: JSON.stringify(queryParams) } : {}), |
||||
}, |
||||
{ title: meta.tn }, |
||||
); |
||||
// XcCache.del([this.baseId, this.dbAlias, 'table', meta.tn].join('::'));
|
||||
// if (!localMetas) {
|
||||
// this.models[meta.tn] = this.getBaseModel(meta);
|
||||
// }
|
||||
} |
||||
|
||||
// Update metadata of associative table
|
||||
for (const meta of assocMetas) { |
||||
await this.xcMeta.metaUpdate( |
||||
context.workspace_id, |
||||
context.base_id, |
||||
'nc_models', |
||||
{ |
||||
mm: 1, |
||||
}, |
||||
{ title: meta.tn }, |
||||
); |
||||
} |
||||
|
||||
return metas; |
||||
} |
||||
} |
||||
|
||||
interface NcBuilderUpgraderCtx { |
||||
xcMeta: MetaService; |
||||
builder: BaseApiBuilder<any>; |
||||
baseId: string; |
||||
dbAlias: string; |
||||
} |
||||
|
||||
interface NcMetaData { |
||||
tn: string; |
||||
_tn?: string; |
||||
v: Array<{ |
||||
_cn?: string; |
||||
[key: string]: any; |
||||
}>; |
||||
columns: Array<{ |
||||
_cn?: string; |
||||
cn?: string; |
||||
uidt?: string; |
||||
[key: string]: any; |
||||
}>; |
||||
|
||||
[key: string]: any; |
||||
} |
||||
|
||||
type XcTablesPopulateParams = { |
||||
tableNames?: Array<{ |
||||
tn: string; |
||||
_tn?: string; |
||||
}>; |
||||
type?: 'table' | 'view' | 'function' | 'procedure'; |
||||
columns?: { |
||||
[tn: string]: any; |
||||
}; |
||||
oldMetas?: { |
||||
[tn: string]: NcMetaData; |
||||
}; |
||||
}; |
||||
export { NcBuilderUpgraderCtx, NcMetaData, XcTablesPopulateParams }; |
@ -1,198 +0,0 @@
|
||||
import { Router } from 'express'; |
||||
import { GqlApiBuilder } from './gql/GqlApiBuilder'; |
||||
import { RestApiBuilder } from './rest/RestApiBuilder'; |
||||
import type Noco from '~/Noco'; |
||||
import type { NcConfig } from '~/interface/config'; |
||||
import { SqlClientFactory } from '~/db/sql-client/lib/SqlClientFactory'; |
||||
|
||||
export default class NcProjectBuilder { |
||||
public readonly id: string; |
||||
public readonly title: string; |
||||
public readonly description: string; |
||||
public readonly router: Router; |
||||
public readonly apiBuilders: Array<RestApiBuilder | GqlApiBuilder> = []; |
||||
private _config: any; |
||||
|
||||
protected startTime; |
||||
protected app: Noco; |
||||
protected appConfig: NcConfig; |
||||
protected apiInfInfoList: any[] = []; |
||||
protected aggregatedApiInfo: any; |
||||
protected authHook: any; |
||||
|
||||
constructor(app: Noco, appConfig: NcConfig, base: any) { |
||||
this.app = app; |
||||
this.appConfig = appConfig; |
||||
|
||||
if (base) { |
||||
this.id = base.id; |
||||
this.title = base.title; |
||||
this.description = base.description; |
||||
this._config = { ...this.appConfig, ...JSON.parse(base.config) }; |
||||
this.router = Router(); |
||||
} |
||||
} |
||||
|
||||
public async init(_isFirstTime?: boolean) { |
||||
try { |
||||
// await this.addAuthHookToMiddleware();
|
||||
|
||||
this.startTime = Date.now(); |
||||
const allRoutesInfo: any[] = []; |
||||
// await this.app.ncMeta.baseStatusUpdate(this.id, 'starting');
|
||||
// await this.syncMigration();
|
||||
await this._createApiBuilder(); |
||||
// this.initApiInfoRoute();
|
||||
|
||||
/* Create REST APIs / GraphQL Resolvers */ |
||||
for (const meta of this.apiBuilders) { |
||||
let routeInfo; |
||||
if (meta instanceof RestApiBuilder) { |
||||
console.log( |
||||
`Creating REST APIs ${meta.getDbType()} - > ${meta.getDbName()}`, |
||||
); |
||||
routeInfo = await (meta as RestApiBuilder).init(); |
||||
} else if (meta instanceof GqlApiBuilder) { |
||||
console.log( |
||||
`Creating GraphQL APIs ${meta.getDbType()} - > ${meta.getDbName()}`, |
||||
); |
||||
routeInfo = await (meta as GqlApiBuilder).init(); |
||||
} |
||||
allRoutesInfo.push(routeInfo); |
||||
// this.progress(routeInfo, allRoutesInfo, isFirstTime);
|
||||
} |
||||
|
||||
// this.app.baseRouter.use(`/nc/${this.id}`, this.router);
|
||||
// await this.app.ncMeta.baseStatusUpdate(this.id, 'started');
|
||||
} catch (e) { |
||||
console.log(e); |
||||
throw e; |
||||
// await this.app.ncMeta.baseStatusUpdate(this.id, 'stopped');
|
||||
} |
||||
} |
||||
|
||||
protected async _createApiBuilder() { |
||||
this.apiBuilders.splice(0, this.apiBuilders.length); |
||||
let i = 0; |
||||
|
||||
const connectionConfigs = []; |
||||
|
||||
/* for each db create an api builder */ |
||||
for (const db of this.config?.envs?.[this.appConfig?.workingEnv]?.db || |
||||
[]) { |
||||
let Builder; |
||||
switch (db.meta.api.type) { |
||||
case 'graphql': |
||||
Builder = GqlApiBuilder; |
||||
break; |
||||
|
||||
case 'rest': |
||||
Builder = RestApiBuilder; |
||||
break; |
||||
} |
||||
|
||||
if ((db?.connection as any)?.database) { |
||||
const connectionConfig = { |
||||
...db, |
||||
meta: { |
||||
...db.meta, |
||||
api: { |
||||
...db.meta.api, |
||||
prefix: db.meta.api.prefix || this.genVer(i), |
||||
}, |
||||
}, |
||||
}; |
||||
|
||||
this.apiBuilders.push( |
||||
new Builder( |
||||
this.app, |
||||
this, |
||||
this.config, |
||||
connectionConfig, |
||||
this.app.ncMeta, |
||||
), |
||||
); |
||||
connectionConfigs.push(connectionConfig); |
||||
i++; |
||||
} else if (db.meta?.allSchemas) { |
||||
/* get all schemas and create APIs for all of them */ |
||||
const sqlClient = await SqlClientFactory.create({ |
||||
...db, |
||||
connection: { ...db.connection, database: undefined }, |
||||
}); |
||||
|
||||
const schemaList = (await sqlClient.schemaList({}))?.data?.list; |
||||
for (const schema of schemaList) { |
||||
const connectionConfig = { |
||||
...db, |
||||
connection: { ...db.connection, database: schema.schema_name }, |
||||
meta: { |
||||
...db.meta, |
||||
dbAlias: i ? db.meta.dbAlias + i : db.meta.dbAlias, |
||||
api: { |
||||
...db.meta.api, |
||||
prefix: db.meta.api.prefix || this.genVer(i), |
||||
}, |
||||
}, |
||||
}; |
||||
|
||||
this.apiBuilders.push( |
||||
new Builder( |
||||
this.app, |
||||
this, |
||||
this.config, |
||||
connectionConfig, |
||||
this.app.ncMeta, |
||||
), |
||||
); |
||||
connectionConfigs.push(connectionConfig); |
||||
|
||||
i++; |
||||
} |
||||
|
||||
sqlClient.knex.destroy(); |
||||
} |
||||
} |
||||
if (this.config?.envs?.[this.appConfig.workingEnv]?.db) { |
||||
this.config.envs[this.appConfig.workingEnv].db.splice( |
||||
0, |
||||
this.config.envs[this.appConfig.workingEnv].db.length, |
||||
...connectionConfigs, |
||||
); |
||||
} |
||||
} |
||||
|
||||
protected genVer(i): string { |
||||
const l = 'vwxyzabcdefghijklmnopqrstu'; |
||||
return ( |
||||
i |
||||
.toString(26) |
||||
.split('') |
||||
.map((v) => l[parseInt(v, 26)]) |
||||
.join('') + '1' |
||||
); |
||||
} |
||||
|
||||
protected static triggerGarbageCollect() { |
||||
try { |
||||
if (global.gc) { |
||||
global.gc(); |
||||
} |
||||
} catch (e) { |
||||
console.log('`node --expose-gc index.js`'); |
||||
process.exit(); |
||||
} |
||||
} |
||||
|
||||
public get prefix(): string { |
||||
return this.config?.prefix; |
||||
} |
||||
|
||||
public get config(): any { |
||||
return this._config; |
||||
} |
||||
|
||||
public updateConfig(config: string) { |
||||
this._config = { ...this.appConfig, ...JSON.parse(config) }; |
||||
} |
||||
} |
@ -1,145 +0,0 @@
|
||||
import { Router } from 'express'; |
||||
import BaseApiBuilder from '../BaseApiBuilder'; |
||||
import type NcProjectBuilder from '../NcProjectBuilder'; |
||||
import type XcMetaMgr from '~/interface/XcMetaMgr'; |
||||
import type { DbConfig, NcConfig } from '~/interface/config'; |
||||
import type { MetaService } from '~/meta/meta.service'; |
||||
import type Noco from '~/Noco'; |
||||
import GqlXcSchemaFactory from '~/db/sql-mgr/code/gql-schema/xc-ts/GqlXcSchemaFactory'; |
||||
|
||||
export class GqlApiBuilder extends BaseApiBuilder<Noco> implements XcMetaMgr { |
||||
public readonly type = 'gql'; |
||||
|
||||
private readonly gqlRouter: Router; |
||||
|
||||
constructor( |
||||
app: Noco, |
||||
baseBuilder: NcProjectBuilder, |
||||
config: NcConfig, |
||||
connectionConfig: DbConfig, |
||||
xcMeta?: MetaService, |
||||
) { |
||||
super(app, baseBuilder, config, connectionConfig); |
||||
this.config = config; |
||||
this.connectionConfig = connectionConfig; |
||||
this.gqlRouter = Router(); |
||||
this.xcMeta = xcMeta; |
||||
} |
||||
|
||||
public async init(): Promise<void> { |
||||
await super.init(); |
||||
} |
||||
|
||||
protected async ncUpAddNestedResolverArgs(_ctx: any): Promise<any> { |
||||
const models = await this.xcMeta.metaList2(context.workspace_id, context.base_id, 'nc_models', { |
||||
fields: ['meta'], |
||||
condition: { |
||||
type: 'table', |
||||
}, |
||||
}); |
||||
if (!models.length) { |
||||
return; |
||||
} |
||||
// add virtual columns for relations
|
||||
for (const metaObj of models) { |
||||
const meta = JSON.parse(metaObj.meta); |
||||
const ctx = this.generateContextForTable( |
||||
meta.tn, |
||||
meta.columns, |
||||
[], |
||||
meta.hasMany, |
||||
meta.belongsTo, |
||||
meta.type, |
||||
meta._tn, |
||||
); |
||||
|
||||
/* generate gql schema of the table */ |
||||
const schema = GqlXcSchemaFactory.create(this.connectionConfig, { |
||||
dir: '', |
||||
ctx: { |
||||
...ctx, |
||||
manyToMany: meta.manyToMany, |
||||
}, |
||||
filename: '', |
||||
}).getString(); |
||||
|
||||
/* update schema in metadb */ |
||||
await this.xcMeta.metaUpdate( |
||||
context.workspace_id, |
||||
context.base_id, |
||||
'nc_models', |
||||
{ |
||||
schema, |
||||
}, |
||||
{ |
||||
title: meta.tn, |
||||
type: 'table', |
||||
}, |
||||
); |
||||
} |
||||
} |
||||
|
||||
protected async ncUpManyToMany(ctx: any): Promise<any> { |
||||
const metas = await super.ncUpManyToMany(ctx); |
||||
|
||||
if (!metas) { |
||||
return; |
||||
} |
||||
for (const meta of metas) { |
||||
const ctx = this.generateContextForTable( |
||||
meta.tn, |
||||
meta.columns, |
||||
[], |
||||
meta.hasMany, |
||||
meta.belongsTo, |
||||
meta.type, |
||||
meta._tn, |
||||
); |
||||
|
||||
/* generate gql schema of the table */ |
||||
const schema = GqlXcSchemaFactory.create(this.connectionConfig, { |
||||
dir: '', |
||||
ctx: { |
||||
...ctx, |
||||
manyToMany: meta.manyToMany, |
||||
}, |
||||
filename: '', |
||||
}).getString(); |
||||
|
||||
/* update schema in metadb */ |
||||
await this.xcMeta.metaUpdate( |
||||
context.workspace_id, |
||||
context.base_id, |
||||
'nc_models', |
||||
{ |
||||
schema, |
||||
}, |
||||
{ |
||||
title: meta.tn, |
||||
type: 'table', |
||||
}, |
||||
); |
||||
|
||||
// todo : add loaders
|
||||
|
||||
if (meta.manyToMany) { |
||||
for (const mm of meta.manyToMany) { |
||||
await this.xcMeta.metaInsert2( |
||||
context.workspace_id, |
||||
context.base_id, |
||||
'nc_loaders', |
||||
{ |
||||
title: `${mm.tn}Mm${mm.rtn}List`, |
||||
parent: mm.tn, |
||||
child: mm.rtn, |
||||
relation: 'mm', |
||||
resolver: 'mmlist', |
||||
dbAlias: this.dbAlias, |
||||
}, |
||||
true, |
||||
); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
@ -1,38 +0,0 @@
|
||||
import type { NcBuilderUpgraderCtx } from '../BaseApiBuilder'; |
||||
|
||||
export default async function (ctx: NcBuilderUpgraderCtx) { |
||||
const models = await ctx.xcMeta.metaList2(context.workspace_id, context.base_id, 'nc_models', { |
||||
xcCondition: { |
||||
_or: [{ type: { eq: 'table' } }, { type: { eq: 'view' } }], |
||||
}, |
||||
}); |
||||
let order = 0; |
||||
for (const model of models) { |
||||
await ctx.xcMeta.metaUpdate( |
||||
context.workspace_id, |
||||
context.base_id, |
||||
'nc_models', |
||||
{ |
||||
order: ++order, |
||||
view_order: 1, |
||||
}, |
||||
model.id, |
||||
); |
||||
|
||||
const views = await ctx.xcMeta.metaList2(context.workspace_id, context.base_id, 'nc_models', { |
||||
condition: { parent_model_title: model.title }, |
||||
}); |
||||
let view_order = 1; |
||||
for (const view of views) { |
||||
await ctx.xcMeta.metaUpdate( |
||||
context.workspace_id, |
||||
context.base_id, |
||||
'nc_models', |
||||
{ |
||||
view_order: ++view_order, |
||||
}, |
||||
view.id, |
||||
); |
||||
} |
||||
} |
||||
} |
@ -1,24 +0,0 @@
|
||||
import type { NcBuilderUpgraderCtx } from '../BaseApiBuilder'; |
||||
|
||||
export default async function (ctx: NcBuilderUpgraderCtx) { |
||||
const views = await ctx.xcMeta.metaList2(context.workspace_id, context.base_id, 'nc_models', { |
||||
condition: { |
||||
type: 'vtable', |
||||
}, |
||||
}); |
||||
|
||||
for (const view of views) { |
||||
await ctx.xcMeta.metaUpdate( |
||||
context.workspace_id, |
||||
context.base_id, |
||||
'nc_disabled_models_for_role', |
||||
{ |
||||
parent_model_title: view.parent_model_title, |
||||
}, |
||||
{ |
||||
type: 'vtable', |
||||
title: view.title, |
||||
}, |
||||
); |
||||
} |
||||
} |
@ -1,112 +0,0 @@
|
||||
import type { NcBuilderUpgraderCtx } from '../BaseApiBuilder'; |
||||
|
||||
export default async function (ctx: NcBuilderUpgraderCtx) { |
||||
try { |
||||
const relations = await ctx.xcMeta.metaList2( |
||||
context.workspace_id, |
||||
context.base_id, |
||||
'nc_relations', |
||||
); |
||||
|
||||
const duplicates = []; |
||||
|
||||
for (const relation of relations) { |
||||
if (relation.type !== 'real' || duplicates.includes(relation)) continue; |
||||
const duplicateRelIndex = relations.findIndex( |
||||
(rel) => |
||||
rel !== relation && |
||||
rel.tn === relation.tn && |
||||
rel.rtn === relation.rtn && |
||||
rel.cn === relation.cn && |
||||
rel.rcn === relation.rcn && |
||||
rel.type === 'real', |
||||
); |
||||
|
||||
if (duplicateRelIndex > -1) duplicates.push(relations[duplicateRelIndex]); |
||||
} |
||||
|
||||
// delete relation
|
||||
for (const dupRelation of duplicates) { |
||||
await ctx.xcMeta.metaDeleteAll('nc_relations', { |
||||
id: dupRelation.id, |
||||
base_id: ctx.baseId, |
||||
db_alias: ctx.dbAlias, |
||||
}); |
||||
{ |
||||
const tnModel = await ctx.xcMeta.metaGet( |
||||
ctx.baseId, |
||||
ctx.dbAlias, |
||||
'nc_models', |
||||
{ |
||||
type: 'table', |
||||
title: dupRelation.tn, |
||||
}, |
||||
); |
||||
|
||||
const meta = JSON.parse(tnModel.meta); |
||||
|
||||
const duplicateBts = meta.belongsTo.filter( |
||||
(bt) => |
||||
bt.tn === dupRelation.tn && |
||||
bt.rtn === dupRelation.rtn && |
||||
bt.cn === dupRelation.cn && |
||||
bt.rcn === dupRelation.rcn && |
||||
bt.type === 'real', |
||||
); |
||||
|
||||
if (duplicateBts?.length > 1) { |
||||
meta.belongsTo.splice(meta.belongsTo.indexOf(duplicateBts[1]), 1); |
||||
} |
||||
|
||||
await ctx.xcMeta.metaUpdate( |
||||
context.workspace_id, |
||||
context.base_id, |
||||
'nc_models', |
||||
{ meta: JSON.stringify(meta) }, |
||||
{ |
||||
type: 'table', |
||||
title: dupRelation.tn, |
||||
}, |
||||
); |
||||
} |
||||
{ |
||||
const rtnModel = await ctx.xcMeta.metaGet( |
||||
ctx.baseId, |
||||
ctx.dbAlias, |
||||
'nc_models', |
||||
{ |
||||
type: 'table', |
||||
title: dupRelation.rtn, |
||||
}, |
||||
); |
||||
|
||||
const meta = JSON.parse(rtnModel.meta); |
||||
|
||||
const duplicateHms = meta.hasMany.filter( |
||||
(bt) => |
||||
bt.tn === dupRelation.tn && |
||||
bt.rtn === dupRelation.rtn && |
||||
bt.cn === dupRelation.cn && |
||||
bt.rcn === dupRelation.rcn && |
||||
bt.type === 'real', |
||||
); |
||||
|
||||
if (duplicateHms?.length > 1) { |
||||
meta.hasMany.splice(meta.hasMany.indexOf(duplicateHms[1]), 1); |
||||
} |
||||
await ctx.xcMeta.metaUpdate( |
||||
context.workspace_id, |
||||
context.base_id, |
||||
'nc_models', |
||||
{ meta: JSON.stringify(meta) }, |
||||
{ |
||||
type: 'table', |
||||
title: dupRelation.rtn, |
||||
}, |
||||
); |
||||
} |
||||
} |
||||
} catch (e) { |
||||
console.log(e); |
||||
} |
||||
} |
@ -1,176 +0,0 @@
|
||||
import autoBind from 'auto-bind'; |
||||
import BaseApiBuilder from '../BaseApiBuilder'; |
||||
import type NcProjectBuilder from '../NcProjectBuilder'; |
||||
import type { Router } from 'express'; |
||||
import type { DbConfig, NcConfig } from '~/interface/config'; |
||||
import type { MetaService } from '~/meta/meta.service'; |
||||
import type Noco from '~/Noco'; |
||||
import NcHelp from '~/utils/NcHelp'; |
||||
import ExpressXcTsRoutes from '~/db/sql-mgr/code/routes/xc-ts/ExpressXcTsRoutes'; |
||||
import SwaggerXc from '~/db/sql-mgr/code/routers/xc-ts/SwaggerXc'; |
||||
|
||||
export class RestApiBuilder extends BaseApiBuilder<Noco> { |
||||
public readonly type = 'rest'; |
||||
|
||||
protected nocoTypes: any; |
||||
protected nocoRootResolvers: any; |
||||
private routers: { [key: string]: Router }; |
||||
|
||||
constructor( |
||||
app: Noco, |
||||
baseBuilder: NcProjectBuilder, |
||||
config: NcConfig, |
||||
connectionConfig: DbConfig, |
||||
xcMeta?: MetaService, |
||||
) { |
||||
super(app, baseBuilder, config, connectionConfig); |
||||
autoBind(this); |
||||
this.routers = {}; |
||||
this.hooks = {}; |
||||
this.xcMeta = xcMeta; |
||||
} |
||||
|
||||
public async init(): Promise<void> { |
||||
await super.init(); |
||||
} |
||||
|
||||
protected async ncUpManyToMany(ctx: any): Promise<any> { |
||||
const metas = await super.ncUpManyToMany(ctx); |
||||
if (!metas) { |
||||
return; |
||||
} |
||||
for (const meta of metas) { |
||||
const ctx = this.generateContextForTable( |
||||
meta.tn, |
||||
meta.columns, |
||||
[], |
||||
meta.hasMany, |
||||
meta.belongsTo, |
||||
meta.type, |
||||
meta._tn, |
||||
); |
||||
|
||||
/* create routes for table */ |
||||
const routes = new ExpressXcTsRoutes({ |
||||
dir: '', |
||||
ctx, |
||||
filename: '', |
||||
}).getObjectWithoutFunctions(); |
||||
|
||||
/* create nc_routes, add new routes or update order */ |
||||
const routesInsertion = routes.map((route, i) => { |
||||
return async () => { |
||||
if ( |
||||
!(await this.xcMeta.metaGet( |
||||
this.baseId, |
||||
this.dbAlias, |
||||
'nc_routes', |
||||
{ |
||||
path: route.path, |
||||
tn: meta.tn, |
||||
title: meta.tn, |
||||
type: route.type, |
||||
}, |
||||
)) |
||||
) { |
||||
await this.xcMeta.metaInsert2( |
||||
context.workspace_id, |
||||
context.base_id, |
||||
'nc_routes', |
||||
{ |
||||
acl: JSON.stringify(route.acl), |
||||
handler: JSON.stringify(route.handler), |
||||
order: i, |
||||
path: route.path, |
||||
tn: meta.tn, |
||||
title: meta.tn, |
||||
type: route.type, |
||||
dbAlias: this.dbAlias, |
||||
}, |
||||
true, |
||||
); |
||||
} else { |
||||
await this.xcMeta.metaUpdate( |
||||
context.workspace_id, |
||||
context.base_id, |
||||
'nc_routes', |
||||
{ |
||||
order: i, |
||||
}, |
||||
{ |
||||
path: route.path, |
||||
tn: meta.tn, |
||||
title: meta.tn, |
||||
type: route.type, |
||||
}, |
||||
); |
||||
} |
||||
}; |
||||
}); |
||||
|
||||
await NcHelp.executeOperations( |
||||
routesInsertion, |
||||
this.connectionConfig.client, |
||||
); |
||||
} |
||||
|
||||
// add new routes
|
||||
} |
||||
|
||||
protected async getManyToManyRelations(args = {}): Promise<Set<any>> { |
||||
const metas: Set<any> = await super.getManyToManyRelations(args); |
||||
|
||||
for (const metaObj of metas) { |
||||
const ctx = this.generateContextForTable( |
||||
metaObj.tn, |
||||
metaObj.columns, |
||||
[...metaObj.belongsTo, ...metaObj.hasMany], |
||||
metaObj.hasMany, |
||||
metaObj.belongsTo, |
||||
); |
||||
|
||||
const swaggerDoc = await new SwaggerXc({ |
||||
dir: '', |
||||
ctx: { |
||||
...ctx, |
||||
v: metaObj.v, |
||||
}, |
||||
filename: '', |
||||
}).getObject(); |
||||
|
||||
const meta = await this.xcMeta.metaGet( |
||||
this.baseId, |
||||
this.dbAlias, |
||||
'nc_models', |
||||
{ |
||||
title: metaObj.tn, |
||||
type: 'table', |
||||
}, |
||||
); |
||||
const oldSwaggerDoc = JSON.parse(meta.schema); |
||||
|
||||
// // keep upto 5 schema backup on table update
|
||||
// let previousSchemas = [oldSwaggerDoc]
|
||||
// if (meta.schema_previous) {
|
||||
// previousSchemas = [...JSON.parse(meta.schema_previous), oldSwaggerDoc].slice(-5);
|
||||
// }
|
||||
|
||||
oldSwaggerDoc.definitions = swaggerDoc.definitions; |
||||
await this.xcMeta.metaUpdate( |
||||
context.workspace_id, |
||||
context.base_id, |
||||
'nc_models', |
||||
{ |
||||
schema: JSON.stringify(oldSwaggerDoc), |
||||
// schema_previous: JSON.stringify(previousSchemas)
|
||||
}, |
||||
{ |
||||
title: metaObj.tn, |
||||
type: 'table', |
||||
}, |
||||
); |
||||
} |
||||
|
||||
return metas; |
||||
} |
||||
} |
@ -1,253 +0,0 @@
|
||||
import { SqlUiFactory, UITypes } from 'nocodb-sdk'; |
||||
import type { MssqlUi, MysqlUi, OracleUi, PgUi, SqliteUi } from 'nocodb-sdk'; |
||||
|
||||
export default class NcTemplateParser { |
||||
sqlUi: |
||||
| typeof MysqlUi |
||||
| typeof MssqlUi |
||||
| typeof PgUi |
||||
| typeof OracleUi |
||||
| typeof SqliteUi; |
||||
|
||||
private _tables: any[]; |
||||
private client: string; |
||||
private _relations: any[]; |
||||
private _m2mRelations: any[]; |
||||
private _virtualColumns: { [tn: string]: any[] }; |
||||
private prefix: string; |
||||
private template: any; |
||||
|
||||
constructor({ client, template, prefix = '' }) { |
||||
this.client = client; |
||||
this.sqlUi = SqlUiFactory.create({ client }); |
||||
this.template = template; |
||||
this.prefix = prefix; |
||||
} |
||||
|
||||
public parse(template?: any): any { |
||||
const tables = []; |
||||
this.template = template || this.template; |
||||
const tableTemplates = this.template.tables.map((tableTemplate) => { |
||||
const t = { |
||||
...tableTemplate, |
||||
tn: this.getTable(tableTemplate.tn), |
||||
_tn: tableTemplate._tn || tableTemplate.tn, |
||||
}; |
||||
const table = this.extractTable(t); |
||||
tables.push(table); |
||||
return t; |
||||
}); |
||||
|
||||
this._tables = tables; |
||||
|
||||
for (const tableTemplate of tableTemplates) { |
||||
this.extractRelations(tableTemplate); |
||||
this.extractVirtualColumns(tableTemplate); |
||||
} |
||||
} |
||||
|
||||
private extractTable(tableTemplate) { |
||||
if (!tableTemplate?.tn) { |
||||
throw Error('Missing table name in template'); |
||||
} |
||||
|
||||
const defaultColumns = this.sqlUi |
||||
.getNewTableColumns() |
||||
.filter( |
||||
(column) => |
||||
column.cn !== 'title' && |
||||
(column.uidt !== 'ID' || |
||||
tableTemplate.columns.every((c) => c.uidt !== 'ID')), |
||||
); |
||||
|
||||
return { |
||||
tn: tableTemplate.tn, |
||||
_tn: tableTemplate._tn, |
||||
columns: [ |
||||
defaultColumns[0], |
||||
...this.extractTableColumns(tableTemplate.columns), |
||||
...defaultColumns.slice(1), |
||||
], |
||||
}; |
||||
} |
||||
|
||||
private extractTableColumns(tableColumns: any[]) { |
||||
const columns = []; |
||||
for (const tableColumn of tableColumns) { |
||||
if (!tableColumn?.cn) { |
||||
throw Error('Missing column name in template'); |
||||
} |
||||
switch (tableColumn.uidt) { |
||||
// case UITypes.ForeignKey:
|
||||
// // todo :
|
||||
// this.extractRelations(tableColumn, 'bt');
|
||||
// break;
|
||||
// case UITypes.LinkToAnotherRecord:
|
||||
// // todo :
|
||||
// this.extractRelations(tableColumn, 'hm');
|
||||
// // this.extractRelations(tableColumn, 'mm');
|
||||
// break;
|
||||
default: |
||||
{ |
||||
const colProp = this.sqlUi.getDataTypeForUiType(tableColumn); |
||||
columns.push({ |
||||
...this.sqlUi.getNewColumn(''), |
||||
rqd: false, |
||||
pk: false, |
||||
ai: false, |
||||
cdf: null, |
||||
un: false, |
||||
dtx: 'specificType', |
||||
dtxp: this.sqlUi.getDefaultLengthForDatatype(colProp.dt), |
||||
dtxs: this.sqlUi.getDefaultScaleForDatatype(colProp.dt), |
||||
...colProp, |
||||
_cn: tableColumn.cn, |
||||
...tableColumn, |
||||
}); |
||||
} |
||||
break; |
||||
} |
||||
} |
||||
return columns; |
||||
} |
||||
|
||||
protected extractRelations(tableTemplate) { |
||||
if (!this._relations) this._relations = []; |
||||
if (!this._m2mRelations) this._m2mRelations = []; |
||||
for (const hasMany of tableTemplate.hasMany || []) { |
||||
const childTable = this.tables.find( |
||||
(table) => table.tn === this.getTable(hasMany.tn), |
||||
); |
||||
const parentTable = this.tables.find( |
||||
(table) => table.tn === tableTemplate.tn, |
||||
); |
||||
const parentPrimaryColumn = parentTable.columns.find( |
||||
(column) => column.uidt === UITypes.ID, |
||||
); |
||||
//
|
||||
// // if duplicate relation ignore
|
||||
// if (
|
||||
// this._relations.some(rl => {
|
||||
// return (
|
||||
// (rl.childTable === childTable.tn &&
|
||||
// rl.parentTable === parentTable.tn) ||
|
||||
// (rl.parentTable === childTable.tn &&
|
||||
// rl.childTable === parentTable.tn)
|
||||
// );
|
||||
// })
|
||||
// ) {
|
||||
// continue;f
|
||||
// }
|
||||
|
||||
// add a column in child table
|
||||
const childColumnName = `${tableTemplate.tn}_id`; |
||||
|
||||
childTable.columns.push({ |
||||
column_name: childColumnName, |
||||
_cn: childColumnName, |
||||
rqd: false, |
||||
pk: false, |
||||
ai: false, |
||||
cdf: null, |
||||
dt: parentPrimaryColumn.dt, |
||||
dtxp: parentPrimaryColumn.dtxp, |
||||
dtxs: parentPrimaryColumn.dtxs, |
||||
un: parentPrimaryColumn.un, |
||||
altered: 1, |
||||
}); |
||||
|
||||
// add relation create entry
|
||||
this._relations.push({ |
||||
childColumn: childColumnName, |
||||
childTable: childTable.tn, |
||||
onDelete: 'NO ACTION', |
||||
onUpdate: 'NO ACTION', |
||||
parentColumn: parentPrimaryColumn.cn, |
||||
parentTable: tableTemplate.tn, |
||||
type: this.client === 'sqlite3' ? 'virtual' : 'real', |
||||
updateRelation: false, |
||||
}); |
||||
} |
||||
for (const manyToMany of tableTemplate.manyToMany || []) { |
||||
// @ts-ignore
|
||||
const childTable = this.tables.find( |
||||
(table) => table.tn === this.getTable(manyToMany.rtn), |
||||
); |
||||
const parentTable = this.tables.find( |
||||
(table) => table.tn === tableTemplate.tn, |
||||
); |
||||
const parentPrimaryColumn = parentTable.columns.find( |
||||
(column) => column.uidt === UITypes.ID, |
||||
); |
||||
const childPrimaryColumn = childTable.columns.find( |
||||
(column) => column.uidt === UITypes.ID, |
||||
); |
||||
|
||||
// if duplicate relation ignore
|
||||
if ( |
||||
this._m2mRelations.some((mm) => { |
||||
return ( |
||||
(mm.childTable === childTable.tn && |
||||
mm.parentTable === parentTable.tn) || |
||||
(mm.parentTable === childTable.tn && |
||||
mm.childTable === parentTable.tn) |
||||
); |
||||
}) |
||||
) { |
||||
continue; |
||||
} |
||||
|
||||
// add many to many relation create entry
|
||||
this._m2mRelations.push({ |
||||
alias: 'title8', |
||||
childColumn: childPrimaryColumn.cn, |
||||
childTable: childTable.tn, |
||||
onDelete: 'NO ACTION', |
||||
onUpdate: 'NO ACTION', |
||||
parentColumn: parentPrimaryColumn.cn, |
||||
parentTable: parentTable.tn, |
||||
type: this.client === 'sqlite3' ? 'virtual' : 'real', |
||||
updateRelation: false, |
||||
}); |
||||
} |
||||
} |
||||
|
||||
private extractVirtualColumns(tableMeta) { |
||||
if (!this._virtualColumns) this._virtualColumns = {}; |
||||
const virtualColumns = []; |
||||
for (const v of tableMeta.v || []) { |
||||
const v1 = { ...v }; |
||||
|
||||
if (v.rl) { |
||||
v1.rl.rlttn = v1.rl.rltn; |
||||
v1.rl.rltn = this.getTable(v1.rl.rltn); |
||||
} else if (v.lk) { |
||||
v1.lk._ltn = v1.lk.ltn; |
||||
v1.lk.ltn = this.getTable(v1.lk.ltn); |
||||
} |
||||
|
||||
virtualColumns.push(v1); |
||||
} |
||||
this.virtualColumns[tableMeta.tn] = virtualColumns; |
||||
} |
||||
|
||||
get tables(): any[] { |
||||
return this._tables; |
||||
} |
||||
|
||||
get relations(): any[] { |
||||
return this._relations; |
||||
} |
||||
|
||||
get m2mRelations(): any[] { |
||||
return this._m2mRelations; |
||||
} |
||||
|
||||
get virtualColumns(): { [tn: string]: any[] } { |
||||
return this._virtualColumns; |
||||
} |
||||
|
||||
private getTable(tn) { |
||||
return `${this.prefix}${tn}`; |
||||
} |
||||
} |
Loading…
Reference in new issue