diff --git a/lib/constants/operations.js b/lib/constants/operations.js index 61bc87f..2eac198 100644 --- a/lib/constants/operations.js +++ b/lib/constants/operations.js @@ -6,6 +6,7 @@ const operations = { UPDATE_NODE: "update_node", REMOVE_NODE: "remove_node", DESCRIBE_ALL: "describe_all", + CREATE_ATTRIBUTE:"create_attribute", CREATE_SCHEMA: "create_schema", DESCRIBE_SCHEMA: "describe_schema", DROP_SCHEMA: "drop_schema", diff --git a/lib/core/harpeeHttp.js b/lib/core/harpeeHttp.js index 953ce87..12d11d9 100644 --- a/lib/core/harpeeHttp.js +++ b/lib/core/harpeeHttp.js @@ -58,7 +58,7 @@ class HarpeeHttp { /** * * @param {Object} reqBody - * @param {function} [callback] + * @param {(err:any,result:({[key:string]:any}|{[key:string]:any}[]))=>void} [callback] * @param {boolean} [single=false] * @returns {(void|Promise)} * @protected diff --git a/lib/core/harpeeModel.js b/lib/core/harpeeModel.js index 037341f..9bdd1d3 100644 --- a/lib/core/harpeeModel.js +++ b/lib/core/harpeeModel.js @@ -34,25 +34,30 @@ class HarpeeModel extends HarpeeHttp { const schemaName = schemaObject.name; /** *@private + @readonly */ this.schemaName = schemaName; /** *@private + @readonly */ this.modelName = modelName; /** * @private + * @readonly */ this.schemaFields = schemaObject.fields; const { primaryKey } = schemaObject; /** * @private + * @readonly */ this.primaryKey = primaryKey; /** * @private + * @readonly */ this.silent = schemaObject.silent; @@ -60,16 +65,17 @@ class HarpeeModel extends HarpeeHttp { } /** - * This creates the schema & table if they don't exist yet. - * **you should get rid of this after use.** + * This creates the schema, table, and the attributes specified in Schema.`fields`, if they don't exist. + * **you should get rid of this after running your app atleast once.** * @returns void; */ async init() { try { - + const schema=this.schemaName; + const table=this.modelName; const createSchema = async () => this.$callbackOrPromise({ operation: operations.CREATE_SCHEMA, - schema: this.schemaName + schema }); const describeAll = async () => this.$callbackOrPromise({ @@ -79,24 +85,58 @@ class HarpeeModel extends HarpeeHttp { const createTable = async () => this.$callbackOrPromise({ operation: operations.CREATE_TABLE, - schema: this.schemaName, - table: this.modelName, + schema, + table, hash_attribute: this.primaryKey, }); + const createAttribute = async (attribute) => this.$callbackOrPromise({ + operation: operations.CREATE_ATTRIBUTE, + schema, + table, + attribute + }); - +// get information about the database const respA = await describeAll(); - if (!(respA[this.schemaName])) { + // check if the schema already exist, else create it + if (!(respA[schema])) { await createSchema() } - +// get information about the database const respB = await describeAll(); - - if (!(respB[this.schemaName] && respB[this.schemaName][this.modelName])) { +// check if the table already exist, else create it + if (!(respB[schema] && respB[schema][table])) { await createTable() } + + // get information about the database +const respC=await describeAll(); + +// get fields from Schema.`fields` +const fields=this.schemaFields; + +// turn the fields object into an array of strings +const attributes=util.splitObject(fields).keys; +// get previous attributes from the table +const previousAttributes=respC[schema][table]['attributes']; + +// turn the previous attributes object into an array of strings +const previousAttributesValues=util.ObjectArrayToStringArray(previousAttributes); + +// loop through attributes from `fields` +const attributeLoop=async()=>{ + for(let attribute of attributes){ + // create the attribute if it's not in the previous attribute + if(!previousAttributesValues.includes(attribute)){ + + await createAttribute(attribute); + } + } + +} +await attributeLoop(); } catch (err) { diff --git a/lib/core/harpeeSchema.js b/lib/core/harpeeSchema.js index 872958b..1140f26 100644 --- a/lib/core/harpeeSchema.js +++ b/lib/core/harpeeSchema.js @@ -6,7 +6,7 @@ const util = require("../helpers/util"); */ class HarpeeSchema{ /** - * Let's you specify your schema name, also configure your table's columns and types. + * Let's you specify the chema name, also configure your table's column names. * * @param {HarpeeSchemaConfig} schemaConfig */ diff --git a/lib/helpers/util.js b/lib/helpers/util.js index 9bea5f6..e4b3fe6 100644 --- a/lib/helpers/util.js +++ b/lib/helpers/util.js @@ -134,6 +134,24 @@ const util = { }); return { keys, values }; }, + /** + * + * @param {{[key:string]:any}[]} arrayOfObj - an array of objects + * @param {boolean} [keys] - when true, returns object keys otherwise object values + * @returns {string[]} + */ + ObjectArrayToStringArray(arrayOfObj,keys=false){ + if(!Array.isArray(arrayOfObj)){ + return [] + } + return arrayOfObj.reduce((accum,item)=>{ + for(let key in item){ + keys ? accum.push(key) : accum.push(item[key]); + } + return accum; + },[]) + }, + /** Splits a string by a seperator and returns the last string * @param {string} str - the string to be splitted. * diff --git a/package-lock.json b/package-lock.json index 75d8ffc..37bf08e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "harpee", - "version": "3.0.12", + "version": "3.0.13", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "harpee", - "version": "3.0.12", + "version": "3.0.13", "license": "MIT", "dependencies": { "axios": "^0.27.1" diff --git a/package.json b/package.json index d53d8d2..bb57cab 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "harpee", - "version": "3.0.13", + "version": "3.1.0", "description": "Harpee is a modeling tool for HarperDB, harpee supports both callbacks and Promises.", "main": "./dist/index.js", "types": "./types/index.d.ts", diff --git a/types/constants/operations.d.ts b/types/constants/operations.d.ts index 8726a2a..cf69676 100644 --- a/types/constants/operations.d.ts +++ b/types/constants/operations.d.ts @@ -5,6 +5,7 @@ export const ADD_NODE: string; export const UPDATE_NODE: string; export const REMOVE_NODE: string; export const DESCRIBE_ALL: string; +export const CREATE_ATTRIBUTE: string; export const CREATE_SCHEMA: string; export const DESCRIBE_SCHEMA: string; export const DROP_SCHEMA: string; diff --git a/types/core/harpeeHttp.d.ts b/types/core/harpeeHttp.d.ts index e49fe41..2581211 100644 --- a/types/core/harpeeHttp.d.ts +++ b/types/core/harpeeHttp.d.ts @@ -15,10 +15,14 @@ declare class HarpeeHttp { /** * * @param {Object} reqBody - * @param {function} [callback] + * @param {(err:any,result:({[key:string]:any}|{[key:string]:any}[]))=>void} [callback] * @param {boolean} [single=false] * @returns {(void|Promise)} * @protected */ - protected $callbackOrPromise(reqBody: any, callback?: Function, single?: boolean): (void | Promise); + protected $callbackOrPromise(reqBody: any, callback?: (err: any, result: { + [key: string]: any; + } | { + [key: string]: any; + }[]) => void, single?: boolean): (void | Promise); } diff --git a/types/core/harpeeModel.d.ts b/types/core/harpeeModel.d.ts index d361db0..fd90d44 100644 --- a/types/core/harpeeModel.d.ts +++ b/types/core/harpeeModel.d.ts @@ -13,27 +13,32 @@ declare class HarpeeModel extends HarpeeHttp { constructor(modelName: string, schemaObject: HarpeeSchema); /** *@private + @readonly */ - private schemaName; + private readonly schemaName; /** *@private + @readonly */ - private modelName; + private readonly modelName; /** * @private + * @readonly */ - private schemaFields; + private readonly schemaFields; /** * @private + * @readonly */ - private primaryKey; + private readonly primaryKey; /** * @private + * @readonly */ - private silent; + private readonly silent; /** - * This creates the schema & table if they don't exist yet. - * **you should get rid of this after use.** + * This creates the schema, table, and the attributes specified in Schema.`fields`, if they don't exist. + * **you should get rid of this after running your app atleast once.** * @returns void; */ init(): Promise; diff --git a/types/core/harpeeSchema.d.ts b/types/core/harpeeSchema.d.ts index fa9890d..a3edcf0 100644 --- a/types/core/harpeeSchema.d.ts +++ b/types/core/harpeeSchema.d.ts @@ -5,7 +5,7 @@ export = HarpeeSchema; */ declare class HarpeeSchema { /** - * Let's you specify your schema name, also configure your table's columns and types. + * Let's you specify the chema name, also configure your table's column names. * * @param {HarpeeSchemaConfig} schemaConfig */ diff --git a/types/helpers/util.d.ts b/types/helpers/util.d.ts index 03f66e8..02af30a 100644 --- a/types/helpers/util.d.ts +++ b/types/helpers/util.d.ts @@ -21,6 +21,24 @@ export function splitObjectSorted(obj: any): { keys: any[]; values: any[]; }; +/** + * + * @param {{[key:string]:any}[]} arrayOfObj - an array of objects + * @param {boolean} [keys] - when true, returns object keys otherwise object values + * @returns {string[]} + */ +export function ObjectArrayToStringArray(arrayOfObj: { + [key: string]: any; +}[], keys?: boolean): string[]; +/** + * + * @param {{[key:string]:any}[]} arrayOfObj - an array of objects + * @param {boolean} [keys] - when true, returns object keys otherwise object values + * @returns {string[]} + */ +export function ObjectArrayToStringArray(arrayOfObj: { + [key: string]: any; +}[], keys?: boolean): string[]; export function getExtname(str: string): string; export function getFirst(str: string, seperator: any): string; export function objectToArray(obj: any, seperator?: string): any[];