From e7be2079112d062d0b8439ffe8a259c184e7ff4f Mon Sep 17 00:00:00 2001 From: "Dzmitry_Tamashevich@epam.com" Date: Thu, 1 Oct 2020 01:08:02 +0300 Subject: [PATCH] add cli tool --- media-store/.vscode/launch.json | 9 +++- media-store/db/schema.cds | 56 ++++++++++++++++++++----- media-store/package.json | 3 +- media-store/srv/media-service.cds | 12 +++++- media-store/util/importData.js | 70 +++++++++++++++++++++++++++++++ 5 files changed, 136 insertions(+), 14 deletions(-) create mode 100644 media-store/util/importData.js diff --git a/media-store/.vscode/launch.json b/media-store/.vscode/launch.json index 3f308a6c..51b33553 100644 --- a/media-store/.vscode/launch.json +++ b/media-store/.vscode/launch.json @@ -4,12 +4,19 @@ // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 "version": "0.2.0", "configurations": [ + { + "name": "Launch Program", + "command": "npm run import:data", + "request": "launch", + "skipFiles": ["/**"], + "type": "node-terminal" + }, { "command": "cds run --with-mocks --in-memory?", "name": "cds run", "request": "launch", "type": "node-terminal", - "skipFiles": [ "/**" ] + "skipFiles": ["/**"] } ] } diff --git a/media-store/db/schema.cds b/media-store/db/schema.cds index 614d6e3f..1d3b3d32 100644 --- a/media-store/db/schema.cds +++ b/media-store/db/schema.cds @@ -6,8 +6,9 @@ aspect NamedEntityAspect { } aspect ContactInfoAspect { - firstName : String(40); + key ID : Integer; lastName : String(20); + firstName : String(40); city : String(40); state : String(40); adress : String(70); @@ -35,18 +36,51 @@ entity Albums { artist : Association to Artists; } -entity Employees : ContactInfoAspect { - key ID : Integer; - reportsTo : Association to Employees; - title : String(20); - birthDate : DateTime; - hireDate : DateTime; +// entity Employees : ContactInfoAspect { +// reportsTo : Association to Employees; +// title : String(20); +// birthDate : DateTime; +// hireDate : DateTime; +// } + +// entity Customers : ContactInfoAspect { +// company : String(80); +// supportRep : Association to Employees; +// } + +// keep columns order for importing data +entity Employees { + key ID : Integer; + lastName : String(20); + firstName : String(40); + title : String(20); + reportsTo : Association to Employees; + birthDate : DateTime; + hireDate : DateTime; + adress : String(70); + city : String(40); + state : String(40); + country : String(40); + postalCode : String(10); + phone : String(24); + fax : String(24); + email : String(60); } -entity Customers : ContactInfoAspect { - key ID : Integer; - company : String(80); - supportRepId : Association to Employees; +entity Customers { + key ID : Integer; + firstName : String(40); + lastName : String(20); + company : String(80); + adress : String(70); + city : String(40); + state : String(40); + country : String(40); + postalCode : String(10); + phone : String(24); + fax : String(24); + email : String(60); + supportRep : Association to Employees; } entity Invoices { diff --git a/media-store/package.json b/media-store/package.json index a36c641d..ff454e81 100644 --- a/media-store/package.json +++ b/media-store/package.json @@ -13,7 +13,8 @@ "sqlite3": "^5" }, "scripts": { - "start": "npx cds run" + "start": "npx cds run", + "import:data": "node ./util/importData.js sqlite:chinook.db sqlite:mychinook.db ./db/schema.cds" }, "cds": { "requires": { diff --git a/media-store/srv/media-service.cds b/media-store/srv/media-service.cds index 56865f9f..b978967d 100644 --- a/media-store/srv/media-service.cds +++ b/media-store/srv/media-service.cds @@ -1,5 +1,15 @@ -using {sap.capire.media.store as my} from '../db/schema'; +using { sap.capire.media.store as my } from '../db/schema'; service MediaService { entity Employees as projection on my.Employees; + entity Customers as projection on my.Customers; + entity Albums as projection on my.Albums; + entity Artists as projection on my.Artists; + entity Genres as projection on my.Genres; + entity InvoiceItems as projection on my.InvoiceItems; + entity Invoices as projection on my.Invoices; + entity MediaTypes as projection on my.MediaTypes; + entity PlaylistTrack as projection on my.PlaylistTrack; + entity Playlists as projection on my.Playlists; + entity Tracks as projection on my.Tracks; } diff --git a/media-store/util/importData.js b/media-store/util/importData.js new file mode 100644 index 00000000..08707497 --- /dev/null +++ b/media-store/util/importData.js @@ -0,0 +1,70 @@ +const cds = require("@sap/cds"); + +const FIRST_INDEX = 0; +const SECOND_INDEX = 1; +const SKIP_CLI_ARGS_NUMBER = 2; +const THIRD_INDEX = 3; + +const toValues = (object) => Object.values(object); + +const camelCaseToSnake = (str) => + str.replace( + /[a-z][A-Z]/g, + (letters) => + `${letters[FIRST_INDEX].toLowerCase()}_${letters[ + SECOND_INDEX + ].toLowerCase()}` + ); + +const elementsToColumns = (elements) => { + return Object.values(elements).map((element) => + element.target ? `${element.name}_ID` : element.name + ); +}; + +const constructInsertQuery = (targetEntityName, columns) => { + return (data) => INSERT.into(targetEntityName).columns(columns).rows(data); +}; + +(async () => { + const args = process.argv.slice(SKIP_CLI_ARGS_NUMBER); + const SRC_STORAGE_NAME = args[FIRST_INDEX]; + const TARGET_STORAGE_NAME = args[SECOND_INDEX]; + const TARGET_SCHEMA_PATH = args[THIRD_INDEX]; + console.log( + "[LOG]: Import data from", + SRC_STORAGE_NAME, + "to", + TARGET_STORAGE_NAME + ); + + try { + const srcStorage = await cds.connect.to(SRC_STORAGE_NAME); + const targetStorage = await cds.connect.to(TARGET_STORAGE_NAME); + + const eList = targetStorage.entities; + + const targetCSNModel = await cds.load(TARGET_SCHEMA_PATH); + const reflectedCSNModel = cds.reflect(targetCSNModel); + const targetCSNEntities = Object.values(reflectedCSNModel.entities); + + for (index in targetCSNEntities) { + const { name: targetEntityName, elements } = targetCSNEntities[index]; + const targetColumns = elementsToColumns(elements); + const insertQuery = constructInsertQuery(targetEntityName, targetColumns); + + const srcEntityName = camelCaseToSnake(targetEntityName.split(".").pop()); + const srcResultRows = (await srcStorage.read(srcEntityName)).map( + toValues + ); + + console.log("[LOG]: From", srcEntityName, "to", targetEntityName); + + const transaction = await targetStorage.tx(); + await transaction.run(srcResultRows.map(insertQuery)); + await transaction.commit(); + } + } catch (errors) { + console.error(errors); + } +})();