You're Invited:Meet the Socket Team at BlackHat and DEF CON in Las Vegas, Aug 4-6.RSVP
Socket
Book a DemoInstallSign in
Socket

fms-api-client

Package Overview
Dependencies
Maintainers
1
Versions
51
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

fms-api-client

A FileMaker Data API client designed to allow easier interaction with a FileMaker application from a web environment.

1.5.0
Source
npmnpm
Version published
Weekly downloads
31
14.81%
Maintainers
1
Weekly downloads
 
Created
Source

fms-api-client

Build Status Known Vulnerabilities Coverage Status GitHub issues Github commits (since latest release) GitHub license

A FileMaker Data API client designed to allow easier interaction with a FileMaker application from a web environment. This client abstracts the FileMaker 17 Data API into class based methods. You can find detailed documentation on this project here:

fms-api-client Documentation

Installation

npm install --save fms-api-client

Usage

Introduction

The fms-api-client is a wrapper around the FileMaker Data API. Much :heart: to FileMaker for their work on the Data API. The client attempts to follow the terminology used by FileMaker wherever possible. the client uses a lightweight datastore to hold Data API connections. The client contains methods which are modeled after the Data API Endpoints.

Datastore Connection

Connect must be called before the filemaker class is instiantiated. This connect uses Marpat.Marpat is a fork of Camo. Thanks and love to Scott Robinson for his creation and maintenance of Camo. My fork of Camo - Marpat is designed to allow the use of multiple datastores with the focus on encrypted file storage.

For more information on marpat and the different types of supported storage visit marpat

connect('nedb://memory')

Excerpt from ./examples/index.js

Client Creation

After connecting to a datastore you can import and create clients. A client is created using the create method on the client class. The client requires a server and application to connect to as well as valid credentials. Note that the server must be an http or https domain.

    const client = Filemaker.create({
      application: process.env.APPLICATION,
      server: process.env.SERVER,
      user: process.env.USERNAME,
      password: process.env.PASSWORD
    });

Excerpt from ./examples/index.js

A client can be used directly after saving it. It is also stored on the datastore so that it can be reused later.

    return client
      .save()
      .then(client => authentication(client))
      .then(client => creates(client))
      .then(client => lists(client))
      .then(client => finds(client))
      .then(client => edits(client))
      .then(client => scripts(client))
      .then(client => globals(client))
      .then(client => deletes(client))
      .then(client => uploads(client))
      .then(client => utilities(client));

Excerpt from ./examples/index.js

Client Use

All public methods on the client are promises. You can chain together multiple calls.

const createManyRecords = client =>
  Promise.all([
    client.create('Heroes', { name: 'Anakin Skywalker' }, { merge: true }),
    client.create('Heroes', { name: 'Obi-Wan' }, { merge: true }),
    client.create('Heroes', { name: 'Yoda' }, { merge: true })
  ]).then(result => log('create-many-records', result));

Excerpt from ./examples/create.examples.js

Results:

[
  {
    "name": "Anakin Skywalker",
    "recordId": 729077,
    "modId": 0
  },
  {
    "name": "Obi-Wan",
    "recordId": 729073,
    "modId": 0
  },
  {
    "name": "Yoda",
    "recordId": 729075,
    "modId": 0
  }
]

File ./examples/results/create-many-records.json

Authentication

The client contains two methods related to authentication. The client has an authenticate method and the logout method.

Authenticate Method

The authenticate method is used to start a FileMaker user session and generate an authentication. The client will automatically call the authenticate method if it does not have a valid token. This method returns a string rather than an object. The string returned is the authentication token. This method will also save the token to the client's connection for future use.

Note The authenticate will change in an upcoming release. It will be modified to return an object.

const login = client => client.authenticate();

Excerpt from ./examples/authentication.examples.js

Logout Method

The logout method is used to close a FileMaker User session. This method will also remove the current client's authentication token.

Note The logout method will change in an upcoming release. It will be modified to accept a session parameter.

const logout = client =>
  client.logout().then(result => log('client-logout-example', result));

Excerpt from ./examples/authentication.examples.js

Create Records

Using the client you can create filemaker records. To create a record specify the layout to use and the data to insert on creation. The client will automatically convert numbers, arrays, and objects into strings so they can be inserted into a filemaker field.

const createRecord = client =>
  client
    .create('Heroes', {
      name: 'George Lucas'
    })
    .then(result => log('create-record', result));

Excerpt from ./examples/create.examples.js

Result:

{
  "recordId": 729074,
  "modId": 0
}

File ./examples/results/create-record.json

The create method accepts the option of merge. If merge is true the data used to create the with DAPI's response object on success.

const mergeDataOnCreate = client =>
  client
    .create(
      'Heroes',
      {
        name: 'George Lucas'
      },
      { merge: true }
    )
    .then(result => log('create-record-merge', result));

Excerpt from ./examples/create.examples.js

Result:

{
  "name": "George Lucas",
  "recordId": 729072,
  "modId": 0
}

File ./examples/results/create-record-merge.json

The create methods also allows you to trigger scripts when creating a record. Notice the scripts property in the following example. You can specify scripts to run using either FileMaker's script.key syntax or specify an array of scripts with a name, phase, and script parameter.

const triggerScriptsOnCreate = client =>
  client
    .create(
      'Heroes',
      { name: 'Anakin Skywalker' },
      {
        merge: true,
        scripts: [
          { name: 'Create Droids', param: { droids: ['C3-PO', 'R2-D2'] } }
        ]
      }
    )
    .then(result => log('trigger-scripts-on-create', result));

Excerpt from ./examples/create.examples.js

Result:

{
  "name": "Anakin Skywalker",
  "scriptError": 0,
  "recordId": 729076,
  "modId": 0
}

File ./examples/results/trigger-scripts-on-create.json

List Records

You can use the client to list filemaker records. The list method accepts a layout and parameter variable. The client will automatically santize the limit, offset, and sort keys to correspond with the DAPI's requirements.

const listHeroes = client =>
  client
    .list('Heroes', { limit: 5 })
    .then(result => log('list-records-example', result));

Excerpt from ./examples/list.examples.js

Result:

{
  "data": [
    {
      "fieldData": {
        "id": "91C249FB-2127-8B47-9FBD-A4B004D95D5F",
        "name": "Yoda",
        "image(1)": "https://some-server.com/Streaming_SSL/MainDB/07680AA37D5FF57418036B4A1664401C5ED1C192845407761F52BDE15DAD2D7A?RCType=EmbeddedRCFileProcessor",
        "object": "",
        "array": "",
        "height": "",
        "image(2)": ""
      },
      "portalData": {
        "planets": []
      },
      "recordId": "729057",
      "modId": "1"
    },
    {
      "fieldData": {
        "id": "921B1983-2AC9-3647-9EC9-1C99F5BC7259",
        "name": "Darth Vader",
        "image(1)": "",
        "object": "",
        "array": "",
        "height": "",
        "image(2)": ""
      },
      "portalData": {
        "planets": []
      },
      "recordId": "729058",
      "modId": "1"
    },
    {
      "fieldData": {
        "id": "97A3CF0E-869C-EF42-821D-AF59AF650BD9",
        "name": "Obi-Wan",
        "image(1)": "",
        "object": "",
        "array": "",
        "height": "",
        "image(2)": ""
      },
      "portalData": {
        "planets": []
      },
      "recordId": "729061",
      "modId": "0"
    },
    {
      "fieldData": {
        "id": "8AFDEF46-0481-5644-8683-95EC04810BE1",
        "name": "",
        "image(1)": "https://some-server.com/Streaming_SSL/MainDB/691AF27E7EBA2A7BF58E2F52BD4756C46C9301CF7CCE14214C6763EEEF500423?RCType=EmbeddedRCFileProcessor",
        "object": "",
        "array": "",
        "height": "",
        "image(2)": ""
      },
      "portalData": {
        "planets": []
      },
      "recordId": "729064",
      "modId": "1"
    },
    {
      "fieldData": {
        "id": "BBA9D269-0089-F142-ABCA-A3194836C5D3",
        "name": "George Lucas",
        "image(1)": "",
        "object": "",
        "array": "",
        "height": "",
        "image(2)": ""
      },
      "portalData": {
        "planets": []
      },
      "recordId": "729065",
      "modId": "0"
    }
  ]
}

File ./examples/results/list-records-example.json

Find Records

The client's find method will accept either a single object as find parameters or an array. The find method will also santize the limit, sort, and offset parameters to conform with the Data API's requirements.

const findRecords = client =>
  client
    .find('Heroes', [{ name: 'Anakin Skywalker' }], { limit: 1 })
    .then(result => log('find-records-example', result));

Excerpt from ./examples/find.examples.js

Result:

{
  "data": [
    {
      "fieldData": {
        "id": "A63A76F7-804E-C24A-BDB8-53B38598877C",
        "name": "Anakin Skywalker",
        "image(1)": "",
        "object": "",
        "array": "",
        "height": "",
        "image(2)": ""
      },
      "portalData": {
        "planets": []
      },
      "recordId": "729067",
      "modId": "0"
    }
  ]
}

File ./examples/results/find-records-example.json

Edit Records

The client's edit method requires a layout, recordId, and object to use for updating the record.

const editRecords = client =>
  client
    .find('Heroes', [{ name: 'Anakin Skywalker' }], { limit: 1 })
    .then(response => response.data[0].recordId)
    .then(recordId => client.edit('Heroes', recordId, { name: 'Darth Vader' }))
    .then(result => log('edit-record-example', result));

Excerpt from ./examples/edit.examples.js

Result:

{
  "modId": 1
}

File ./examples/results/edit-record-example.json

Delete Records

The client's delete method requires a layout and a record id.

const deleteRecords = client =>
  client
    .find('Heroes', [{ name: 'yoda' }], { limit: 1 })
    .then(response => response.data[0].recordId)
    .then(recordId => client.delete('Heroes', recordId))
    .then(result => log('delete-record-example', result));

Excerpt from ./examples/delete.examples.js

Result:

{}

File ./examples/results/delete-record-example.json

Trigger Scripts

The client's script method requires a script to run and a layout to run on.

Note The trigger script parameter order while change in a future release. It will be modified to swap the script name parameter with the layout parameter.

const triggerScript = client =>
  client
    .script('FMS Triggered Script', 'Heroes', { name: 'Han' })
    .then(result => log('script-trigger-example', result));

Excerpt from ./examples/script.examples.js

Result:

{
  "result": {
    "answer": "Han shot first"
  }
}

File ./examples/results/script-trigger-example.json

Upload Files

The client's upload method will upload file data to a filemaker file. The upload method requires a file path, layout, and container field name.

const uploadImage = client =>
  client
    .upload('./assets/placeholder.md', 'Heroes', 'image')
    .then(result => log('upload-image-example', result));

Excerpt from ./examples/upload.examples.js

Result:

{
  "modId": 1
}

File ./examples/results/upload-image-example.json

You can also provide a record Id to the upload method and the file will be uploaded to that record.

const uploadSpecificImage = client =>
  client
    .find('Heroes', [{ name: 'yoda' }], { limit: 1 })
    .then(response => response.data[0].recordId)
    .then(recordId =>
      client.upload('./assets/placeholder.md', 'Heroes', 'image', recordId)
    )
    .then(result => log('upload-specific-record-example', result));

Excerpt from ./examples/upload.examples.js

Result:

{
  "modId": 1
}

File ./examples/results/upload-specific-record-example.json

Set Session Globals

You can also use the client to set FileMaker Globals for the session.

const setGlobals = client =>
	client
		.globals({ 'Globals::ship': 'Millenium Falcon' })
		.then(result => log('set-globals-example', result));

Excerpt from ./examples/globals.examples.js

Result:

{}

File ./examples/results/set-globals-example.json

Helper Methods

The client also provides helper methods to aid in parsing and manipulating FileMaker Data. There are currently to helper methods.

recordId Method

The recordId method takes either an object or an array of objects with recordId properties and returns either a single recordId or an array of recordIds as strings.

const extractRecordId = client =>
  client
    .find('Heroes', { name: 'yoda' })
    .then(response => recordId(response.data))
    .then(result => log('recordid-utility-example', result));

Excerpt from ./examples/utility.examples.js

Result:

[
  "729068",
  "729075",
  "729078"
]

File ./examples/results/recordid-utility-example.json

fieldData Method

The fieldData method takes either an object or an array of objects and returns either a single object's fieldData or an array of fieldData objects.

const extractFieldData = client =>
  client
    .find('Heroes', { name: 'yoda' })
    .then(response => fieldData(response.data))
    .then(result => log('fielddata-utility-example', result));

Excerpt from ./examples/utility.examples.js

Result:

[
  {
    "id": "F3EE8445-8F11-8D42-B5B8-5442A1D91CF3",
    "name": "Yoda",
    "image(1)": "https://some-server.com/Streaming_SSL/MainDB/AEE712BE129B381ABC9F7B1AFA64F3D8B0A08E17A24AD91AAAE58B163FCEE4CB?RCType=EmbeddedRCFileProcessor",
    "object": "",
    "array": "",
    "height": "",
    "image(2)": "",
    "recordId": "729068",
    "modId": "1"
  },
  {
    "id": "EE42F16D-1C92-CE47-91DF-C2BB6D8D9076",
    "name": "Yoda",
    "image(1)": "",
    "object": "",
    "array": "",
    "height": "",
    "image(2)": "",
    "recordId": "729075",
    "modId": "0"
  },
  {
    "id": "BBAC1BA6-6346-654F-A787-E62BD8D0D0EA",
    "name": "yoda",
    "image(1)": "",
    "object": "",
    "array": "",
    "height": "",
    "image(2)": "",
    "recordId": "729078",
    "modId": "0"
  }
]

File ./examples/results/fielddata-utility-example.json

Tests

npm install
npm test
> fms-api-client@1.4.5 test /Users/luidelaparra/Documents/Development/fms-api-client
> nyc _mocha --recursive  ./tests --timeout=30000 --exit



  Authentication Capabilities
    ✓ should authenticate into FileMaker. (614ms)
    ✓ should automatically request an authentication token (280ms)
    ✓ should reuse a saved authentication token (236ms)
    ✓ should log out of the filemaker. (304ms)
    ✓ should not attempt a logout if there is no valid token.
    ✓ should reject if the logout request fails (472ms)
    ✓ should reject if the authentication request fails (1484ms)

  Create Capabilities
    ✓ should create FileMaker records. (219ms)
    ✓ should reject bad data with an error (3322ms)
    ✓ should create FileMaker records with mixed types (170ms)
    ✓ should substitute an empty object if data is not provided (801ms)
    ✓ should return an object with merged filemaker and data properties (252ms)
    ✓ should allow you to run a script when creating a record with a merge response (261ms)
    ✓ should allow you to specify scripts as an array (271ms)
    ✓ should allow you to specify scripts as an array with a merge response (191ms)
    ✓ should sanitize parameters when creating a new record (827ms)
    ✓ should accept both the default script parameters and a scripts array (216ms)

  Delete Capabilities
    ✓ should delete FileMaker records. (266ms)
    ✓ should trigger scripts via an array when deleting records. (385ms)
    ✓ should trigger scripts via parameters when deleting records. (581ms)
    ✓ should allow you to mix script parameters and scripts array when deleting records. (331ms)
    ✓ should stringify script parameters. (306ms)
    ✓ should reject deletions that do not specify a recordId (173ms)
    ✓ should reject deletions that do not specify an invalid recordId (477ms)

  Edit Capabilities
    ✓ should edit FileMaker records.
    ✓ should reject bad data with an error (379ms)
    ✓ should return an object with merged filemaker and data properties
    ✓ should allow you to run a script when editing a record (682ms)
    ✓ should allow you to run a script via a scripts array when editing a record (367ms)
    ✓ should allow you to specify scripts as an array (279ms)
    ✓ should allow you to specify scripts as an array with a merge response (226ms)
    ✓ should sanitize parameters when creating a new record (218ms)
    ✓ should accept both the default script parameters and a scripts array (229ms)

  Find Capabilities
    ✓ should perform a find request (415ms)
    ✓ should allow you to use an object instead of an array for a find (243ms)
    ✓ should specify omit Criterea (350ms)
    ✓ should allow additional parameters to manipulate the results (3297ms)
    ✓ should allow you to limit the number of portal records to return (3269ms)
    ✓ should allow you to use numbers in the find query parameters (168ms)
    ✓ should allow you to sort the results (256ms)
    ✓ should return an empty array if the find does not return results (271ms)
    ✓ should allow you run a pre request script (3507ms)
    ✓ should return a response even if a script fails (311ms)
    ✓ should allow you to send a parameter to the pre request script (9552ms)
    ✓ should allow you run script after the find and before the sort (3229ms)
    ✓ should allow you to pass a parameter to a script after the find and before the sort (238ms)
    ✓ should reject of there is an issue with the find request (265ms)

  Get Capabilities
    ✓ should get specific FileMaker records. (387ms)
    ✓ should reject get requests that do not specify a recordId (3373ms)
    ✓ should allow you to limit the number of portal records to return (370ms)
    ✓ should accept namespaced portal limit and offset parameters (6384ms)

  Global Capabilities
    ✓ should allow you to set FileMaker globals (262ms)
    ✓ should reject with a message and code if it fails to set a global (221ms)

  Request Interceptor Capabilities
    ✓ should reject if the server errors (133ms)
    ✓ should handle non JSON responses by rejecting with a json error (123ms)
    ✓ should reject non http requests to the server with a json error
*Notice* Data API response does not contain a code
    ✓ should reject non https requests to the server with a json error (3204ms)

  List Capabilities
    ✓ should allow you to list records (3384ms)
    ✓ should allow you use parameters to modify the list response (4095ms)
    ✓ should should allow you to use numbers in parameters (177ms)
    ✓ should should allow you to provide an array of portals in parameters (793ms)
    ✓ should should remove non used properties from a portal object (3284ms)
    ✓ should modify requests to comply with DAPI name reservations (3593ms)
    ✓ should allow strings while complying with DAPI name reservations (307ms)
    ✓ should allow you to offset the list response (270ms)
    ✓ should santize parameters that would cause unexpected parameters (196ms)
    ✓ should allow you to limit the number of portal records to return (9449ms)
    ✓ should accept namespaced portal limit and offset parameters (269ms)
    ✓ should reject invalid parameters (203ms)

  Script Capabilities
    ✓ should allow you to trigger a script in FileMaker (269ms)
    ✓ should allow you to trigger a script in FileMaker (527ms)
    ✓ should allow you to trigger a script in a find (315ms)
    ✓ should allow you to trigger a script in a list (3322ms)
    ✓ should allow reject a script that does not exist (3274ms)
    ✓ should allow return a result even if a script returns an error (278ms)
    ✓ should parse script results if the results are json (182ms)
    ✓ should not parse script results if the results are not json (183ms)
    ✓ should parse an array of scripts (576ms)
    ✓ should trigger scripts on all three script phases (238ms)

  Storage
    ✓ should allow an instance to be created
    ✓ should allow an instance to be saved.
    ✓ should reject if a client can not be validated
    ✓ should allow an instance to be recalled
    ✓ should allow insances to be listed
    ✓ should allow you to remove an instance

  File Upload Capabilities
    ✓ should allow you to upload a file to a new record (1622ms)
    ✓ should allow you to upload a file to a specific container repetition (1452ms)
    ✓ should reject with a message if it can not find the file to upload
    ✓ should allow you to upload a file to a specific record (1617ms)
    ✓ should allow you to upload a file to a specific record container repetition (4932ms)
    ✓ should reject of the request is invalid (442ms)

  Data Usage 
    Tracks Data Usage
      ✓ should track API usage data. (9240ms)
      ✓ should allow you to reset usage data. (511ms)
    Does Not Track Data Usage
      ✓ should not track data usage in (10162ms)
      ✓ should not track data usage out (258ms)

  Utility Capabilities
    ✓ *Depricated* it should extract field while maintaining the array (644ms)
    ✓ *Depricated* it should extract field data while maintaining the object (385ms)
    ✓ *Depricated* it should extract the recordId while maintaining the array (3612ms)
    ✓ *Depricated* it should extract field data while maintaining the object (902ms)
    ✓ it should extract field while maintaining the array (401ms)
    ✓ it should extract field data while maintaining the object (614ms)
    ✓ it should extract the recordId while maintaining the array (349ms)
    ✓ it should extract field data while maintaining the object (607ms)
    ✓ it should remove properties while maintaing the array
    ✓ it should remove properties while maintaing the array


  105 passing (2m)

------------------------------|----------|----------|----------|----------|-------------------|
File                          |  % Stmts | % Branch |  % Funcs |  % Lines | Uncovered Line #s |
------------------------------|----------|----------|----------|----------|-------------------|
All files                     |      100 |      100 |      100 |      100 |                   |
 fms-api-client               |      100 |      100 |      100 |      100 |                   |
  index.js                    |      100 |      100 |      100 |      100 |                   |
 fms-api-client/src           |      100 |      100 |      100 |      100 |                   |
  client.model.js             |      100 |      100 |      100 |      100 |                   |
  connection.model.js         |      100 |      100 |      100 |      100 |                   |
  credentials.model.js        |      100 |      100 |      100 |      100 |                   |
  data.model.js               |      100 |      100 |      100 |      100 |                   |
  index.js                    |      100 |      100 |      100 |      100 |                   |
  request.service.js          |      100 |      100 |      100 |      100 |                   |
 fms-api-client/src/utilities |      100 |      100 |      100 |      100 |                   |
  conversion.utilities.js     |      100 |      100 |      100 |      100 |                   |
  filemaker.utilities.js      |      100 |      100 |      100 |      100 |                   |
  index.js                    |      100 |      100 |      100 |      100 |                   |
------------------------------|----------|----------|----------|----------|-------------------|

Dependencies

  • axios: Promise based HTTP client for the browser and node.js
  • form-data: A library to create readable "multipart/form-data" streams. Can be used to submit forms and file uploads to other web applications.
  • lodash: Lodash modular utilities.
  • marpat: A class-based ES6 ODM for Mongo-like databases.
  • moment: Parse, validate, manipulate, and display dates
  • object-sizeof: Sizeof of a JavaScript object in Bytes
  • prettysize: Convert bytes to other sizes for prettier logging

Dev Dependencies

  • chai: BDD/TDD assertion library for node.js and the browser. Test framework agnostic.
  • chai-as-promised: Extends Chai with assertions about promises.
  • colors: get colors in your node.js console
  • coveralls: takes json-cov output into stdin and POSTs to coveralls.io
  • deep-map: Transforms nested values of complex objects
  • dotenv: Loads environment variables from .env file
  • eslint: An AST-based pattern checker for JavaScript.
  • eslint-config-google: ESLint shareable config for the Google style
  • eslint-config-prettier: Turns off all rules that are unnecessary or might conflict with Prettier.
  • eslint-plugin-prettier: Runs prettier as an eslint rule
  • fs-extra: fs-extra contains methods that aren't included in the vanilla Node.js fs package. Such as mkdir -p, cp -r, and rm -rf.
  • jsdocs: jsdocs
  • minami: Clean and minimal JSDoc 3 Template / Theme
  • mocha: simple, flexible, fun test framework
  • mocha-lcov-reporter: LCOV reporter for Mocha
  • mos: A pluggable module that injects content into your markdown files via hidden JavaScript snippets
  • mos-plugin-dependencies: A mos plugin that creates dependencies sections
  • mos-plugin-execute: Mos plugin to inline a process output
  • mos-plugin-installation: A mos plugin for creating installation section
  • mos-plugin-license: A mos plugin for generating a license section
  • mos-plugin-snippet: A mos plugin for embedding snippets from files
  • nyc: the Istanbul command line interface
  • prettier: Prettier is an opinionated code formatter
  • varium: A strict parser and validator of environment config variables

License

MIT © Lui de la Parra

Keywords

FileMaker

FAQs

Package last updated on 17 Sep 2018

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts