Skip to content

Commit

Permalink
feat: ink ui template with commands (#74)
Browse files Browse the repository at this point in the history
  • Loading branch information
kidneyweakx authored Jul 20, 2023
1 parent 36940f2 commit 6b62a88
Show file tree
Hide file tree
Showing 13 changed files with 3,970 additions and 1,980 deletions.
14 changes: 14 additions & 0 deletions .eslintrc
Original file line number Diff line number Diff line change
@@ -1,8 +1,22 @@
{
"extends": [
"plugin:react/recommended",
"./node_modules/ericlint"
],
"rules": {
"react/jsx-uses-react": "error",
"react/jsx-uses-vars": "error",
"react/react-in-jsx-scope": "error"
},
"parserOptions": {
"project": "tsconfig.eslint.json"
},
"plugins": [
"react"
],
"settings": {
"react": {
"version": "detect"
}
}
}
5,706 changes: 3,739 additions & 1,967 deletions package-lock.json

Large diffs are not rendered by default.

27 changes: 17 additions & 10 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,12 @@
"check:node_version": "node check_node_version.js",
"preversion": "npm run eslint && npm run build-ts",
"build-ts": "rm -rf dist && tsc",
"eslint": "eslint -c .eslintrc \"./src/**/*.ts\" \"./test/**/*.ts\"",
"eslint:fix": "tsc --noEmit && node_modules/.bin/eslint -c .eslintrc ./src/**/*.ts ./test/**/*.ts --quiet --fix",
"eslint": "eslint -c .eslintrc \"./src/**/*.*(ts|tsx)\" \"./test/**/*.ts\"",
"eslint:fix": "tsc --noEmit && node_modules/.bin/eslint -c .eslintrc ./src/**/*.*(ts|tsx) ./test/**/*.ts --quiet --fix",
"init:autocomplete": "bdk fabric completion > $HOME/.bash_bdk",
"build:console": "ts-node src/console.ts",
"start:dev": "NODE_ENV=development nodemon --watch 'src/**/*.ts' --exec 'ts-node' src/console.ts",
"start:dev": "NODE_ENV=development nodemon --watch 'src/**/*' -e ts,tsx --exec 'ts-node' src/console.ts",
"start:ui": "NODE_ENV=ui nodemon --watch 'src/**/*' -e ts,tsx --exec 'ts-node' src/console.ts",
"test": "NODE_ENV=testing BDK_PATH=$(pwd)/test/bdk BDK_DOCKER_HOST_PATH=$(pwd)/test/bdk mocha --reporter spec --require ts-node/register ./test/**/*.test.ts --exit",
"test:dev": "nodemon --watch 'test/**/*.test.ts' -e ts,tsx --exec npm run test",
"test:nyan": "NODE_ENV=testing mocha --reporter nyan --require ts-node/register ./test/**/*.test.ts --exit",
Expand All @@ -47,13 +48,17 @@
"dependencies": {
"deep-object-diff": "^1.1.0",
"dockerode": "^3.3.1",
"dotenv": "^8.2.0",
"envfile": "^6.14.0",
"dotenv": "^16.3.1",
"envfile": "^6.18.0",
"ethers": "^5.6.5",
"fs-extra": "^9.1.0",
"ink": "^3.2.0",
"ink-gradient": "^2.0.0",
"ink-select-input": "^4.2.2",
"js-yaml": "^4.1.0",
"ora": "^5.4.1",
"prompts": "^2.4.0",
"react": "^17.0.2",
"rlp": "^3.0.0",
"string-format": "^2.0.0",
"tar": "^6.1.12",
Expand All @@ -62,20 +67,22 @@
},
"devDependencies": {
"@istanbuljs/nyc-config-typescript": "^1.0.1",
"@types/axios": "^0.14.0",
"@types/dockerode": "^3.2.1",
"@types/fs-extra": "^9.0.9",
"@types/ink-gradient": "^2.0.1",
"@types/js-yaml": "^4.0.5",
"@types/mocha": "^8.0.3",
"@types/node": "^14.6.4",
"@types/prompts": "^2.0.9",
"@types/react": "^18.2.14",
"@types/sinon": "^9.0.8",
"@types/source-map-support": "^0.5.3",
"@types/string-format": "^2.0.0",
"@types/tar": "^6.1.3",
"@types/triple-beam": "^1.3.2",
"@types/yargs": "^15.0.5",
"ericlint": "^1.1.3",
"eslint-plugin-react": "^7.32.2",
"git-cliff": "^1.2.0",
"mocha": "^9.1.3",
"mocha-sonarqube-reporter": "^1.0.2",
Expand All @@ -84,12 +91,12 @@
"semver": "^7.3.5",
"sinon": "^9.2.0",
"source-map-support": "^0.5.19",
"ts-node": "^10.4.0",
"typedoc": "^0.21.2",
"typescript": "^4.5.4"
"ts-node": "^10.9.1",
"typedoc": "^0.24.8",
"typescript": "^4.9.5"
},
"engines": {
"node": ">=12.0.0"
"node": ">=16.0.0"
},
"publishConfig": {
"@cathayddt:registry": "https://npm.pkg.github.com"
Expand Down
1 change: 1 addition & 0 deletions src/bdk.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ const argv = yargs
.commandDir('fabric')
.commandDir('quorum')
.commandDir('hello')
.commandDir('ui')
.strict()
.demandCommand()
.completion()
Expand Down
12 changes: 12 additions & 0 deletions src/ui/components/table.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import React from 'react'
import { Box } from 'ink'

export default function Table () {
return (
<Box flexDirection='column'>
<Box>
<Box width='25%'>props</Box>
</Box>
</Box>
)
}
41 changes: 41 additions & 0 deletions src/ui/services/commandContext.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { execSync } from 'child_process'

export default class commandContext {
public getCommandContext (command: string): (string|undefined)[] {
const text = execSync(`${command} --help`).toString()

const regex = /(?::|:|คอมมาน)\n((?:\s+.*\n)+)/
const match = regex.exec(text)

const commandsRegex = this.makeRegex(command)
if (match) {
const commandsText = match[1]
const commands = commandsText.match(commandsRegex)
?.map((match) => `${command} ${match.trim().split(/\s+/).pop()}`) ?? []
console.log(commands)
return commands
}
return []
}

public getCommandOutput (command: string): string {
let output
if (this.checkInteractive(command)) {
output = execSync(`${command} --interactive`).toString()
}
output = execSync(command).toString()
return output
}

private checkInteractive (command: string): boolean {
const text = execSync(`${command} --help`).toString()
const regex = /interactive/
const match = regex.exec(text)
if (match) return true
return false
}

private makeRegex (command: string): RegExp {
return new RegExp(`\\s+${command}\\s+([A-Za-z0-9]+)`, 'g')
}
}
15 changes: 15 additions & 0 deletions src/ui/ui.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import React from 'react'
import { Argv } from 'yargs'
import { render } from 'ink'
import App from './views/app.js'

export const command = 'ui'

export const desc = '使用 ui 模式'
export const builder = (yargs: Argv<any>) => {
return yargs
}

export const handler = () => {
render(<App />)
}
44 changes: 44 additions & 0 deletions src/ui/views/app.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import React from 'react'
import { Box, Text, useApp, useInput } from 'ink'
import Logo from './logo'
import Command from './command'
import DockerLogs from './dockerLogs'
import Terminal from './terminal'
import SelectInput from 'ink-select-input'

export default function App () {
const { exit } = useApp()
useInput((input, key) => {
if (input === 'q' || (key.ctrl && input === 'c') || key.escape) {
exit()
}
})
const items = [
{
label: 'Fabric',
value: 'bdk fabric',
},
{
label: 'Quorum',
value: 'bdk quorum',
},
]
return (
<Box borderStyle='single' flexDirection='column' height={50}>
<Box flexDirection='row' height={90}>
<Box flexDirection='column' flexGrow={1}>
<Logo />
<Command />
<SelectInput items={items} isFocused={false} />
<DockerLogs />
</Box>
<Box flexGrow={1}>
<Terminal />
</Box>
</Box>
<Box flexDirection='column'>
</Box>
<Text bold={true} color='yellow'>-- Press q to exit --</Text>
</Box>
)
}
21 changes: 21 additions & 0 deletions src/ui/views/command.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import React from 'react'
import { Text, Box, Newline } from 'ink'
import QuorumCommands from '../services/commandContext'

export default function Command () {
const quorum = new QuorumCommands()
const [output, setOutput] = React.useState('')
React.useEffect(() => {
setOutput(quorum.getCommandContext('bdk quorum').toString())
}, [setOutput])

return (
<Box>
<Text>Choose a command:</Text>
<Newline />
<Box flexDirection="column">
<Text> Quorum: {output}</Text>
</Box>
</Box>
)
}
27 changes: 27 additions & 0 deletions src/ui/views/dockerLogs.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import React from 'react'
import { Text, Box } from 'ink'

const items = [
{
label: 'Fabric',
value: 'bdk fabric',
},
{
label: 'Quorum',
value: 'bdk quorum',
},
]
export default function DockerLogs () {
return (
<Box borderStyle='single' flexDirection='column'>
<Text>Blockchain Platform:</Text>
<Box flexDirection='column'>
{items.map((item) => (
<Box key={item.value}>
<Text>{item.label}</Text>
</Box>
))}
</Box>
</Box>
)
}
17 changes: 17 additions & 0 deletions src/ui/views/logo.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import React from 'react'
import { Text, Box } from 'ink'
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
import Gradient from 'ink-gradient'

export default function Logo () {
return (
<Box borderStyle='single' flexDirection='column'>
<Gradient name="rainbow">
<Text>
Blockchain Deploy Kit
</Text>
</Gradient>
</Box>
)
}
19 changes: 19 additions & 0 deletions src/ui/views/terminal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import React from 'react'
import { Text, Box } from 'ink'
import { execSync } from 'child_process'

export default function Terminal () {
const [output, setOutput] = React.useState('')
React.useEffect(() => {
setOutput(execSync('bdk fabric --help').toString())
}, [setOutput])

return (
<Box borderStyle="single" flexDirection="column" flexGrow={1}>
<Text>Command output:</Text>
<Box marginTop={1}>
<Text>{output}</Text>
</Box>
</Box>
)
}
6 changes: 3 additions & 3 deletions tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"lib": ["es2019"], /* Specify library files to be included in the compilation. */
// "allowJs": true, /* Allow javascript files to be compiled. */
// "checkJs": true, /* Report errors in .js files. */
// "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */
"jsx": "react-jsx", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */
"declaration": true, /* Generates corresponding '.d.ts' file. */
"declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */
"sourceMap": true, /* Generates corresponding '.map' file. */
Expand Down Expand Up @@ -40,12 +40,12 @@

/* Module Resolution Options */
"moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */
"baseUrl": ".src/", /* Base directory to resolve non-absolute module names. */
"baseUrl": ".src/", /* Base directory to resolve non-absolute module names. */
"paths": {
"*": [
"node_modules/*"
]
}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */
}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */
// "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */
// "typeRoots": [], /* List of folders to include type definitions from. */
// "types": [], /* Type declaration files to be included in compilation. */
Expand Down

0 comments on commit 6b62a88

Please sign in to comment.