mirror of
https://github.com/sasjs/adapter.git
synced 2026-01-05 03:30:05 +00:00
Compare commits
10 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
40de5f2e11 | ||
|
|
6056424d26 | ||
|
|
ae5110974f | ||
|
|
b2f6d4e6d1 | ||
|
|
f69a635e1d | ||
|
|
c8bc6936e8 | ||
|
|
9a24a8b962 | ||
|
|
c43c9ec211 | ||
|
|
9b0e02f5b7 | ||
|
|
0f9eca7482 |
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
224
docs/classes/reflection-706.reflection-178.fileuploader.html
Normal file
224
docs/classes/reflection-706.reflection-178.fileuploader.html
Normal file
File diff suppressed because one or more lines are too long
297
docs/classes/reflection-706.reflection-178.sas9apiclient.html
Normal file
297
docs/classes/reflection-706.reflection-178.sas9apiclient.html
Normal file
File diff suppressed because one or more lines are too long
1218
docs/classes/reflection-706.reflection-178.sasjs.html
Normal file
1218
docs/classes/reflection-706.reflection-178.sasjs.html
Normal file
File diff suppressed because one or more lines are too long
1163
docs/classes/reflection-706.reflection-178.sasviyaapiclient.html
Normal file
1163
docs/classes/reflection-706.reflection-178.sasviyaapiclient.html
Normal file
File diff suppressed because one or more lines are too long
260
docs/classes/reflection-706.reflection-178.sessionmanager.html
Normal file
260
docs/classes/reflection-706.reflection-178.sessionmanager.html
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
252
docs/interfaces/types.editcontextinput.html
Normal file
252
docs/interfaces/types.editcontextinput.html
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
107
docs/modules/reflection-706.html
Normal file
107
docs/modules/reflection-706.html
Normal file
File diff suppressed because one or more lines are too long
129
docs/modules/reflection-706.reflection-178.html
Normal file
129
docs/modules/reflection-706.reflection-178.html
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -8,7 +8,14 @@ import {
|
|||||||
} from './utils'
|
} from './utils'
|
||||||
import * as NodeFormData from 'form-data'
|
import * as NodeFormData from 'form-data'
|
||||||
import * as path from 'path'
|
import * as path from 'path'
|
||||||
import { Job, Session, Context, Folder, CsrfToken } from './types'
|
import {
|
||||||
|
Job,
|
||||||
|
Session,
|
||||||
|
Context,
|
||||||
|
Folder,
|
||||||
|
CsrfToken,
|
||||||
|
EditContextInput
|
||||||
|
} from './types'
|
||||||
import { JobDefinition } from './types/JobDefinition'
|
import { JobDefinition } from './types/JobDefinition'
|
||||||
import { formatDataForRequest } from './utils/formatDataForRequest'
|
import { formatDataForRequest } from './utils/formatDataForRequest'
|
||||||
import { SessionManager } from './SessionManager'
|
import { SessionManager } from './SessionManager'
|
||||||
@@ -267,6 +274,68 @@ export class SASViyaApiClient {
|
|||||||
return context
|
return context
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates a compute context on the given server.
|
||||||
|
* @param contextId - the ID of the context to be deleted.
|
||||||
|
* @param editedContext - an object with the properties to be updated.
|
||||||
|
* @param accessToken - an access token for an authorized user.
|
||||||
|
*/
|
||||||
|
public async editContext(
|
||||||
|
contextId: string,
|
||||||
|
updatedContext: EditContextInput,
|
||||||
|
accessToken?: string
|
||||||
|
) {
|
||||||
|
if (!contextId) {
|
||||||
|
throw new Error('Invalid context ID.')
|
||||||
|
}
|
||||||
|
|
||||||
|
const headers: any = {
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
}
|
||||||
|
|
||||||
|
if (accessToken) {
|
||||||
|
headers.Authorization = `Bearer ${accessToken}`
|
||||||
|
}
|
||||||
|
|
||||||
|
const { result: context, etag } = await this.request<Context>(
|
||||||
|
`${this.serverUrl}/compute/contexts/${contextId}`,
|
||||||
|
{
|
||||||
|
headers
|
||||||
|
}
|
||||||
|
).catch((e) => {
|
||||||
|
console.error(e)
|
||||||
|
|
||||||
|
if (e && e.status === 404) {
|
||||||
|
throw new Error(
|
||||||
|
`The context with ID ${contextId} was not found on this server.`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
throw new Error(
|
||||||
|
`An error occurred when fetching the context with ID ${contextId}`
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
// An If-Match header with the value of the last ETag for the context
|
||||||
|
// is required to be able to update it
|
||||||
|
// https://developer.sas.com/apis/rest/Compute/#update-a-context-definition
|
||||||
|
headers['If-Match'] = etag
|
||||||
|
|
||||||
|
const updateContextRequest: RequestInit = {
|
||||||
|
method: 'PUT',
|
||||||
|
headers,
|
||||||
|
body: JSON.stringify({
|
||||||
|
...context,
|
||||||
|
...updatedContext,
|
||||||
|
attributes: { ...context.attributes, ...updatedContext.attributes }
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return await this.request<Context>(
|
||||||
|
`${this.serverUrl}/compute/contexts/${contextId}`,
|
||||||
|
updateContextRequest
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Deletes a compute context on the given server.
|
* Deletes a compute context on the given server.
|
||||||
* @param contextId - the ID of the context to be deleted.
|
* @param contextId - the ID of the context to be deleted.
|
||||||
|
|||||||
24
src/SASjs.ts
24
src/SASjs.ts
@@ -29,7 +29,8 @@ import {
|
|||||||
SASjsWaitingRequest,
|
SASjsWaitingRequest,
|
||||||
ServerType,
|
ServerType,
|
||||||
CsrfToken,
|
CsrfToken,
|
||||||
UploadFile
|
UploadFile,
|
||||||
|
EditContextInput
|
||||||
} from './types'
|
} from './types'
|
||||||
import { SASViyaApiClient } from './SASViyaApiClient'
|
import { SASViyaApiClient } from './SASViyaApiClient'
|
||||||
import { SAS9ApiClient } from './SAS9ApiClient'
|
import { SAS9ApiClient } from './SAS9ApiClient'
|
||||||
@@ -137,6 +138,27 @@ export default class SASjs {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates a compute context on the given server.
|
||||||
|
* @param contextId - the ID of the context to be deleted.
|
||||||
|
* @param editedContext - an object with the properties to be updated.
|
||||||
|
* @param accessToken - an access token for an authorized user.
|
||||||
|
*/
|
||||||
|
public async editContext(
|
||||||
|
contextId: string,
|
||||||
|
editedContext: EditContextInput,
|
||||||
|
accessToken?: string
|
||||||
|
) {
|
||||||
|
if (this.sasjsConfig.serverType !== ServerType.SASViya) {
|
||||||
|
throw new Error('This operation is only supported on SAS Viya servers.')
|
||||||
|
}
|
||||||
|
return await this.sasViyaApiClient!.editContext(
|
||||||
|
contextId,
|
||||||
|
editedContext,
|
||||||
|
accessToken
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Deletes a compute context on the given server.
|
* Deletes a compute context on the given server.
|
||||||
* @param contextId - the ID of the context to be deleted.
|
* @param contextId - the ID of the context to be deleted.
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ export class SessionManager {
|
|||||||
(new Date().getTime() - new Date(session!.creationTimeStamp).getTime()) /
|
(new Date().getTime() - new Date(session!.creationTimeStamp).getTime()) /
|
||||||
1000
|
1000
|
||||||
if (
|
if (
|
||||||
|
!session!.attributes ||
|
||||||
secondsSinceSessionCreation >= session!.attributes.sessionInactiveTimeout
|
secondsSinceSessionCreation >= session!.attributes.sessionInactiveTimeout
|
||||||
) {
|
) {
|
||||||
await this.createSessions(accessToken)
|
await this.createSessions(accessToken)
|
||||||
|
|||||||
@@ -3,4 +3,15 @@ export interface Context {
|
|||||||
id: string
|
id: string
|
||||||
createdBy: string
|
createdBy: string
|
||||||
version: number
|
version: number
|
||||||
|
attributes?: any
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface EditContextInput {
|
||||||
|
name?: string
|
||||||
|
description?: string
|
||||||
|
launchContext?: { name: string }
|
||||||
|
environment?: { options?: string[]; autoExecLines?: string[] }
|
||||||
|
attributes?: any
|
||||||
|
authorizedUsers?: string[]
|
||||||
|
authorizeAllAuthenticatedUsers?: boolean
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,34 +1,21 @@
|
|||||||
import SASjs from './index'
|
import { parseGeneratedCode } from './index'
|
||||||
|
|
||||||
const adapter = new SASjs()
|
|
||||||
|
|
||||||
it('should parse SAS9 source code', async (done) => {
|
|
||||||
expect(sampleResponse).toBeTruthy()
|
|
||||||
const parsedSourceCode = (adapter as any).parseSAS9SourceCode(sampleResponse)
|
|
||||||
expect(parsedSourceCode).toBeTruthy()
|
|
||||||
const sourceCodeLines = parsedSourceCode.split('\r\n')
|
|
||||||
expect(sourceCodeLines.length).toEqual(5)
|
|
||||||
expect(sourceCodeLines[0].startsWith('6')).toBeTruthy()
|
|
||||||
expect(sourceCodeLines[1].startsWith('7')).toBeTruthy()
|
|
||||||
expect(sourceCodeLines[2].startsWith('8')).toBeTruthy()
|
|
||||||
expect(sourceCodeLines[3].startsWith('9')).toBeTruthy()
|
|
||||||
expect(sourceCodeLines[4].startsWith('10')).toBeTruthy()
|
|
||||||
done()
|
|
||||||
})
|
|
||||||
|
|
||||||
it('should parse generated code', async (done) => {
|
it('should parse generated code', async (done) => {
|
||||||
expect(sampleResponse).toBeTruthy()
|
expect(sampleResponse).toBeTruthy()
|
||||||
const parsedGeneratedCode = (adapter as any).parseGeneratedCode(
|
|
||||||
sampleResponse
|
const parsedGeneratedCode = parseGeneratedCode(sampleResponse)
|
||||||
)
|
|
||||||
expect(parsedGeneratedCode).toBeTruthy()
|
expect(parsedGeneratedCode).toBeTruthy()
|
||||||
|
|
||||||
const generatedCodeLines = parsedGeneratedCode.split('\r\n')
|
const generatedCodeLines = parsedGeneratedCode.split('\r\n')
|
||||||
|
|
||||||
expect(generatedCodeLines.length).toEqual(5)
|
expect(generatedCodeLines.length).toEqual(5)
|
||||||
expect(generatedCodeLines[0].startsWith('MPRINT(MM_WEBIN)')).toBeTruthy()
|
expect(generatedCodeLines[0].startsWith('MPRINT(MM_WEBIN)')).toBeTruthy()
|
||||||
expect(generatedCodeLines[1].startsWith('MPRINT(MM_WEBLEFT)')).toBeTruthy()
|
expect(generatedCodeLines[1].startsWith('MPRINT(MM_WEBLEFT)')).toBeTruthy()
|
||||||
expect(generatedCodeLines[2].startsWith('MPRINT(MM_WEBOUT)')).toBeTruthy()
|
expect(generatedCodeLines[2].startsWith('MPRINT(MM_WEBOUT)')).toBeTruthy()
|
||||||
expect(generatedCodeLines[3].startsWith('MPRINT(MM_WEBRIGHT)')).toBeTruthy()
|
expect(generatedCodeLines[3].startsWith('MPRINT(MM_WEBRIGHT)')).toBeTruthy()
|
||||||
expect(generatedCodeLines[4].startsWith('MPRINT(MM_WEBOUT)')).toBeTruthy()
|
expect(generatedCodeLines[4].startsWith('MPRINT(MM_WEBOUT)')).toBeTruthy()
|
||||||
|
|
||||||
done()
|
done()
|
||||||
})
|
})
|
||||||
|
|
||||||
35
src/utils/parseSourceCode.spec.ts
Normal file
35
src/utils/parseSourceCode.spec.ts
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
import { parseSourceCode } from './index'
|
||||||
|
|
||||||
|
it('should parse SAS9 source code', async (done) => {
|
||||||
|
expect(sampleResponse).toBeTruthy()
|
||||||
|
|
||||||
|
const parsedSourceCode = parseSourceCode(sampleResponse)
|
||||||
|
|
||||||
|
expect(parsedSourceCode).toBeTruthy()
|
||||||
|
|
||||||
|
const sourceCodeLines = parsedSourceCode.split('\r\n')
|
||||||
|
|
||||||
|
expect(sourceCodeLines.length).toEqual(5)
|
||||||
|
expect(sourceCodeLines[0].startsWith('6')).toBeTruthy()
|
||||||
|
expect(sourceCodeLines[1].startsWith('7')).toBeTruthy()
|
||||||
|
expect(sourceCodeLines[2].startsWith('8')).toBeTruthy()
|
||||||
|
expect(sourceCodeLines[3].startsWith('9')).toBeTruthy()
|
||||||
|
expect(sourceCodeLines[4].startsWith('10')).toBeTruthy()
|
||||||
|
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
|
||||||
|
/* tslint:disable */
|
||||||
|
const sampleResponse = `<meta http-equiv="Content-Type" content="text/html; charset=windows-1252"/>
|
||||||
|
6 @file mm_webout.sas
|
||||||
|
7 @brief Send data to/from SAS Stored Processes
|
||||||
|
8 @details This macro should be added to the start of each Stored Process,
|
||||||
|
9 **immediately** followed by a call to:
|
||||||
|
10 %webout(OPEN)
|
||||||
|
MPRINT(MM_WEBIN): ;
|
||||||
|
MPRINT(MM_WEBLEFT): filename _temp temp lrecl=999999;
|
||||||
|
MPRINT(MM_WEBOUT): data _null_;
|
||||||
|
MPRINT(MM_WEBRIGHT): file _temp;
|
||||||
|
MPRINT(MM_WEBOUT): if upcase(symget('_debug'))='LOG' then put '>>weboutBEGIN<<';
|
||||||
|
`
|
||||||
|
/* tslint:enable */
|
||||||
Reference in New Issue
Block a user