Skip to content

Commit

Permalink
Refactored
Browse files Browse the repository at this point in the history
  • Loading branch information
Chris Nurse committed Oct 11, 2022
1 parent 07fabca commit b683b6c
Show file tree
Hide file tree
Showing 3 changed files with 255 additions and 84 deletions.
173 changes: 173 additions & 0 deletions src/CrudioMongooseDataModel.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
import { model } from "mongoose";
import CrudioDataModel from "./CrudioDataModel";
import CrudioEntityDefinition from "./CrudioEntityDefinition";
import CrudioTable from "./CrudioTable";
import { ICrudioConfig } from "./CrudioTypes";

/**
* Definition of schema and models for Mongoose
* @date 11/10/2022 - 14:31:36
*
* @export
* @class CrudioMongooseDataModel
* @typedef {CrudioMongooseDataModel}
*/
export default class CrudioMongooseDataModel {
/**
* Schema map
* @date 11/10/2022 - 14:31:36
*
* @private
* @type {*}
*/
private schema: any = {};
/**
* Models map
* @date 11/10/2022 - 14:31:36
*
* @private
* @type {*}
*/
private models: any = {};

/**
* Schema map
* @date 11/10/2022 - 14:31:36
*
* @public
* @readonly
* @type {*}
*/
public get Schema(): any {
return this.schema;
}

/**
* Models map
* @date 11/10/2022 - 14:31:36
*
* @public
* @readonly
* @type {*}
*/
public get Models(): any {
return this.models;
}

/**
* Constructor
* @date 7/18/2022 - 1:46:23 PM
*
* @constructor
* @param {ICrudioConfig} config
* @param {CrudioDataModel} datamodel
*/
constructor(private config: ICrudioConfig, private datamodel: CrudioDataModel) {
if (datamodel.TargetDbSchema)
this.config.schema = datamodel.TargetDbSchema;
this.CreateSchemaModels();
}

/**
* Create all schema and models
* @date 11/10/2022 - 14:31:36
*
* @private
*/
private CreateSchemaModels() {
// First pass create all required schema
this.datamodel.Tables.map(t => {
this.schema[t.TableName] = this.CreateSchemaForTable(t);
});

// Second pass connect foreign keys and create models
this.datamodel.Tables.map(t => {
this.AssignForeignKeys(t.EntityDefinition);
this.models[t.TableName] = model(t.TableName, this.schema[t.TableName]);
});
}

/**
* Create a schema for a table definition
* @date 11/10/2022 - 14:31:36
*
* @private
* @param {CrudioTable} table
* @returns {*}
*/
private CreateSchemaForTable(table: CrudioTable): any {
const schema = {};

table.EntityDefinition.fields.map(f => {
const field = {};
field["type"] = this.GetMongooseFieldType(f.fieldType);
schema[f.fieldName] = field;
});

return schema;
}

/**
* Convert a data type to Mongoose field type
* @date 11/10/2022 - 14:31:36
*
* @private
* @param {string} fieldType
* @returns {*}
*/
private GetMongooseFieldType(fieldType: string): any {
switch (fieldType.toLocaleLowerCase()) {
case "uuid":
case "string":
return "String";

case "boolean":
return "Boolean";

case "integer":
return "Number";

case "decimal":
return "Number";

case "timestamp":
case "date":
return "Date";

case "array":
return "Array;";

case "jsonb":
return "Map;";

default:
throw new Error(`'${fieldType}' has no assigned equivalent in Mongoose`);
}
}

/**
* Assign foreign keys to the one and many ends of a relationship
* @date 11/10/2022 - 14:31:36
*
* @private
* @param {CrudioEntityDefinition} entity
* @returns {*}
*/
private AssignForeignKeys(entity: CrudioEntityDefinition): any {
const key_map = {};

// add foreign keys to insert columns for one to many
entity.OneToManyRelationships.map(r => {

const from_entity = this.datamodel.GetEntityDefinition(r.FromEntity);
const to_entity = this.datamodel.GetEntityDefinition(r.ToEntity);
const from_schema = this.schema[from_entity.TableName];
const to_schema = this.schema[to_entity.TableName];

from_schema[to_entity.TableName] = { type: String, ref: to_entity.TableName };
to_schema[from_entity.TableName] = [{ type: String, ref: from_entity.TableName }];
});

return key_map;
}
}
159 changes: 76 additions & 83 deletions src/CrudioMongooseWrapper.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,56 @@
import mongoose, { Schema } from "mongoose";
import mongoose from "mongoose";

import { ICrudioConfig } from "./CrudioTypes";
import CrudioDataModel from "./CrudioDataModel";
import CrudioEntityDefinition from "./CrudioEntityDefinition";
import CrudioField from "./CrudioField";
import CrudioMongooseDataModel from "./CrudioMongooseDataModel";
import CrudioTable from "./CrudioTable";
import { ICrudioConfig } from "./CrudioTypes";


/**
* Provide basic data insertion capabilities to populate a database
* @date 11/10/2022 - 14:28:24
*
* @export
* @class CrudioMongooseWrapper
* @typedef {CrudioMongooseWrapper}
*/
export default class CrudioMongooseWrapper {
private schema: any = {};
/**
* Reference to the mongoose schema and models
* @date 11/10/2022 - 14:28:24
*
* @private
* @type {CrudioMongooseDataModel}
*/
private data_model: CrudioMongooseDataModel;

/**
* Creates an instance of CrudioMongoose.
* Schema map
* @date 11/10/2022 - 14:28:24
*
* @public
* @readonly
* @type {*}
*/
public get Schema(): any {
return this.data_model.Schema;
}

/**
* Models map
* @date 11/10/2022 - 14:28:24
*
* @public
* @readonly
* @type {*}
*/
public get Models(): any {
return this.data_model.Models;
}

/**
* Constructor
* @date 7/18/2022 - 1:46:23 PM
*
* @constructor
Expand All @@ -20,10 +59,12 @@ export default class CrudioMongooseWrapper {
*/
constructor(private config: ICrudioConfig, private datamodel: CrudioDataModel) {
if (datamodel.TargetDbSchema) this.config.schema = datamodel.TargetDbSchema;

this.data_model = new CrudioMongooseDataModel(config, datamodel);
}

/**
* Drop schema and recreate with no tables
* Drop all collections in the database
* @date 7/18/2022 - 1:46:23 PM
*
* @public
Expand All @@ -43,20 +84,15 @@ export default class CrudioMongooseWrapper {
}
}

public CreateMongooseSchema() {
this.datamodel.Tables.map(t => {
const schema = this.GetMongooseSchema(t);
this.schema[t.TableName] = schema;
});

this.datamodel.Tables.map(t => {
this.AssignForeignKeys(t.EntityDefinition);
});
}

/**
* Populate database tables from memory based tables
* @date 11/10/2022 - 14:28:24
*
* @public
* @async
* @returns {Promise<void>}
*/
public async PopulateDatabaseTables(): Promise<void> {
this.CreateMongooseSchema();

for (var index = 0; index < this.datamodel.Tables.length; index++) {
const table: CrudioTable = this.datamodel.Tables[index];

Expand All @@ -66,18 +102,16 @@ export default class CrudioMongooseWrapper {
}

/**
* Build the SQL to insert values into data tables
* Insert data into the specified table
* @date 7/18/2022 - 1:46:23 PM
*
* @private
* @param {CrudioTable} table
* @param {SqlInstructionList} instructions
*/
private async InsertData(table: CrudioTable): Promise<void> {
console.log("Loading ", table.TableName);
const schema = this.schema[table.TableName];

var model = mongoose.model(table.TableName, schema);
var model = this.Models[table.TableName];

for (var r = 0; r < table.DataRows.length; r++) {
let data = table.DataRows[r].DataValues;
Expand Down Expand Up @@ -115,46 +149,14 @@ export default class CrudioMongooseWrapper {
}
}

public GetMongooseSchema(table: CrudioTable): any {
const schema = {
}

table.EntityDefinition.fields.map(f => {
const field = {};
field["type"] = this.GetMongooseFieldType(f.fieldType);
schema[f.fieldName] = field;
});

return schema
}

public GetMongooseFieldType(fieldType: string): any {
switch (fieldType.toLocaleLowerCase()) {
case "uuid":
case "string":
return "String";

case "boolean":
return "Boolean";

case "integer":
return "Number";

case "decimal":
return "Number";

case "timestamp":
case "date":
return "Date";

case "array":
return "Array;"

case "jsonb":
return "Map;"
}
}

/**
* Get column names from the entity definition
* @date 11/10/2022 - 14:28:24
*
* @private
* @param {CrudioEntityDefinition} entity
* @returns {string[]}
*/
private GetColumns(entity: CrudioEntityDefinition): string[] {
const table_field_list = [];

Expand All @@ -167,30 +169,21 @@ export default class CrudioMongooseWrapper {
return table_field_list;
}

private AssignForeignKeys(entity: CrudioEntityDefinition): any {
const key_map = {};

// add foreign keys to insert columns for one to many
entity.OneToManyRelationships.map(r => {

const from_entity = this.datamodel.GetEntityDefinition(r.FromEntity);
const to_entity = this.datamodel.GetEntityDefinition(r.ToEntity);
const from_schema = this.schema[from_entity.TableName];
const to_schema = this.schema[to_entity.TableName];

from_schema[to_entity.TableName] = { type: String, ref: to_entity.TableName };
to_schema[from_entity.TableName] = [{ type: String, ref: from_entity.TableName }];
});

return key_map;
}

private GetForeignKeyValues(entity: CrudioEntityDefinition, values: any): any {
/**
* Get the IDs of foreign tables which are referenced by entity values
* @date 11/10/2022 - 14:28:24
*
* @private
* @param {CrudioEntityDefinition} entity
* @param {*} entity_values
* @returns {*}
*/
private GetForeignKeyValues(entity: CrudioEntityDefinition, entity_values: any): any {
const key_map = {};

// add foreign keys to insert columns for one to many
entity.OneToManyRelationships.map(r => {
const source = values[r.FromColumn].dataValues;
const source = entity_values[r.FromColumn].dataValues;
const entity = this.datamodel.GetEntityDefinition(r.ToEntity);

key_map[entity.TableName] = source[this.config.idField];
Expand Down
Loading

0 comments on commit b683b6c

Please sign in to comment.