npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

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! :)