Skip to content
This repository was archived by the owner on Jan 24, 2023. It is now read-only.

Commit 52fd609

Browse files
committed
feat(server): Added command server:sync
1 parent f846c8e commit 52fd609

8 files changed

Lines changed: 240 additions & 24 deletions

File tree

packages/@simpli/cli-server/generator/index.js

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -8,25 +8,27 @@ module.exports = (api, options) => {
88
const dir = options.serverSetup.packageDir
99
const moduleName = options.serverSetup.moduleName
1010

11-
// From root
12-
api.renderFrom('./injected', 'src/main/AppProvider.kt', `./java/${dir}/AppProvider.kt`)
13-
api.renderFrom('./injected', 'src/main/RouterWrapper.kt', `./java/${dir}/RouterWrapper.kt`)
14-
api.renderFrom('./injected', 'src/main/SwaggerInit.kt', `./java/${dir}/SwaggerInit.kt`)
11+
if (!options.sync) {
12+
// From root
13+
api.renderFrom('./injected', 'src/main/AppProvider.kt', `./java/${dir}/AppProvider.kt`)
14+
api.renderFrom('./injected', 'src/main/RouterWrapper.kt', `./java/${dir}/RouterWrapper.kt`)
15+
api.renderFrom('./injected', 'src/main/SwaggerInit.kt', `./java/${dir}/SwaggerInit.kt`)
1516

16-
// Router
17-
api.renderFrom('./injected', 'src/main/module/Router.kt', `../java/${dir}/${moduleName}/Router.kt`)
17+
// Router
18+
api.renderFrom('./injected', 'src/main/module/Router.kt', `../java/${dir}/${moduleName}/Router.kt`)
1819

19-
// Login Controller
20-
api.renderFrom('./injected', 'src/main/module/process/LoginService.kt', `../../java/${dir}/${moduleName}/process/LoginService.kt`)
21-
api.renderFrom('./injected', 'src/main/module/response/LoginResp.kt', `../../java/${dir}/${moduleName}/response/LoginResp.kt`)
22-
api.renderFrom('./injected', 'src/main/dao/LoginServiceDao.kt', `../java/${dir}/dao/LoginServiceDao.kt`)
20+
// Login Controller
21+
api.renderFrom('./injected', 'src/main/module/process/LoginService.kt', `../../java/${dir}/${moduleName}/process/LoginService.kt`)
22+
api.renderFrom('./injected', 'src/main/module/response/LoginResp.kt', `../../java/${dir}/${moduleName}/response/LoginResp.kt`)
23+
api.renderFrom('./injected', 'src/main/dao/LoginServiceDao.kt', `../java/${dir}/dao/LoginServiceDao.kt`)
2324

24-
// Exception
25-
api.renderFrom('./injected', 'src/main/exception/HttpException.kt', `../java/${dir}/exception/HttpException.kt`)
25+
// Exception
26+
api.renderFrom('./injected', 'src/main/exception/HttpException.kt', `../java/${dir}/exception/HttpException.kt`)
2627

27-
// Test
28-
api.renderFrom('./injected', 'src/test/module/process/LoginServiceTest.kt', `../../java/${dir}/${moduleName}/process/LoginServiceTest.kt`)
29-
api.renderFrom('./injected', 'src/test/OtherTest.kt', `./java/${dir}/OtherTest.kt`)
28+
// Test
29+
api.renderFrom('./injected', 'src/test/module/process/LoginServiceTest.kt', `../../java/${dir}/${moduleName}/process/LoginServiceTest.kt`)
30+
api.renderFrom('./injected', 'src/test/OtherTest.kt', `./java/${dir}/OtherTest.kt`)
31+
}
3032

3133
commonTables.forEach((table) => {
3234
const data = { table }
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
<%_ var config = options.serverSetup _%>
2+
SERVER_NAME=<%-config.serverName%>
3+
MODULE_NAME=<%-config.moduleName%>
4+
PACKAGE_ADDRESS=<%-config.packageAddress%>

packages/@simpli/cli/bin/simpli.js

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ program
3636

3737
program
3838
.command('scaffold:sync')
39-
.description('sync the current frontend project based in its webserver swagger')
39+
.description('sync the current frontend project based on its webserver swagger')
4040
.action(() => {
4141
require('../lib/cmd/scaffoldSync')()
4242
})
@@ -48,6 +48,13 @@ program
4848
require('../lib/cmd/serverInspect')(paths)
4949
})
5050

51+
program
52+
.command('server:sync')
53+
.description('sync the current backend project based on its database')
54+
.action(() => {
55+
require('../lib/cmd/serverSync')()
56+
})
57+
5158
// output help information on unknown commands
5259
program
5360
.arguments('<command>')
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
/* eslint-disable handle-callback-err */
2+
const fs = require('fs')
3+
const path = require('path')
4+
const clearConsole = require('../util/clearConsole')
5+
const inquirer = require('inquirer')
6+
const { error, stopSpinner } = require('@vue/cli-shared-utils')
7+
const Server = require('../server/Server')
8+
const execa = require('execa')
9+
const xml2js = require('xml2js')
10+
11+
async function sync () {
12+
require('dotenv').config()
13+
14+
const serverName = process.env.SERVER_NAME
15+
const moduleName = process.env.MODULE_NAME
16+
const packageAddress = process.env.PACKAGE_ADDRESS
17+
18+
const targetDir = path.resolve('./')
19+
const pom = path.resolve('./pom.xml')
20+
const context = path.resolve('./src/main/webapp/META-INF/context.xml')
21+
const parser = new xml2js.Parser()
22+
23+
const run = (command, args) => {
24+
if (!args) { [command, ...args] = command.split(/\s+/) }
25+
return execa(command, args, { cwd: targetDir })
26+
}
27+
28+
try {
29+
const hasFilesToCommit = await run('git status --porcelain')
30+
if (hasFilesToCommit.stdout) {
31+
error('This project has files to commit. Commit them to proceed.')
32+
process.exit(1)
33+
}
34+
} catch (e) {
35+
error('Git hasn\'t initialized')
36+
process.exit(1)
37+
}
38+
39+
if (!fs.existsSync(pom)) {
40+
error('The current directory is not the root of a simpli backend project')
41+
process.exit(1)
42+
}
43+
44+
let serverConfig = { serverName, moduleName, packageAddress }
45+
if (!serverName || !moduleName || !packageAddress) {
46+
const { confirm } = await inquirer.prompt([
47+
{
48+
name: 'confirm',
49+
type: 'confirm',
50+
message: 'Can\'t find the server config. Do you want to define the configuration?'
51+
}
52+
])
53+
54+
if (!confirm) {
55+
process.exit(1)
56+
}
57+
58+
serverConfig = null
59+
}
60+
61+
const injectData = (data, connection) => {
62+
const url = data.url
63+
const pattern = /^(?:\w+:)*(?:mysql:\/\/)(\w+):(\d+)\/(\w+)$/g
64+
const match = pattern.exec(url)
65+
if (match) {
66+
connection.host = match[1]
67+
connection.port = match[2]
68+
connection.database = match[3]
69+
connection.user = data.username
70+
connection.password = data.password
71+
}
72+
}
73+
74+
const connection = {
75+
host: null,
76+
port: null,
77+
user: null,
78+
password: null,
79+
database: null
80+
}
81+
82+
await fs.readFile(context, async (err, data) => {
83+
await parser.parseString(data, async (err, result) => {
84+
let dataContext = {}
85+
try {
86+
dataContext = result.Context.Resource[0].$ || {}
87+
} catch (e) {}
88+
89+
await clearConsole()
90+
injectData(dataContext, connection)
91+
92+
const server = new Server(null, targetDir, [])
93+
await server.syncModels(connection, serverConfig)
94+
})
95+
})
96+
}
97+
98+
module.exports = (...args) => {
99+
sync(...args).catch(err => {
100+
stopSpinner(false) // do not persist
101+
error(err)
102+
process.exit(1)
103+
})
104+
}

packages/@simpli/cli/lib/server/Database.js

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ module.exports = class Database {
126126
name: 'serverName',
127127
type: 'input',
128128
message: 'Enter the server name',
129-
default: capitalizeFirstLetter(camelCase(defaultName))
129+
default: defaultName ? capitalizeFirstLetter(camelCase(defaultName)) : undefined
130130
}
131131
])
132132
if (!serverName) {
@@ -238,6 +238,23 @@ module.exports = class Database {
238238
return { userTable, accountColumn, passwordColumn }
239239
}
240240

241+
static async requestSync (availableTables = [], serverSetup) {
242+
const { syncTableNames } = await inquirer.prompt([
243+
{
244+
name: 'syncTableNames',
245+
type: 'checkbox',
246+
choices: availableTables.map((table) => table.name),
247+
message: 'Which of these tables do you want to sync?'
248+
}
249+
])
250+
251+
const syncTables = serverSetup.tables
252+
.filter((table) => syncTableNames.find((name) => name === table.name))
253+
254+
serverSetup.tables = syncTables
255+
return { syncTables }
256+
}
257+
241258
static async confirm () {
242259
const { confirm } = await inquirer.prompt([
243260
{

packages/@simpli/cli/lib/server/Server.js

Lines changed: 76 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -145,16 +145,16 @@ module.exports = class Server {
145145
extractConfigFiles: preset.useConfigFiles
146146
})
147147

148+
await run(`rm -rf ./node_modules`)
149+
await run(`rm -f ./package.json`)
150+
await run(`rm -f ./package-lock.json`)
151+
148152
// commit initial state
149153
if (hasGit()) {
150154
await run('git add -A')
151155
await run(`git commit -m init`)
152156
}
153157

154-
await run(`rm -rf ./node_modules`)
155-
await run(`rm -f ./package.json`)
156-
await run(`rm -f ./package-lock.json`)
157-
158158
// log instructions
159159
stopSpinner()
160160
log()
@@ -164,12 +164,82 @@ module.exports = class Server {
164164
generator.printExitLogs()
165165
}
166166

167+
async syncModels (defaultConnection, serverConfig) {
168+
const run = (command, args) => {
169+
if (!args) { [command, ...args] = command.split(/\s+/) }
170+
return execa(command, args, { cwd: context })
171+
}
172+
173+
let config = serverConfig
174+
if (!config) {
175+
const { serverName } = await Database.requestServerName()
176+
const { moduleName, packageAddress } = await Database.requestModuleAndPackage(serverName)
177+
config = { serverName, moduleName, packageAddress }
178+
}
179+
const { availableTables } = await Database.requestConnection(this.serverSetup, defaultConnection)
180+
const { syncTables } = await Database.requestSync(availableTables, this.serverSetup)
181+
await Database.confirm()
182+
183+
this.serverSetup.serverName = config.serverName
184+
this.serverSetup.moduleName = config.moduleName
185+
this.serverSetup.packageAddress = config.packageAddress
186+
187+
const { context, createCompleteCbs } = this
188+
189+
const preset = {
190+
plugins: {
191+
'@simpli/cli-server': {
192+
serverSetup: this.serverSetup,
193+
sync: true
194+
}
195+
}
196+
}
197+
198+
// get latest CLI version
199+
const { latest } = await getVersions()
200+
// generate package.json with plugin dependencies
201+
const pkg = {
202+
name: 'sync-server',
203+
version: '0.1.0',
204+
private: true,
205+
devDependencies: {}
206+
}
207+
const deps = Object.keys(preset.plugins)
208+
deps.forEach(dep => {
209+
pkg.devDependencies[dep] = preset.plugins[dep].version ||
210+
(/^@simpli/.test(dep) ? `${latest}` : `latest`)
211+
})
212+
// write package.json
213+
await writeFileTree(context, {
214+
'package.json': JSON.stringify(pkg, null, 2)
215+
})
216+
217+
log()
218+
log(`⚙️ Synchronizing tables...`)
219+
const plugins = this.resolvePlugins(preset.plugins)
220+
const generator = new Generator(context, {
221+
pkg: { _ignore: true },
222+
plugins,
223+
completeCbs: createCompleteCbs
224+
})
225+
await generator.generate()
226+
227+
await run(`rm -rf ./node_modules`)
228+
await run(`rm -f ./package.json`)
229+
await run(`rm -f ./package-lock.json`)
230+
231+
log()
232+
log(`🎉 Successfully synchronized tables ${chalk.yellow(syncTables.map((tables) => tables.name).join(', '))}.`)
233+
log(`👉 Run ${chalk.cyan('git status')} to see which files has changed.`)
234+
log(`👉 Run ${chalk.cyan('git add . && git stash')} to revert the changes safely.\n\n`)
235+
}
236+
167237
resolvePlugins (rawPlugins) {
168238
// ensure cli-service is invoked first
169239
rawPlugins = sortObject(rawPlugins, ['@simpli/cli-server'])
170240
return Object.keys(rawPlugins).map(id => {
171-
const module = resolve.sync(`${id}/generator`, { basedir: this.context })
172-
// const module = resolve.sync('../../../cli-server/generator')
241+
// const module = resolve.sync(`${id}/generator`, { basedir: this.context })
242+
const module = resolve.sync('../../../cli-server/generator')
173243
return {
174244
id,
175245
apply: require(module),

packages/@simpli/cli/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@
5757
"semver": "^5.4.1",
5858
"slash": "^1.0.0",
5959
"uuid": "^3.2.1",
60+
"xml2js": "^0.4.19",
6061
"yaml-front-matter": "^3.4.1"
6162
},
6263
"devDependencies": {

yarn.lock

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4647,7 +4647,7 @@ sane@^2.0.0:
46474647
optionalDependencies:
46484648
fsevents "^1.1.1"
46494649

4650-
sax@^1.2.4:
4650+
sax@>=0.6.0, sax@^1.2.4:
46514651
version "1.2.4"
46524652
resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9"
46534653

@@ -5474,6 +5474,17 @@ xml-name-validator@^3.0.0:
54745474
version "3.0.0"
54755475
resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-3.0.0.tgz#6ae73e06de4d8c6e47f9fb181f78d648ad457c6a"
54765476

5477+
xml2js@^0.4.19:
5478+
version "0.4.19"
5479+
resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.4.19.tgz#686c20f213209e94abf0d1bcf1efaa291c7827a7"
5480+
dependencies:
5481+
sax ">=0.6.0"
5482+
xmlbuilder "~9.0.1"
5483+
5484+
xmlbuilder@~9.0.1:
5485+
version "9.0.7"
5486+
resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-9.0.7.tgz#132ee63d2ec5565c557e20f4c22df9aca686b10d"
5487+
54775488
xtend@^4.0.0, xtend@~4.0.1:
54785489
version "4.0.1"
54795490
resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af"

0 commit comments

Comments
 (0)