Giter Site home page Giter Site logo

luidog / fms-api-client Goto Github PK

View Code? Open in Web Editor NEW
84.0 16.0 26.0 4.56 MB

A FileMaker Server Data API client designed to allow interaction with a FileMaker database from a web environment.

License: MIT License

JavaScript 100.00%
filemaker data-api marpat

fms-api-client's People

Contributors

jwillinghalpern avatar luidog avatar snyk-bot avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

fms-api-client's Issues

fms-api-client - unable to verify the first certificate, local server

I am using the filemaker data api 18 with nodejs v14.15.4 and latest fms-api-client package.

I have a local filemaker server which doesnt have a real SSL certificate, when I try to use the package I always get a problem with the ssl verification since Filemaker server comes with a default SSL certificate which is not valid I get this error message:

{ code: 'UNABLE_TO_VERIFY_LEAF_SIGNATURE', message: 'unable to verify the first certificate' }

I found a workaround but its not ideal it works but I always get a Nodejs warning message.

process.env['NODE_TLS_REJECT_UNAUTHORIZED'] = 0

I think there is a real workaround which I didnt find yet in the fms-api-client package, I tried to use an option from the library which didnt seem to work.

agent: {rejectUnauthorized: false}

Stale DAPI Sessions causing issues

Describe the bug
I took your advice and set up my service to store the client objects in MongoDB and I'm retrieving it by the '_id' which is sent to the client in a JWT token.

The service seems to run fine while the initial DAPI session(s) are active. However, if a session is disconnected, either automatically after the set 15 minutes or manually from the FileMaker admin console, I completely lose the ability to make any requests (finds, edits, deletes, etc.). After some debugging I found that the client.request methods isn't returning a promise causing neither the .then nor .catch blocks execute.

Sometimes the initial request will fail and subsequent requests will work, however a new session is created and that is what is used. Up to 4 new sessions are created even though my concurrency is set to 2.

Expected behavior
Stale/disconnected DAPI sessions should be removed and a new session should be created and used for subsequent requests.

Additional context
Concurrency is set to 2.

A client object retrieved from MongoDB:

  • This was the state of the client object after the session had already expired.
  • Some information removed for security.
{
	"_id" : ObjectId("5e696c3d3927e5281f71e0b9"),
	"name" : "2020-03-11 22:54:53",
	"data" : {
		"track" : false,
		"in" : 0,
		"out" : 0,
		"since" : "2020-03-11T17:54:53-05:00"
	},
	"agent" : {
		"global" : "REMOVED",
		"protocol" : "https",
		"agent" : null,
		"connection" : {
			"server" : "REMOVED",
			"database" : "REMOVED",
			"version" : "vLatest",
			"starting" : true,
			"sessions" : [
				{
					"id" : "b0c87093-e87e-49d7-86b0-0a2f17b0a365",
					"issued" : "2020-03-11T17:54:54-05:00",
					"expires" : "2020-03-11T18:09:54-05:00",
					"used" : "2020-03-11T17:54:54-05:00",
					"active" : true,
					"token" : "REMOVED",
					"url" : "REMOVED"
				}
			],
			"credentials" : {
				"password" : "REMOVED",
				"user" : "REMOVED"
			}
		},
		"concurrency" : 2,
		"queue" : [ ],
		"pending" : [ ],
		"timeout" : 120000,
		"delay" : 1,
		"proxy" : null
	}
}

Export Utility Methods

Is your feature request related to a problem? Please describe.
fieldData and responseId methods are only useable when client is in scope.

Describe the solution you'd like
Move fieldData and responseId helper methods from the client to utilities and export from main module.

Describe alternatives you've considered
keep client in scope.

Additional context
The methods should remain on the client model but use the utility methods. Utility methods will be exported from the main module.

Sessions aren't reused

Describe the bug
Sessions aren't reused, there is a new session created for every request.
This can be reproduced with the code in the example section, where I'm calling a find request every 5 seconds.
The newly created sessions can be observed in the admin-console.
With a few active clients, the number of sessions climbs very quickly.
http://127.0.0.1:16001/admin-console/app/activities

Expected behavior
A session should be set to inactive once it receives a response or an error, so it can be reused for the next request.

Code Examples
`process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0'

const { Filemaker } = require('fms-api-client')

// datastore-connect for fms-api-client
const { connect } = require('marpat')

const config = {
server: 'https://SERVER',
user: 'USER',
password: 'PASS',
db: 'DB',
layout: 'LAYOUT',
value: 'VALUE'
}

test()

async function test() {
try {

    await connect('nedb://memory')

    const client = Filemaker.create({
        database: config.db,
        server: config.server,
        user: config.user,
        password: config.password,
        concurrency: 25,
        timeout: 10000,
    })
    await client.save()

    await findInterval(client)
} catch (error) {
    console.log(error)
}

}

async function findInterval(client) {
const response = await client.find(config.layout, [{ id: config.value }])
console.log(response)
setTimeout(() => {
findInterval(client)
}, 5000)
}`

Additional context
Happens on Filemaker Server 18.0.3, aswell as 18.0.4.

I've identified 2 issues and created a fix in this fork, which seems to work so far.
As I'm not familiar with the project, I might've overlooked something. What do think of it?
radiorottu@f68a77c

Request never completes - Node async bug

Describe the bug
This is an intermittent bug that is related to an async timing issue inherent in Node.

When we make a call to the same FileMaker file in short succession, one of the requests never finishes. This is due to a problem with a promise never resolving or rejecting.

Expected behavior
Request should return with the results of the FileMaker server. The promise should either resolve or reject.

Code Examples
I tracked the bug down to the watcher method on the agent model.

if (!global.FMS_API_CLIENT.WATCHERS[this.global]) {
      const WATCHER = setTimeout(
        function watch() {

What happens is on the second request, the watch with this.global uuid actually exists so it doesn't create a new watcher.

However, the problem is that later on in the watcher, this.pending.length is 0 meaning the watcher is destroyed and the second request never completes.

if (this.queue.length === 0 && this.pending.length === 0) {
            clearTimeout(global.FMS_API_CLIENT.WATCHERS[this.global]);
            delete global.FMS_API_CLIENT.WATCHERS[this.global];
          } else {
            setTimeout(watch.bind(this), this.delay);
          }

Therefore this.resolve() is never called and the promise is left in an unresolved state.

What is being hard to track down is how the watcher can exist if it appears that the second request is not in the pending array. The only explanation is that there is some weird timing issue happening in the Node event loop where things don't line up the way they should.

Tests
Working on this now. Hard to reproduce since it's timing based and therefore intermittent.

Additional context
I'm wondering if there is a better way to deal with the request in the queue/pending than a setTimeout that gets renewed or torn down? Did you every look at the possibility of using Node's event emitter system instead?

One potential solution would be to make the watcher unique for each request

global.FMS_API_CLIENT.WATCHERS[`${this.global}-${some other unique identifier from the request}`] = WATCHER;

Would have to figure out what the unique identifier would be and if there are other repercussions of having individual watchers for each request. Probably won't even need that this.global for the watcher. That seems to be there to reuse the watcher but I'm actually not sure what situation that would ever happen, except for the one I'm experiencing that is a bug.

Browser based library?

Wondering if you've considered porting this to a browser based library? Something that could be perhaps used in frontend apps to pull data from the FileMaker api.

Possible bug

Disclaimer, this may not be a bug. Here is the issue I am experiencing just in case it's not just me.

Describe the bug
Every other request through client.create() method times out. Request 1,3,5,7,9... all fine. Request 2,4,6,8... timeout.

Expected behavior
100% success or failure.

Code Examples
(apologies for the excessive console.log, comes in handy below)

const { Filemaker } = require('fms-api-client');
const { connect } = require('marpat');

const fmUrl = process.env.FM_URL;
const fmApiPath = process.env.FM_APIPATH;
const fmDbname = process.env.FM_DBNAME;
const fmLayout = process.env.FM_LAYOUT;
const fmUsername = process.env.FM_USER;
const fmPassword = process.env.FM_PW;


const execute = (body, cb, client) => {
  connect('nedb://memory')
    .then(db => {
      if(typeof client !== 'undefined'){
        console.log(client);
      }else{
        console.log("Client not defined entering filemaker.js");
      }
      client = Filemaker.create({
        application: fmDbname,
        server: fmUrl,
        user: fmUsername,
        password: fmPassword,
        agent: {rejectUnauthorized: false}
      });
      console.log("Initial client - line 28");
      return client.save()
      .then(client => {
        console.log("Post Initial Save - line 31")
        client.create(fmLayout, {
         FormBody: body
        })
        .then(client => {
          console.log('Post Record Create - line 36');
          cb(null, client);
        })
        .catch(err => {
          console.log("Error on record creation - line 40");
          cb(err, null);
        });
      })
      .catch(err => {
        console.log("Error on intial client save - line 45");
        cb(err, null);
      });
    })
    .catch(err => {
      console.log("Larger Error otherwise unspecified....");
      console.log(err);
    });


}


module.exports = {
  execute: (body, cb) => {
    execute(body, (err, result) => {
        cb(err, result)
    })
  }
}

Tests
N/A

Additional context
Here is a sample of the console output running on my local machine over the course of three requests:

listening on port 3000.....
##### REQUEST 1 ############
express deprecated res.send(status): Use res.sendStatus(status) instead app.js:22:7
Client not defined entering filemaker.js
Initial client - line 28
Post Initial Save - line 31
Post Record Create - line 36
null (success)
##### REQUEST 2 ############
Client not defined entering filemaker.js
Initial client - line 28
Post Initial Save - line 31
Error on record creation - line 40
{ Error: connect ETIMEDOUT 10.10.10.10
    at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1082:14)
  errno: 'ETIMEDOUT',
  code: 'ETIMEDOUT',
  syscall: 'connect',
  address: '10.10.10.10',
  port: 443,
  config:
   { adapter: [Function: httpAdapter],
     transformRequest: { '0': [Function: transformRequest] },
     transformResponse: { '0': [Function: transformResponse] },
     timeout: 0,
     xsrfCookieName: 'XSRF-TOKEN',
     xsrfHeaderName: 'X-XSRF-TOKEN',
     maxContentLength: -1,
     headers:
      { Accept: 'application/json, text/plain, */*',
        'Content-Type': 'application/json',
        authorization:
         'Basic xxxxxxxxxxxxx',
        'User-Agent': 'axios/0.18.0',
        'Content-Length': 2 },
     method: 'post',
     url:
      'https://someserversomewhere//fmi/data/v1/databases/Tabernacles-2019/sessions',
     data: '{}',
     httpsAgent:
      Agent {
        _events: [Object],
        _eventsCount: 1,
        _maxListeners: undefined,
        defaultPort: 443,
        protocol: 'https:',
        options: [Object],
        requests: {},
        sockets: [Object],
        freeSockets: {},
        keepAliveMsecs: 1000,
        keepAlive: false,
        maxSockets: Infinity,
        maxFreeSockets: 256,
        maxCachedSessions: 100,
        _sessionCache: [Object] },
     maxRedirects: 0,
     [Symbol(COOKIEJAR_SUPPORT_LOCAL)]:
      { backupOptions: [Object], jar: undefined, redirectCount: 5 } },
  request:
   ClientRequest {
     _events:
      [Object: null prototype] { response: [Function], error: [Function: handleRequestError] },
     _eventsCount: 2,
     _maxListeners: undefined,
     output: [],
     outputEncodings: [],
     outputCallbacks: [],
     outputSize: 0,
     writable: true,
     _last: true,
     chunkedEncoding: false,
     shouldKeepAlive: false,
     useChunkedEncodingByDefault: true,
     sendDate: false,
     _removedConnection: false,
     _removedContLen: false,
     _removedTE: false,
     _contentLength: 2,
     _hasBody: true,
     _trailer: '',
     finished: true,
     _headerSent: true,
     socket:
      TLSSocket {
        _tlsOptions: [Object],
        _secureEstablished: false,
        _securePending: false,
        _newSessionPending: false,
        _controlReleased: true,
        _SNICallback: null,
        servername: null,
        alpnProtocol: null,
        authorized: false,
        authorizationError: null,
        encrypted: true,
        _events: [Object],
        _eventsCount: 9,
        connecting: false,
        _hadError: true,
        _handle: null,
        _parent: null,
        _host: 'someserversomewhere',
        _readableState: [ReadableState],
        readable: false,
        _maxListeners: undefined,
        _writableState: [WritableState],
        writable: false,
        allowHalfOpen: false,
        _sockname: null,
        _pendingData: [Array],
        _pendingEncoding: '',
        server: undefined,
        _server: null,
        ssl: null,
        _requestCert: true,
        _rejectUnauthorized: false,
        parser: null,
        _httpMessage: [Circular],
        [Symbol(res)]: [TLSWrap],
        [Symbol(asyncId)]: 115,
        [Symbol(lastWriteQueueSize)]: 0,
        [Symbol(timeout)]: null,
        [Symbol(kBytesRead)]: 0,
        [Symbol(kBytesWritten)]: 0,
        [Symbol(connect-options)]: [Object] },
     connection:
      TLSSocket {
        _tlsOptions: [Object],
        _secureEstablished: false,
        _securePending: false,
        _newSessionPending: false,
        _controlReleased: true,
        _SNICallback: null,
        servername: null,
        alpnProtocol: null,
        authorized: false,
        authorizationError: null,
        encrypted: true,
        _events: [Object],
        _eventsCount: 9,
        connecting: false,
        _hadError: true,
        _handle: null,
        _parent: null,
        _host: 'someserversomewhere',
        _readableState: [ReadableState],
        readable: false,
        _maxListeners: undefined,
        _writableState: [WritableState],
        writable: false,
        allowHalfOpen: false,
        _sockname: null,
        _pendingData: [Array],
        _pendingEncoding: '',
        server: undefined,
        _server: null,
        ssl: null,
        _requestCert: true,
        _rejectUnauthorized: false,
        parser: null,
        _httpMessage: [Circular],
        [Symbol(res)]: [TLSWrap],
        [Symbol(asyncId)]: 115,
        [Symbol(lastWriteQueueSize)]: 0,
        [Symbol(timeout)]: null,
        [Symbol(kBytesRead)]: 0,
        [Symbol(kBytesWritten)]: 0,
        [Symbol(connect-options)]: [Object] },
     _header:
      'POST //fmi/data/v1/databases/Tabernacles-2019/sessions HTTP/1.1\r\nAccept: application/json, text/plain, */*\r\nContent-Type: application/json\r\nauthorization: Basic xxxxxxxxx\r\nUser-Agent: axios/0.18.0\r\nContent-Length: 2\r\nHost: someserversomewhere\r\nConnection: close\r\n\r\n',
     _onPendingData: [Function: noopPendingOutput],
     agent:
      Agent {
        _events: [Object],
        _eventsCount: 1,
        _maxListeners: undefined,
        defaultPort: 443,
        protocol: 'https:',
        options: [Object],
        requests: {},
        sockets: [Object],
        freeSockets: {},
        keepAliveMsecs: 1000,
        keepAlive: false,
        maxSockets: Infinity,
        maxFreeSockets: 256,
        maxCachedSessions: 100,
        _sessionCache: [Object] },
     socketPath: undefined,
     timeout: undefined,
     method: 'POST',
     path: '//fmi/data/v1/databases/Tabernacles-2019/sessions',
     _ended: false,
     res: null,
     aborted: false,
     timeoutCb: null,
     upgradeOrConnect: false,
     parser: null,
     maxHeadersCount: null,
     [Symbol(isCorked)]: false,
     [Symbol(outHeadersKey)]:
      [Object: null prototype] {
        accept: [Array],
        'content-type': [Array],
        authorization: [Array],
        'user-agent': [Array],
        'content-length': [Array],
        host: [Array] } },
  response: undefined }
(node:38817) UnhandledPromiseRejectionWarning: TypeError: Converting circular structure to JSON
    at JSON.stringify (<anonymous>)
    at fmdb.execute (/Users/brianmangus/Desktop/lion-lamb/LL-App/app.js:33:33)
    at execute (/Users/brianmangus/Desktop/lion-lamb/LL-App/filemaker.js:60:9)
    at client.create.then.catch.err (/Users/brianmangus/Desktop/lion-lamb/LL-App/filemaker.js:40:11)
    at process.internalTickCallback (internal/process/next_tick.js:77:7)
(node:38817) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 3)
(node:38817) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
#### REQUEST 3 ##########
Client not defined entering filemaker.js
Initial client - line 28
Post Initial Save - line 31
Post Record Create - line 36
null (success)

Sessions not being reused when having multiple concurrent requests

Describe the bug
Requests being made almost concurrently are not seeing each other's sessions connected to FMS causing it to use the same session. For example, we have a button on a page that triggers a hook on FM that waits for 5 seconds. When there's no existent client and we click on this button twice, we see it creating and reusing the new client, but only the last session is being saved to the database (We're using NeDB for this). Once both calls come back, if we click on the button twice again, we'll see that both requests were done using the same session, therefore, running the requests sequentially.

Expected behavior
Sessions being used updated on the fly on the database (NeDB) so if a new request comes in, it would see that the current session is being used and it would create a new one for this new request so it would run the requests concurrently.

Tests
Following are some logs that we can see this issue.

First two calls (no client object saved to the database):

dapiClient id: YOAmXDfqSfs4TGsw
Concurrency: 5
Total Sessions: 1
Sessions:
0: 3bce0ff2-ec9f-4dc0-8d44-d7e628482d7b     active: false
/script_625: 5547.687ms
dapiClient id: YOAmXDfqSfs4TGsw
Concurrency: 5
Total Sessions: 1
Sessions:
0: 0cbd5ac1-1005-4db9-8b54-04011d16d55e     active: false
/script_538: 5536.370ms

Following calls:

dapiClient id: YOAmXDfqSfs4TGsw
Concurrency: 5
Total Sessions: 1
Sessions:
0: 0cbd5ac1-1005-4db9-8b54-04011d16d55e     active: false
/script_124: 5107.766ms
dapiClient id: YOAmXDfqSfs4TGsw
Concurrency: 5
Total Sessions: 1
Sessions:
0: 0cbd5ac1-1005-4db9-8b54-04011d16d55e     active: false
/script_311: 9710.650ms

Call queueing does not work

Describe the bug
Api is not called, or at least fm doesnt seem to respond like it

Expected behavior
api is supposed to be called.

Code Examples

this never finished

const marpat = require("marpat");
const fmsApiClient = require("fms-api-client");


(async () => {

    await marpat.connect('nedb://memory');
    const client = fmsApiClient.Filemaker.create({
        //Credentials
        concurrency: 10
    });
    await client.save();

    const promises = [];
    let x = 0;
    while (x < 10) {
       
        try {
          promises.push ( 
            client.create('Accounts Data API Test | Data API', {account_number: x++ })
            )
        } catch (error) {
            console.error(error);
        }
    }
    console.log('called all');
    await Promise.all(promises);
    console.log('done');
})()

but if we change

promises.push ( 
            client.create('Accounts Data API Test | Data API', {account_number: x++ })
            )

to

            await client.create('Accounts Data API Test | Data API', {account_number: x++ })

it creates all but slow

Tests
i will attempt to do so

Additional context

Extremely outdated dependencies - abandoned?

I'm wondering if this package has perhaps been abandoned? There hasn't been a release in several years and there are a number of dependencies which have critical vulnerabilities.

I can take a run at getting them updated if there is any chance of them being merged?

Opening Multiple FM Data API Sessions

Describe the bug
Multiple FM Data API Session create for each Client Object.
Number of sessions > concurrency

Expected behavior
Maximum number of sessions should be <= concurrency.

Code Examples

router.post('/login', (req, res) => {

  // FM Config

  let config = {
    name: `${Date.now()} ${req.body.user}`,
    database: req.body.db,
    concurrency: req.body.concurrency || 2,
    server: req.body.server,
    user: req.body.user,
    password: req.body.pswd,
    usage: true,
    timeout: 1000 * 60 * 2 // 2 Minutes
  };

  connect('nedb://memory')
    .then(db => {
      // Create Client
      const FM = Filemaker.create(config);
      return FM.save();
    })
    .then(client => {
      // Login using new client object
      client
        .login(result => result)
        .then(result => {
      // Create "Token"
          let hash = crypto
            .createHash('sha256')
            .update(`${Date.now()} ${req.body.user}`)
            .digest('hex');
      // Store Client Object in a local object with the "Token" as the key. Then send the requesting client the "Token"
          clientPool[hash] = client;
          res.send({
            client,
            hash
          });
        })
        .catch(err => {
          console.log(err);
          res.status(400).send(err);
        });
    })
    .catch(err => {
      console.log('Marpat Error: ' + err);
      res.status(400).send(err);
    });
});

Additional context
I created a nodejs "Micro-service" to facilitate interaction between FM and React Native. In order to handle multiple different users/connections I created the endpoint above.

The idea was that the user would send their credentials and the service would create a unique hash which would serve as sort of a token. It then stores the Client object as the value in a local JS object with the token as the key.

Everything seems to work as expected, however, when one or multiple client objects are used to call any of the fms-api-client methods there is 40+ Data API sessions opened. On the FM Server Console it shows that each one of the users spawns multiple sessions even if only one user's client object was used.

What am I doing wrong?

Going over concurrency doesn't throw an error but hangs

Describe the bug
I'm trying to make 3 concurrent calls with the same client. As soon as I add the third request it hangs and never returns a response.

Expected behavior
I'd like to better understand the concurrency setting and its expected behavior. I would expect it to throw an error when there aren't enough connections and the call fails. Part of the issue may be that my lambda is timing out before fms-api-client is able to get a response. However, I've raised the timeout quite high and it doesn't seem to change anything. Whereas if I up the concurrency to 6, it works just fine. Just don't want to run into issue where I run out of connection and it fails and there is no error to tell me what is happening.

Code Examples


async function getFmsApiClient(database) {
  const fmsApiClient = Filemaker.create({
    name: `client-${database}`,
    database: database,
    concurrency: 3,
    server: `${process.env.SERVER}`,
    user: `${process.env.USER}`,
    password: `${process.env.PASSWORD}`,
    usage: true,
    timeout: 20000,
  });
  await fmsApiClient.save();

  return fmsApiClient;
}

app.use(async (req, res, next) => {
  await connect("nedb://memory");
  next();
});

router.get("/config/test", async function (req, res, next) {
  const client = await getFmsApiClient("DATABASENAME");

  const getCodes = (layout, listName) => {
    return client
      .find(encodeURI(layout), [{ z_SYS_List_Type_t: listName }])
      .catch((err) => {
        throw new Error(err);
      });
  };

  const codes = await Promise.all([
    getCodes("[LIST] Programming Type", "[SYS] Programming List").catch((err) =>
      console.log(err)
    ),
    getCodes("[LIST] Promo Code Letter", "Promo Code Letter").catch((err) =>
      console.log(err)
    ),
    getCodes("[LIST] Promo Spot Type", "Spot Type List").catch((err) =>
      console.log(err)
    ),
  ]).catch((err) => console.error(err.message));

  res.json({ codes: codes });
});

We're using Express to build an API in front of our FileMaker app. Created the getFmsApiClient to make it easy to create new clients for each file we need to access (it's a large multi-file solution).

Using getCodes to make the find easy and return a promise that should be resolved in the promise.all.

I'm still struggling to understand how marpat works and how the client system works which is making it difficult to debug this issue.

Invalid FileMaker Data API token when using multiple clients

Describe the bug
When creating 2 separate fms-api-client clients for different files, and making a single async calls with each client, the second call will fail.

Expected behavior
It's unexpected that completely separate clients would affect each other. It seems as though there is some sort of collision between the clients that is causing the wrong token to be used.

Code Examples

const { Filemaker } = require("fms-api-client");
const { connect } = require("marpat");
require("dotenv").config({ path: "./.env" });

connect("nedb://memory").then(() => {

  const fmsApiClient1 = Filemaker.create({
    name: `client-database1`,
    database: "database1",
    concurrency: 30,
    server: `${process.env.URL}`,
    user: `${process.env.USERNAME}`,
    password: `${process.env.PASSWORD}`,
    usage: true,
    timeout: 60000,
  });
  const client1 = fmsApiClient1.save();

  const fmsApiClient2 = Filemaker.create({
    name: `client-database2`,
    database: "database2",
    concurrency: 30,
    server: `${process.env.URL}`,
    user: `${process.env.USERNAME}`,
    password: `${process.env.PASSWORD}`,
    usage: true,
    timeout: 60000,
  });
  const client2 = fmsApiClient2.save();

  Promise.all([client1, client2])
    .then(([db1Client, db2Client]) => {
      db1Client.layout("REST_Value_Lists")
        .then((result) => {
          console.log("Result of db1Client");
        })
        .catch((err) => {
          console.log("Error of db1Client");
        });

      db2Client.layout("REST_Value_Lists")
        .then((result) => {
          console.log("Result of db2Client");
        })
        .catch((err) => {
          console.log("Error of db2Client");
        });
    })
});

Additional context
I'm not sure really where to look on this one. Any help knowing where to look would be great. Have VS Code debugger hooked up but still not being able to really track what it going on.

How does fms-api-client decide when to look for a new token. Seems to be in the agent.model file but can't track it down.

Thanks

Unable to login/query for records

Describe the bug
Im getting a couple of issues when using this library. related to login in, and response handling.

I tried Filemaker.create to get a client but it wouldnt work, so i consoled Filemaker as well as the code and thought it was a class so i started using new which sort of worked.

in regards to login in, the preinit hook is not being triggered, so when i try to query it says that this.connection.valid is not a function.

if i call preinit manually and then try to query, i get a response saying

\n\n<title>400 Bad Request</title>\n\n

Bad Request

\n

Your browser sent a request that this server could not understand.
\n

\n
\nApache/2.4.27 (Win64) PHP/5.6.31 Server at localhost Port 80\n\n

Expected behavior
I am able to query for records.

Code Examples
import { connect } from 'marpat';
import { Filemaker } from 'fms-api-client';

connect('nedb://memory')
.then(() => new Filemaker(credentials))
.then(client => {
const getRecordsToProcess = () => client.list(patientsLayout, {});

client.preInit(credentials);
getRecordsToProcess().then(console.log);

});

Tests
If possible write a failing test that showcases the bug.

Additional context
I saw that you have several test for this package and that its running correctly, i tried to look at the test to see what i was doing wrong but i couldnt figure it out:(

Authenticate Method Response Handling

Describe the bug
The authenticate method does not properly catch and reject 502 Bad Gateway responses. The method attempts to access an undefined property which causes an unhandled rejection.

Expected behavior
The authenticate method should check for a 502 Bad Gateway response and generate an appropriate message.

Performance Question

having issues with FM here. I was just wondering, what kind of performance would you say you can get inserting minimal data into FM through api.

i have a minimal solution and code, and i try to insert 100k records. It starts insering at 30 per sec, and then it drops to about 13 after 4k records and eventually it drops to like 4 per second. in your experience, is this normal?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.