Skip to content

Commit

Permalink
Merge pull request #6 from sasjs/execute-code-button
Browse files Browse the repository at this point in the history
feat(*): add execute code button, add default targets
  • Loading branch information
krishna-acondy authored Mar 8, 2021
2 parents c115823 + 50c2c26 commit 40ea037
Show file tree
Hide file tree
Showing 9 changed files with 231 additions and 156 deletions.
6 changes: 3 additions & 3 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
"Other"
],
"activationEvents": [
"onCommand:sasjs-for-vscode.executeCode"
"*"
],
"main": "./out/extension.js",
"contributes": {
Expand Down Expand Up @@ -86,7 +86,7 @@
},
"dependencies": {
"@sasjs/adapter": "^2.1.0",
"@sasjs/utils": "^2.3.0",
"@sasjs/utils": "^2.6.3",
"valid-url": "^1.0.9"
}
}
108 changes: 108 additions & 0 deletions src/commands/execute-code/ExecuteCodeCommand.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
import SASjs from '@sasjs/adapter/node'
import * as os from 'os'
import * as path from 'path'
import {
window,
ExtensionContext,
commands,
StatusBarAlignment,
OutputChannel,
ViewColumn,
workspace,
StatusBarItem
} from 'vscode'
import { getEditorContent } from '../../utils/editor'
import { createFile } from '../../utils/file'
import { selectTarget, getAccessToken } from './internal/configuration'
import { getTimestamp } from './internal/utils'

export class ExecuteCodeCommand {
private outputChannel: OutputChannel
private runSasCodeButton: StatusBarItem

constructor(private context: ExtensionContext) {
this.outputChannel = window.createOutputChannel('SASjs')
}

initialise = () => {
const executeCodeCommand = commands.registerCommand(
'sasjs-for-vscode.executeCode',
() => this.executeCode()
)
this.context.subscriptions.push(executeCodeCommand)

this.initialiseRunSasCodeButton()
}

private initialiseRunSasCodeButton = () => {
this.runSasCodeButton = window.createStatusBarItem(
StatusBarAlignment.Right,
100
)
this.runSasCodeButton.text = '$(notebook-execute) Run SAS code'
this.runSasCodeButton.command = 'sasjs-for-vscode.executeCode'
this.runSasCodeButton.show()
this.context.subscriptions.push(this.runSasCodeButton)
}

private executeCode = async () => {
this.outputChannel.appendLine('Initialising SASjs.')
const target = await selectTarget(this.outputChannel)
if (!target) {
return
}
const accessToken = await getAccessToken(target)
const currentFileContent = getEditorContent()

const adapter = new SASjs({
serverUrl: target.serverUrl,
serverType: target.serverType,
appLoc: target.appLoc,
contextName: target.contextName,
useComputeApi: true,
debug: true
})

this.runSasCodeButton.text = '$(sync~spin) Running your SAS code'
adapter
.executeScriptSASViya(
'vscode-test-exec',
(currentFileContent || '').split('\n'),
'',
accessToken
)
.then(async (res) => {
this.runSasCodeButton.text =
'$(notebook-state-success) SAS code executed successfully!'

const timeout = setTimeout(() => {
this.runSasCodeButton.text = '$(notebook-execute) Run SAS code'
clearTimeout(timeout)
}, 3000)
const timestamp = getTimestamp()
const resultsPath = workspace.workspaceFolders?.length
? path.join(
workspace.workspaceFolders![0].uri.fsPath,
'sasjsresults',
`${timestamp}.log`
)
: path.join(os.homedir(), 'sasjsresults', `${timestamp}.log`)
await createFile(resultsPath, res.log)
const document = await workspace.openTextDocument(resultsPath)
window.showTextDocument(document, {
viewColumn: ViewColumn.Beside
})

this.outputChannel.append(JSON.stringify(res, null, 2))
})
.catch((e) => {
this.runSasCodeButton.text =
'$(notebook-state-error) SAS code execution failed'
const timeout = setTimeout(() => {
this.runSasCodeButton.text = '$(notebook-execute) Run SAS code'
clearTimeout(timeout)
}, 3000)
this.outputChannel.append(JSON.stringify(e, null, 2))
})
}
}
98 changes: 98 additions & 0 deletions src/commands/execute-code/internal/configuration.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
import { OutputChannel, env, Uri } from 'vscode'

import SASjs from '@sasjs/adapter/node'
import { Target, Configuration } from '@sasjs/utils/types'
import {
getAuthCode,
getChoiceInput,
getClientId,
getClientSecret,
getIsDefault,
getServerType,
getServerUrl,
getTargetName
} from '../../../utils/input'
import { getAuthUrl, getTokens } from '../../../utils/auth'
import {
getGlobalConfiguration,
saveGlobalRcFile,
saveToGlobalConfig
} from '../../../utils/config'

export const selectTarget = async (outputChannel: OutputChannel) => {
const config = await getGlobalConfiguration(outputChannel) as Configuration

if (config?.targets?.length) {
let targetName = config.targets.find((t) => t.name === config.defaultTarget)?.name
if (!targetName) {
const targetNames = (config?.targets || []).map((t: any) => t.name)
targetName = await getChoiceInput(targetNames, 'Please select a target')
}

if (!targetName) {
return
}

const selectedTarget = config.targets.find(
(t: any) => t.name === targetName
)
return new Target(selectedTarget)
} else {
return await createTarget(outputChannel)
}
}

export const createTarget = async (outputChannel: OutputChannel) => {
const name = await getTargetName()
const serverUrl = await getServerUrl()
const serverType = await getServerType()
const clientId = await getClientId()

const clientSecret = await getClientSecret()

env.openExternal(Uri.parse(getAuthUrl(serverUrl, clientId)))

const authCode = await getAuthCode()

const adapter = new SASjs({
serverUrl: serverUrl,
serverType: serverType,
appLoc: '/Public/app',
useComputeApi: true,
debug: true
})

const authResponse = await getTokens(
adapter,
clientId,
clientSecret,
authCode
)

const isDefault = await getIsDefault()
const target = new Target({
name,
serverUrl,
serverType,
appLoc: '/Public/app',
authConfig: authResponse,
isDefault
})

await saveToGlobalConfig(target, outputChannel)

if (isDefault) {
await setTargetAsDefault(name, outputChannel)
}
return target
}

export const getAccessToken = async (target: Target) => {
return target.authConfig?.access_token
}

const setTargetAsDefault = async (targetName: string, outputChannel: OutputChannel) => {
const globalConfig = await getGlobalConfiguration(outputChannel)
globalConfig.defaultTarget = targetName
await saveGlobalRcFile(JSON.stringify(globalConfig, null, 2))
}
7 changes: 7 additions & 0 deletions src/commands/execute-code/internal/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { timestampToYYYYMMDDHHMMSS } from '@sasjs/utils/time'

export const getTimestamp = () =>
timestampToYYYYMMDDHHMMSS()
.replace(/ /g, '')
.replace(/\//g, '')
.replace(/:/g, '')
138 changes: 0 additions & 138 deletions src/executeCode.ts

This file was deleted.

Loading

0 comments on commit 40ea037

Please sign in to comment.