fm-data-api
Version:
FileMaker Data Api wrapper for Vue.js
1,152 lines (977 loc) • 27.8 kB
JavaScript
import axios from 'axios'
class Exception {
/**
* Exception constructor
*
* @param message
* @param code
*/
constructor (message, code) {
if (code !== '') {
return '[ ' + code + ', ' + message + ' ]'
}
return '[ ' + message + ' ]'
}
}
export class Response {
/**
* Response constructor
*
* @param headers
* @param body
*/
constructor (headers, body) {
this.setHeaders(headers)
this.body = body
this.RESPONSE_TYPE_JSON = 'json'
this.RESPONSE_TYPE_TEXT = 'text'
if (Array.isArray(body)) {
this.responseType = this.RESPONSE_TYPE_JSON
} else {
this.responseType = this.RESPONSE_TYPE_TEXT
}
}
static get RESPONSE_TYPE_JSON () {
return this.RESPONSE_TYPE_JSON
}
static get RESPONSE_TYPE_TEXT () {
return this.RESPONSE_TYPE_TEXT
}
setHeaders (headers) {
if (Array.isArray(headers)) {
this.headers = headers
return this
}
throw new Exception('Bad headers', '')
}
/**
* @param header
* @returns {*}
* @throws Exception
*/
getHeader (header) {
if (({}.propertyIsEnumerable.call(this.headers, header)) && this.headers[header].length > 0) {
return this.headers[header]
}
throw new Exception('Header not found', '')
}
/**
* @param hearders
* @param body
* @returns {Response}
* @throws Exception
*/
static parse (hearders, body) {
return new Response(Response.parseHeaders(hearders), Response.parseBody(body))
}
/**
* @returns {number}
* @throws Exception
*/
getHttpCode () {
let httpHeader = this.getHeader('Status')
httpHeader = httpHeader.split(' ')
return parseInt(httpHeader[1], 10)
}
/**
* @param headers
* @returns {Array}
*/
static parseHeaders (headers) {
// We convert the raw header string into an array
headers = headers.split('\n')
headers = headers.map(function (header) {
const exploded = header.split(':')
return exploded.map(function (value) {
return value.trim().replace('"', '')
})
})
// We remove empty lines in array
headers = headers.filter(function (value) {
return (Array.isArray(value) ? value[0] : value) !== ''
})
// Lastly, we clean the array format to be a key => value array
// The response code is special as there is no key. We handle it differently
const statusHeader = []
let index
for (index = 0; index < headers.length; ++index) {
const header = ({}.propertyIsEnumerable.call(headers, index) ? headers[index] : [])
if (!{}.propertyIsEnumerable.call(header, 1) || header[1].length > 0) {
break
}
if ({}.propertyIsEnumerable.call(header, 0) && header[0].length > 0) {
statusHeader.push({
Status: header[0]
})
headers.splice(index, 1)
}
}
const processedHeaders = statusHeader
for (index = 0; index < headers.length; ++index) {
const header = ({}.propertyIsEnumerable.call(headers, index) ? headers[index] : [])
if (!{}.propertyIsEnumerable.call(header, 1) || header[1].length <= 0) {
continue
}
processedHeaders[header[0]] = header[1]
}
return processedHeaders
}
/**
* @param body
* @returns {*}
*/
static parseBody (body) {
if (Response.isJson(body)) {
return JSON.parse(body)
}
return body
}
/**
* @param string
* @returns {boolean}
*/
static isJson (string) {
try {
JSON.parse(string)
} catch (e) {
return false
}
return true
}
}
export class AxiosClient {
/**
* AxiosClient constructor
*
* @param apiUrl
*/
constructor (apiUrl) {
this.baseUrl = apiUrl
}
/**
* Execute an axios request
*
* @param method
* @param url
* @param options
* @param dataInfo
* @throws Exception
*/
request (method, url, options, dataInfo = false) {
let completeUrl = encodeURI(this.baseUrl + url)
let body = ''
var requestOptions = {
method: method,
responseType: 'json'
}
const axiosFM = axios.create()
options.headers['Content-Type'] = (options.headers['Content-Type'] === undefined) ? 'application/json' : options.headers['Content-Type']
options.headers.crossDomain = true
// -- Set url
if ({}.propertyIsEnumerable.call(options, 'queryParams')) {
const queryParams = this.httpBuildQuery(options.queryParams)
completeUrl += (queryParams.length > 0 ? '?' + queryParams : '')
}
requestOptions.url = completeUrl
// --
// -- Set body
if ({}.propertyIsEnumerable.call(options, 'json') && method !== 'GET') {
body = '{'
for (const jsonOptionKey in options.json) {
// check if the property/key is defined in the object itself, not in parent
if ({}.propertyIsEnumerable.call(options.json, jsonOptionKey)) {
const jsonOptionData = options.json[jsonOptionKey]
body += '"' + jsonOptionKey + '":' + (Response.isJson(jsonOptionData) ? jsonOptionData : JSON.stringify(jsonOptionData)) + ','
}
}
body = (body.length > 1 ? body.substring(0, (body.length - 1)) : body)
body += '}'
body = JSON.parse(body)
if (body === false) {
throw new Exception('Failed to json encode parameters', '')
}
}
// --
// -- Set headers
if (!{}.propertyIsEnumerable.call(options, 'headers')) {
options.headers = []
}
const myHeaders = {}
for (const headerKey in options.headers) {
// check if the property/key is defined in the object itself, not in parent
if ({}.propertyIsEnumerable.call(options.headers, headerKey)) {
const headerValue = options.headers[headerKey]
const key = headerKey.replace('"', '').trim()
myHeaders[key] = headerValue
}
}
requestOptions.headers = myHeaders
// --
// Send
if ({}.propertyIsEnumerable.call(options, 'fileObject') && method === 'POST') {
var formdata = new FormData()
formdata.append('upload', options.fileObject, options.fileObject.name)
requestOptions.data = formdata
} else if (typeof body !== 'undefined' && method !== 'GET') {
requestOptions.data = JSON.stringify(body)
}
// Return the rights datas for each type of request
axiosFM.interceptors.response.use(function (res) {
// Filtering function for successfull request
if (dataInfo) {
return res.data.response
}
if (res.data.response.data !== undefined) {
return res.data.response.data
}
if (res.data.response.recordId !== undefined) {
return res.data.response.recordId
}
if (res.data.response.modId !== undefined) {
return res.data.response.modId
}
if (res.data.response !== undefined) {
if (res.data.response.length === 0) {
if (res.data.messages[0].code === '0') {
return true
}
if (res.data.messages[0].code === '10') {
return false
}
}
return res.data.response
}
}, function (error) {
// Filtering function for failed request or empty data
// Return empty object for data and 0 for the count of found datas
if ((error.config.url.includes('_find')) && (error.response.data.messages[0].code === '401')) {
return { data: {}, dataInfo: { foundCount: 0 } }
}
throw new Exception(error.response.data.messages[0].message, error.response.data.messages[0].code)
})
return axiosFM(requestOptions)
}
httpBuildQuery (paramsData) {
const searchParameters = new URLSearchParams()
Object.keys(paramsData).forEach(function (parameterName) {
searchParameters.append(parameterName, paramsData[parameterName])
})
return searchParameters.toString()
}
}
export default class DataApi {
/**
* DataApi constructor
*
* @param options
*/
constructor (options = {}, logNow = true) {
this.SCRIPT_PREREQUEST = 'prerequest'
this.SCRIPT_PRESORT = 'presort'
this.SCRIPT_POSTREQUEST = 'postrequest'
this.LASTVERSION = 'v1'
// Init properties
this.initProperties()
// Set properties if in options variable
if ({}.propertyIsEnumerable.call(options, 'login')) {
this.apiUsername = options.login
}
if ({}.propertyIsEnumerable.call(options, 'version')) {
this.version = options.version
}
if ({}.propertyIsEnumerable.call(options, 'password')) {
this.apiPassword = options.password
}
if ({}.propertyIsEnumerable.call(options, 'oAuthRequestId')) {
this.oAuthRequestId = options.oAuthRequestId
}
if ({}.propertyIsEnumerable.call(options, 'oAuthIdentifier')) {
this.oAuthIdentifier = options.oAuthIdentifier
}
if ({}.propertyIsEnumerable.call(options, 'token')) {
this.apiToken = options.token
}
if ({}.propertyIsEnumerable.call(options, 'databaseName')) {
this.apiDatabase = options.databaseName
}
if ({}.propertyIsEnumerable.call(options, 'apiUrl')) {
this.ClientRequest = new AxiosClient(options.apiUrl)
}
// Constructor problem
if (!this.thereIsCredentials() || this.apiToken.length === 0) {
new Exception('Data Api needs valid credentials [username;password] or [authRequestId;authIdentifier] or [token]', '') // eslint-disable-line no-new
}
if (logNow) {
// Basic default Authentication
this.login()
}
}
// -- Start auth Part --
/**
* Login to FileMaker API
*
* @returns {DataApi}
* @throws Exception
*/
async login () {
// Available only if there is credentials
if (this.thereIsCredentials()) {
const headers = this.getHeaderAuth()
// Send axios request
return this.ClientRequest.request(
'POST',
'/' + this.version + '/databases/' + this.apiDatabase + '/sessions', {
headers: headers,
json: []
}
).then((response) => {
this.apiToken = response.token
return this
})
}
return new Exception('Not available without credentials', '')
}
/**
* Close the connection with FileMaker Server API
*
* @returns {DataApi}
* @throws Exception
*/
logout () {
// Send axios request
this.ClientRequest.request(
'DELETE',
'/' + this.version + '/databases/' + this.apiDatabase + '/sessions/' + this.apiToken,
[]
)
this.apiToken = ''
return this
}
/**
* Validate Session
*
* @returns {boolean}
*/
validateSession () {
// Send axios request
const response = this.ClientRequest.request(
'GET',
'/' + this.version + '/validateSession',
{
headers: this.getDefaultHeaders()
}
)
return response
}
// -- End auth Part --
// -- Start records Part --
/**
* Create a new record
*
* @param layout
* @param data
* @param scripts
* @param portalData
* @returns {*}
* @throws Exception
*/
createRecord (layout, data, scripts = [], portalData = {}) {
// Prepare options
const jsonOptions = this.encodeFieldData(data)
if (Object.keys(portalData).length > 0) {
jsonOptions.portalData = this.encodePortalData(portalData)
}
// Add scripts
this.prepareScriptOptions(scripts, jsonOptions)
// Send axios request
const response = this.ClientRequest.request(
'POST',
'/' + this.version + '/databases/' + this.apiDatabase + '/layouts/' + layout + '/records',
{
headers: this.getDefaultHeaders(),
json: jsonOptions
}
)
return response
}
/**
* Duplicate an existing record
*
* @param layout
* @param recordId
* @param scripts
* @returns {*}
* @throws Exception
*/
duplicateRecord (layout, recordId, scripts = []) {
// Send axios request
const response = this.ClientRequest.request(
'POST',
'/' + this.version + '/databases/' + this.apiDatabase + '/layouts/' + layout + '/records/' + recordId, {
headers: this.getDefaultHeaders(),
json: this.prepareScriptOptions(scripts)
}
)
return response.recordId
}
/**
* Edit an existing record by ID
*
* @param layout
* @param recordId
* @param data
* @param lastModificationId
* @param portalData
* @param scripts
* @returns {*}
* @throws Exception
*/
editRecord (layout, recordId, data, lastModificationId = '', portalData = {}, scripts = []) {
// Prepare options
const jsonOptions = this.encodeFieldData(data)
if (lastModificationId.length > 0) {
jsonOptions.modId = lastModificationId
}
if (Object.keys(portalData).length > 0) {
jsonOptions.portalData = this.encodePortalData(portalData)
}
// Add scripts
this.prepareScriptOptions(scripts, jsonOptions)
// Send axios request
const response = this.ClientRequest.request(
'PATCH',
'/' + this.version + '/databases/' + this.apiDatabase + '/layouts/' + layout + '/records/' + recordId, {
headers: this.getDefaultHeaders(),
json: jsonOptions
}
)
return response.modId
}
/**
* Delete record by ID
*
* @param layout
* @param recordId
* @param scripts
* @throws Exception
*/
deleteRecord (layout, recordId, scripts = []) {
// Send axios request
return this.ClientRequest.request(
'DELETE',
'/' + this.version + '/databases/' + this.apiDatabase + '/layouts/' + layout + '/records/' + recordId, {
headers: this.getDefaultHeaders(),
json: this.prepareScriptOptions(scripts)
}
)
}
/**
* Get record detail by ID
*
* @param layout
* @param recordId
* @param portals
* @param scripts
* @param responseLayout
* @returns {*}
* @throws Exception
*/
getRecord (layout, recordId, portals = [], scripts = [], responseLayout = '') {
// Prepare options
const jsonOptions = {}
// optional parameters
if (responseLayout.length > 0) {
jsonOptions['layout.response'] = responseLayout
}
// Add scripts
this.prepareScriptOptions(scripts, jsonOptions)
// Add portals
this.preparePortalsOptions(portals, jsonOptions)
// Send axios request
const response = this.ClientRequest.request(
'GET',
'/' + this.version + '/databases/' + this.apiDatabase + '/layouts/' + layout + '/records/' + recordId, {
headers: this.getDefaultHeaders(),
queryParams: jsonOptions
}
)
return response
}
/**
* Get list of records
*
* @param layout
* @param sort
* @param offset
* @param limit
* @param portals
* @param scripts
* @param responseLayout
* @returns {*}
* @throws Exception
*/
getRecords (layout, sort = '', offset = '', limit = '', portals = [], scripts = [], dataInfo = false, responseLayout = '') {
// Search options
const jsonOptions = this.prepareJsonOption({}, offset, limit, sort, responseLayout, true)
// Add scripts
this.prepareScriptOptions(scripts, jsonOptions)
// Add portals
this.preparePortalsOptions(portals, jsonOptions)
// Send axios request
return this.ClientRequest.request(
'GET',
'/' + this.version + '/databases/' + this.apiDatabase + '/layouts/' + layout + '/records',
{
headers: this.getDefaultHeaders(),
queryParams: jsonOptions
},
dataInfo
)
}
/**
* Find records
*
* @param layout
* @param query
* @param sort
* @param offset
* @param limit
* @param portals
* @param scripts
* @param responseLayout
* @returns {*}
* @throws Exception
*/
findRecords (layout, query, sort = '', offset = '', limit = '', portals = [], scripts = [], dataInfo = false, responseLayout = '') {
// Prepare query
let preparedQuery
if (!Array.isArray(query)) {
preparedQuery = [query]
} else {
preparedQuery = this.prepareQueryOptions(query)
}
// Prepare options
const jsonOptions = {
query: JSON.stringify(preparedQuery)
}
// Search options
this.prepareJsonOption(jsonOptions, offset, limit, sort, responseLayout)
// Add scripts
this.prepareScriptOptions(scripts, jsonOptions)
// Add portals
this.preparePortalsOptions(portals, jsonOptions)
// Send axios request
const response = this.ClientRequest.request(
'POST',
'/' + this.version + '/databases/' + this.apiDatabase + '/layouts/' + layout + '/_find',
{
headers: this.getDefaultHeaders(),
json: jsonOptions
},
dataInfo
)
return response
}
// -- End records Part --
// -- Start scripts Part --
/**
* Execute script alone
*
* @param layout
* @param scriptName
* @param scriptParam
* @returns {*}
* @throws Exception
*/
executeScript (layout, scriptName, scriptParam = '') {
// Prepare options
const jsonOptions = {}
// optional parameters
if (scriptParam.length > 0) {
jsonOptions['script.param'] = scriptParam
}
// Send axios request
const response = this.ClientRequest.request(
'GET',
'/' + this.version + '/databases/' + this.apiDatabase + '/layouts/' + layout + '/script/' + scriptName, {
headers: this.getDefaultHeaders(),
queryParams: jsonOptions
}
)
return response
}
// -- End scripts Part --
// -- Start container Part --
/**
* Upload files into container field with or without specific repetition
*
* @param layout
* @param recordId
* @param containerFieldName
* @param containerFieldRepetition
* @param file
* @returns {boolean}
* @throws Exception
*/
uploadToContainer (layout, recordId, containerFieldName, containerFieldRepetition = '', file) {
// Prepare options
let containerFieldRepetitionFormat = ''
if (containerFieldRepetition.length > 0) {
containerFieldRepetitionFormat = '/' + parseInt(containerFieldRepetition)
}
const headers = this.getDefaultHeaders()
headers['Content-Type'] = 'application/json'
// Send axios request
const response = this.ClientRequest.request(
'POST',
'/' + this.version + '/databases/' + this.apiDatabase + '/layouts/' + layout + '/records/' + recordId + '/containers/' + containerFieldName + containerFieldRepetitionFormat, {
headers: headers,
fileObject: file
}
)
return response
}
// -- End container Part --
// -- Start globals Part --
/**
* Define one or multiple global fields
*
* @param layout
* @param globalFields
* @returns {*}
* @throws Exception
*/
setGlobalFields (layout, globalFields) {
// Send axios request
const response = this.ClientRequest.request(
'PATCH',
'/' + this.version + '/databases/' + this.apiDatabase + '/globals', {
headers: this.getDefaultHeaders(),
json: {
globalFields: JSON.stringify(globalFields)
}
}
)
return response
}
// -- End globals Part --
// -- Start metadata Part --
/**
* @returns {*}
* @throws Exception
*/
getProductInfo () {
// Send axios request
const response = this.ClientRequest.request(
'GET',
'/' + this.version + '/productInfo', {
headers: this.getDefaultHeaders(),
json: []
}
)
return response
}
/**
* @returns {*}
* @throws Exception
*/
getDatabaseNames () {
// Available only if there is credentials
if (this.thereIsCredentials()) {
// Send axios request
const response = this.ClientRequest.request(
'GET',
'/' + this.version + '/databases', {
headers: this.getHeaderAuth(),
json: []
}
)
return response
}
return new Exception('Not available without credentials', '')
}
/**
* @returns {*}
* @throws Exception
*/
getLayoutNames () {
// Send axios request
const response = this.ClientRequest.request(
'GET',
'/' + this.version + '/databases/' + this.apiDatabase + '/layouts', {
headers: this.getDefaultHeaders(),
json: []
}
)
return response
}
/**
* @returns {*}
* @throws Exception
*/
getScriptNames () {
// Send axios request
const response = this.ClientRequest.request(
'GET',
'/' + this.version + '/databases/' + this.apiDatabase + '/scripts', {
headers: this.getDefaultHeaders(),
json: []
}
)
return response
}
/**
* @param layout
* @param recordId
* @returns {*}
* @throws Exception
*/
getLayoutMetadata (layout, recordId = '') {
// Prepare options
const jsonOptions = []
let metadataFormat = '/metadata'
if (recordId.length > 0) {
jsonOptions.recordId = recordId
metadataFormat = ''
}
// Send axios request
const response = this.ClientRequest.request(
'GET',
'/' + this.version + '/databases/' + this.apiDatabase + '/layouts/' + layout + metadataFormat, {
headers: this.getDefaultHeaders(),
json: jsonOptions
}
)
return response
}
// -- End metadata Part --
// -- Class accessors --
/**
* Get API token returned after a successful login
*
* @returns {*|null}
*/
getApiToken () {
return this.apiToken
}
/**
* Set API token returned after a successful login
*
* @param apiToken
* @returns {*|null}
*/
setApiToken (apiToken) {
this.apiToken = apiToken
}
/**
* @param version
*/
setVersion (version) {
this.version = version
}
/**
* Set API token in request headers
*
* @returns {{Authorization: (*|null)}}
*/
getDefaultHeaders () {
return {
Authorization: 'Bearer ' + this.apiToken
}
}
/**
* Get header authorization for basic Auth
*
* @returns {{Authorization: *}}
*/
getHeaderBasicAuth () {
return {
Authorization: 'Basic ' + btoa(this.apiUsername + ':' + this.apiPassword)
}
}
/**
* Get header authorization for OAuth
*
* @returns {{"X-FM-Data-Login-Type": string, "X-FM-Data-OAuth-Request-Id": *, "X-FM-Data-OAuth-Identifier": *}}
*/
getHeaderOAuth () {
return {
'X-FM-Data-Login-Type': 'oauth',
'X-FM-Data-OAuth-Request-Id': this.oAuthRequestId,
'X-FM-Data-OAuth-Identifier': this.oAuthIdentifier
}
}
/**
* Get Header switch to parameters
*
* @returns {Array}
*/
getHeaderAuth () {
let headers = []
if (this.apiUsername.length > 0) {
headers = this.getHeaderBasicAuth()
}
if (this.oAuthRequestId.length > 0) {
headers = this.getHeaderOAuth()
}
return headers
}
// -- Options worker functions --
/**
* Prepare options fields for query
*
* @param query
* @returns {Array}
*/
prepareQueryOptions (query) {
const item = []
if (Array.isArray(query)) {
for (let index = 0; index < query.length; ++index) {
const queryItem = query[index]
if (!{}.propertyIsEnumerable.call(queryItem, 'fields')) {
break
}
if (!Array.isArray(queryItem.fields)) {
if ({}.propertyIsEnumerable.call(queryItem.fields, 'fieldname') && {}.propertyIsEnumerable.call(queryItem.fields, 'fieldvalue')) {
const obj = {}
obj[queryItem.fields.fieldname.replace('"', '').trim()] = queryItem.fields.fieldvalue
item.push(obj)
}
} else {
const objRequest = {}
for (const index in queryItem.fields) {
const fieldData = queryItem.fields[index]
if ({}.propertyIsEnumerable.call(fieldData, 'fieldname') && {}.propertyIsEnumerable.call(fieldData, 'fieldvalue')) {
objRequest[fieldData.fieldname.replace('"', '').trim()] = fieldData.fieldvalue
} else if ({}.propertyIsEnumerable.call(fieldData, 'omit') && fieldData.omit) {
objRequest.omit = 'true'
}
}
if (Object.entries(objRequest).length > 0) {
item.push(objRequest)
}
}
}
}
return item
}
/**
* Prepare options for script
*
* @param scripts
* @param jsonOptions
* @returns {Array}
*/
prepareScriptOptions (scripts, jsonOptions = {}) {
if (Array.isArray(scripts)) {
let index
const listType = [this.SCRIPT_POSTREQUEST, this.SCRIPT_PREREQUEST, this.SCRIPT_PRESORT]
for (index = 0; index < scripts.length; ++index) {
const script = scripts[index]
if (listType.indexOf(script.type) < 0) {
continue
}
const scriptSuffix = !(script.type === this.SCRIPT_POSTREQUEST) ? '.' + script.type : ''
jsonOptions['script' + scriptSuffix] = script.name
jsonOptions['script' + scriptSuffix + '.param'] = script.param
}
}
return jsonOptions
}
/**
* Prepare options for portals
*
* @param portals
* @param jsonOptions
* @returns {Array}
*/
preparePortalsOptions (portals, jsonOptions = {}) {
if (portals.length <= 0) {
return []
}
const portalList = []
let index
for (index = 0; index < portals.length; ++index) {
const portal = portals[index]
portalList.push(portal.name)
if ({}.propertyIsEnumerable.call(portal, 'offset')) {
const optionName = '_offset.' + portal.name
const obj = {}
obj[optionName.replace('"', '').trim()] = parseInt(portal.offset)
jsonOptions[optionName] = portal.offset
}
if ({}.propertyIsEnumerable.call(portal, 'limit')) {
const optionName = '_limit.' + portal.name
const obj = {}
obj[optionName.replace('"', '').trim()] = parseInt(portal.limit)
jsonOptions[optionName] = portal.limit
}
}
jsonOptions.portal = JSON.stringify(portalList)
return jsonOptions
}
/**
* @param data
* @returns {{fieldData: string}}
*/
encodeFieldData (data) {
return {
fieldData: JSON.stringify(data)
}
}
/**
* @param portal
* @returns {string}
*/
encodePortalData (portal) {
return JSON.stringify(portal)
}
/**
* Prepare recurrent options for requests
*
* @param jsonOptions
* @param offset
* @param limit
* @param sort
* @param responseLayout
* @param withUnderscore
* @returns {Array}
*/
prepareJsonOption (jsonOptions = {}, offset = '', limit = '', sort = '', responseLayout = '', withUnderscore = false) {
const additionalCharacter = (withUnderscore ? '_' : '')
if (sort.length > 0) {
jsonOptions[additionalCharacter + 'sort'] = (Array.isArray(sort) ? JSON.stringify(sort) : sort)
}
if (limit.length > 0) {
jsonOptions[additionalCharacter + 'limit'] = parseInt(limit)
}
if (offset.length > 0 && parseInt(offset) > 0) {
jsonOptions[additionalCharacter + 'offset'] = parseInt(offset)
}
if (responseLayout.length > 0) {
jsonOptions['layout.response'] = responseLayout
}
return jsonOptions
}
/**
* Check if there is credentials set
*
* @returns {boolean}
*/
thereIsCredentials () {
return ((this.apiUsername.length > 0 && this.apiPassword.length > 0) || (this.oAuthRequestId.length > 0 && this.oAuthIdentifier.length > 0))
}
/**
* Just init class properties
*/
initProperties () {
this.apiUsername = ''
this.apiPassword = ''
this.oAuthRequestId = ''
this.oAuthIdentifier = ''
this.apiToken = ''
this.apiDatabase = ''
this.ClientRequest = ''
this.version = this.LASTVERSION
}
}