afas-connect
v3.0.6
Published
An API that makes it easy to connect to Afas Profit REST services written entirely in TypeScript.
Downloads
501
Readme
What is AFAS Connect?
An all-in-one API that makes it easy to connect to Afas Profit REST / SOAP services written entirely in TypeScript.
Table of Contents
Installation
To install using npm, simply:
$ npm install afas-connect
Yarn:
$ yarn add afas-connect
Initializing
v3.x
const { Profit } = require('afas-connect');
const { Languages, EnvTypes } = require('afas-connect/lib/models');
const ProfitService = new Profit({
token: '<YOUR_TOKEN_HERE>', // <token><version>1</version><data>....</data></token>
env: '12345',
envType: EnvTypes.Production, // or 'production' like in v2.x
// Optional
language: Languages.Dutch // or 'nl-nl'
})
v2.x
const { Profit } = require('afas-connect');
const ProfitService = new Profit({
token: '<YOUR_TOKEN_HERE>',
env: '12345',
envType: 'production'
})
v1.x
const { Profit } = require('afas-connect');
const ProfitService = new Profit({
apiKey: '<YOUR_TOKEN_HERE>',
env: '12345',
envType: 'production'
})
Profit API
JSON
Models
From /lib/models you can import some enums which make some options more verbose. They are for convience, so you can still just use 1 instead of OperatorTypes.EqualTo if you want to.
// All enums
const { OrderBy, OperatorTypes, Languages, EnvTypes, ImageSizes } = require('afas-connect/lib/models');
Profit
get Profit.config
// Get the current config
const currentconfig = ProfitService.config
// -> expected response { environment, environmentType }
Profit.metainfo()
// Get environment metainfo
const metainfo = await ProfitService.metainfo()
// -> expected response { updateConnectors: [ { id, description } ], getConnectors: [ { id, description } ], info: { envid, appName, group, tokenExpiry } }
Profit.changeConfig(AfasConfig)
// Change the current AfasConfig
ProfitService.changeConfig({ env: "67890" })
GetConnector
GetConnector.get(getconnectorname[, config])
// Getting data
const response = await ProfitService.GetConnector.get('Profit_Article' [, config])
// -> expected response { skip: 0, take: 100, rows: [...] }
GetConnector.metainfo(getconnectorname)
// Getting the metainfo of a getconnector
const metainfo = await ProfitService.GetConnector.metainfo('Profit_Article')
// -> expected response { rows: [...] }
// If left empty, for example .metainfo(''), it will give a list of all connectors. Use Profit.metainfo() then instead
GetConnector Config Schema
const { OrderBy, OperatorTypes } = require('afas-connect/lib/models');
{
// `skip` indicates how much records AFAS should skip
skip: number
// `take` indicates the max records AFAS should take
take: number,
// `orderby` controls the order by which the records will be recieved
orderby: [
{
fieldId: string,
order: 'ASC', 'DESC' or OrderBy.* // Example: OrderBy.Ascending, which is basically 'ASC' but more verbose
},
{
...
}
],
// `filter` allows the recieved records to be filtered to, for example, a single record which you want
filter: [
{
filterfieldid: string,
filtervalue: string,
operatortype: number or OperatorType.*, // example: OperatorType.EqualTo, which is basically 1 but more verbose
or: [
{
filtervalue: string,
operatortype: number or OperatorType.*
},
{
...
}
]
}
]
}
Advanced examples GetConnector
Here we will make full use of the config when getting from a GetConnector
const { OrderBy, OperatorTypes } = require('afas-connect/lib/models');
// Getting data using filter
const config1 = {
skip: 0,
take: 50,
orderby: [
{
fieldId: 'Itemcode',
order: OrderBy.Ascending
},
{
fieldId: 'Date',
order: OrderBy.Descending
}
],
filter: [
{
filterfieldid: 'Itemcode',
filtervalue: '12345AB',
operatortype: OperatorTypes.EqualTo,
or: [
{
filtervalue: '6789CD',
operatortype: OperatorTypes.ContainsText
},
{
filtervalue: '0000',
operatortype: OperatorTypes.StartsWith
}
]
}
]
}
const response1 = await ProfitService.GetConnector.get('Profit_Article', config1)
// Or, using the jsonFilter
const config2 = {
skip: 0,
take: 50,
orderby: [{ fieldId: 'Itemcode', order: 'ASC' }, { fieldId: 'Date', order: 'DESC' }],
jsonFilter: {
"Filters": {
"Filter": [
// Base
{
"@FilterId": "Filter 1",
"Field": [
{
"@FieldId": "Itemcode",
"@OperatorType": 1,
"#text": "12345AB"
},
{
"@FieldId": "Date",
"@OperatorType": 1,
"#text": "01-01-2021"
}
]
},
// Or
{
"@FilterId": "Filter 2",
"Field": [
{
"@FieldId": "Itemcode",
"@OperatorType": 6,
"#text": "6789CD"
},
{
"@FieldId": "Date",
"@OperatorType": 1,
"#text": "02-02-2021"
}
]
},
// Or
{
"@FilterId": "Filter 3",
"Field": [
{
"@FieldId": "Itemcode",
"@OperatorType": 10,
"#text": "0000"
}
]
}
]
}
}
}
const response2 = await ProfitService.GetConnector.get('Profit_Article', config2)
UpdateConnector
UpdateConnector.insert(updateconnectorname, body)
// Inserts a record
await ProfitService.UpdateConnector.insert('FbItemArticle', {
FbItemArticle: {
Element: {
Fields: {
ItCd: "123"
}
}
}
})
UpdateConnector.insertSubUpdateMain(updateconnectorname, subupdateconnectorname, body)
// Updates main record, inserts sub record
await ProfitService.UpdateConnector.insertSubUpdateMain('FbItemArticle', 'FbArticleCustom', {
FbItemArticle: {
Element: {
Fields: {
ItCd: "123"
}
}
}
})
UpdateConnector.update(updateconnectorname, body)
// Updates a record
await ProfitService.UpdateConnector.update('FbItemArticle', {
FbItemArticle: {
Element: {
Fields: {
ItCd: "456"
}
}
}
})
UpdateConnector.delete(updateconnectorname, urlparams)
// Deletes a record
await ProfitService.UpdateConnector.delete('FbItemArticle', 'FbItemArticle/FbItemArticle/ItCd/123')
UpdateConnector.metainfo(updateconnectorname)
// Get metainfo
const metainfo = await ProfitService.UpdateConnector.metainfo('FbItemArticle')
// -> expected response { rows: [...] }
DataConnector
DataConnector.version()
// Get AFAS version
const response = await ProfitService.DataConnector.version()
// -> expected response { version: "<YOUR AFAS VERSION>" }
DataConnector.file(fileId, fileName[, binary])
// Get file from AFAS
const response = await ProfitService.DataConnector.file(123, 'report', false)
DataConnector.image(format, imageId[, binary])
const { ImageSizes } = require('afas-connect/lib/models');
// Get an image from AFAS
const response = await ProfitService.DataConnector.image(0 or ImageSizes.Original, 'image' [, false])
DataConnector.subject(subjectId, fileId)
// Get a subject from AFAS
const response = await ProfitService.DataConnector.subject(123, 456)
DataConnector.report(reportId, additionalFilter[, binary])
// Get a report from AFAS
const response = await ProfitService.DataConnector.report(123, '?filterfieldids=Project&filtervalues=Test&operatortypes=1', false)
InsiteConnector
InsiteConnector.profile(insitePrivateKey, insiteCodeParam[, intergrationtokenurl])
// Get profile on Insite
const profile = await ProfitService.InsiteConnector.profile("<INSITE PRIVATE KEY HERE>", "<INSITE 'CODE' URL QUERY PARAM HERE"[, "<EXAMPLE: https://12345.afasinsite.nl/intergrationtoken>"])
InsiteConnector.requestOTP(profileUserId, environmentApiKey, EnvironmentKey)
// Request a user specific token
const request = await ProfitService.InsiteConnector.requestOTP(profile.userId, "<ENVIRONMENT API KEY HERE>", "<ENVIRONMENT KEY HERE>")
InsiteConnector.validateOTP(profileUserId, environmentApiKey, EnvironmentKey, code)
// Validate request
const userToken = await AfasServiceNoTokenNoEnv.InsiteConnector.validateOTP(profile.userId, "<ENVIRONMENT API KEY HERE>", "<ENVIRONMENT KEY HERE>", "<CODE RECIEVED IN EMAIL HERE>")
// -> expected response '<YOUR USER TOKEN>'
Advanced examples InsiteConnector
Using the InsiteConnector in a website intergrated in Insite. Here we create an instance without knowing the environment and token.
const { Profit } = require('afas-connect');
const AfasServiceNoTokenNoEnv = new Profit({
token: '',
env: '',
envType: 'production'
})
// Private key: You will find this in the In & Outsite tab in AFAS
// Code: When a website is intergrated in Insite, a few params will be added to the URL. In the URL is a 'code' query param, use that one here
// (optional) tokenUrl: use the 'tokenUrl' url query param here. SHOULD BE USED IF 'env' IS NOT FILLED IN
const profile = await AfasServiceNoTokenNoEnv.InsiteConnector.profile("<INSITE PRIVATE KEY HERE>", "<INSITE 'CODE' URL QUERY PARAM HERE", "<EXAMPLE: https://12345.afasinsite.nl/intergrationtoken>")
// changing the env is required for the following requests to work. We know what to change it to since we have the users' profile
AfasServiceNoTokenNoEnv.changeConfig({ env: profile.environmentId })
// userId: could be something along the lines of 12345.Employee
// Environment API Key: You will find this in the In & Outsite tab in AFAS
// Environment Key: You will find this in the In & Outsite tab in AFAS
const request = await AfasServiceNoTokenNoEnv.InsiteConnector.requestOTP(profile.userId, "<ENVIRONMENT API KEY HERE>", "<ENVIRONMENT KEY HERE>")
// request will be true if the OTP request did not fail
if (request) {
// The user will recieve an email with a code
// otp: A code recieved in an email upon the request. If you already requested it recently, and did not recieve an email, you should use the most recent code
const userToken = await AfasServiceNoTokenNoEnv.InsiteConnector.validateOTP(profile.userId, "<ENVIRONMENT API KEY HERE>", "<ENVIRONMENT KEY HERE>", "<CODE RECIEVED IN EMAIL HERE>")
AfasServiceNoTokenNoEnv.changeConfig({ token: userToken })
}
SOAP
SoapConnector
SoapConnector.get(getconnectorname)
// Get data using SOAP
const response = await ProfitService.SoapConnector.get('Profit_Article')
// -> expected response { GetDataResult: "<XML DATA STRING />" }
SoapConnector.update(updateconnectorname, xmlstring)
// Insert a record
const XMLstring1 = `
<FbItemArticle xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Element>
<Fields Action="insert">
<ItCd>123</ItCd>
</Fields>
</Element>
</FbItemArticle>
`
await ProfitService.SoapConnector.update('FbItemArticle', XMLstring1)
// Update a record
const XMLstring2 = `
<FbItemArticle xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Element>
<Fields Action="update">
<ItCd>123</ItCd>
</Fields>
</Element>
</FbItemArticle>
`
await ProfitService.SoapConnector.update('FbItemArticle', XMLstring2)
// Delete a record
const XMLstring3 = `
<FbItemArticle xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Element>
<Fields Action="delete">
<ItCd>123</ItCd>
</Fields>
</Element>
</FbItemArticle>
`
await ProfitService.SoapConnector.update('FbItemArticle', XMLstring3)
Planned
- Node fetch to Axios migration
- DataConnector File upload
After this I consider this package to be fairly complete, however! If you would like something added/ changed you can send in a PR or dm me on Discord garbageslave#0438, @garbageslave
From time to time I will probably update this package as things either change or I discover something new. For now, thank you for using this package! :)