forked from kuzzleio/kourou
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathexecute.ts
145 lines (116 loc) · 3.71 KB
/
execute.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
import { flags } from '@oclif/command'
import { isEmpty } from 'lodash'
import { Editor } from '../../support/editor'
import { Kommand } from '../../common'
import { kuzzleFlags } from '../../support/kuzzle'
class SdkExecute extends Kommand {
public static description = `
Executes arbitrary code.
Code Execution
Provided code will be executed in an async method.
You can access a connected and authenticated SDK with the "sdk" variable.
Templated variable passed as the command arguments are also accessible within the same name.
Returned value will be printed on the standard output (e.g. 'return await sdk.server.now();').
Errors will be caught and printed on the error output (e.g. 'throw new Error("failure");').
Provide code
code can be passed as an argument
code will be read from STDIN if available
Examples:
- kourou sdk:execute 'return await sdk.server.now()'
- kourou sdk:execute 'return await sdk.index.exists(index)' --var 'index="iot-data"'
- kourou sdk:execute < snippet.js
- echo 'return await sdk.server.now()' | kourou sdk:execute
Other
use the --editor flag to modify the code before executing it
Examples:
- kourou sdk:execute 'return await sdk.server.now()' --editor
`;
public static flags = {
help: flags.help(),
var: flags.string({
char: 'v',
description: 'Additional arguments injected into the code. (eg: --var \'index="iot-data"\'',
multiple: true
}),
editor: flags.boolean({
description: 'Open an editor (EDITOR env variable) to edit the code before executing it.'
}),
'keep-alive': flags.boolean({
description: 'Keep the connection running (websocket only)'
}),
'print-raw': flags.boolean({
description: 'Print only the script result to stdout'
}),
...kuzzleFlags,
};
public static args = [
{ name: 'code', description: 'Code to execute. Will be read from STDIN if available.', required: false },
]
private code = ''
static readStdin = true
async beforeConnect() {
this.code = this.stdin || this.args.code || '// paste your code here'
if (this.haveSubscription) {
this.sdkOptions.protocol = 'ws'
}
}
async runSafe() {
if (isEmpty(this.code)) {
throw new Error('No code provided.')
}
let userError: Error | null = null
const variables = (this.flags.var || [])
.map((nameValue: string) => {
const [name, value] = nameValue.split('=')
return ` let ${name} = ${value};`
})
.join('\n')
this.code = `
(async () => {
try {
${variables}
${this.code}
}
catch (error) {
userError = error
}
})();
`
// content from user editor
if (this.flags.editor) {
const editor = new Editor(this.code)
editor.run()
this.code = editor.content
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const sdk: any = this.sdk.sdk
let result
try {
// eslint-disable-next-line no-eval
result = await eval(this.code)
}
catch (error) {
userError = error
}
if (userError) {
this.logKo(`Error when executing SDK code: ${userError}`)
this.log(this.code)
}
else {
this.logOk('Successfully executed SDK code')
if (result !== undefined) {
// eslint-disable-next-line no-console
console.log(JSON.stringify(result, null, 2))
}
}
if (!userError && (this.haveSubscription || this.flags['keep-alive'])) {
this.logInfo('Keep alive for realtime notifications ...')
// eslint-disable-next-line @typescript-eslint/no-empty-function
await new Promise(() => { })
}
}
get haveSubscription() {
return this.code.includes('sdk.realtime.subscribe')
}
}
export default SdkExecute