Skip to content
This repository has been archived by the owner on Oct 15, 2022. It is now read-only.

A TypeScript client for the NetSuite SuiteTalk Web Services API

License

Notifications You must be signed in to change notification settings

Stedi-Public-Archive/typesuite

Repository files navigation

TypeSuite™

TypeSuite™ is a TypeScript client for the NetSuite SuiteTalk Web Services API.

Note: TypeSuite is no longer being worked on, supported, or maintained. Check out SuiteTalk REST Web Services as an alternative to integrate with NetSuite.

TypeSuite was built by the team at Stedi, a platform for B2B trade. If you're using TypeSuite to improve how your business operates, we'd love to hear from you.

Usage

Installation

You can install TypeSuite via npm:

npm install --save @stedi-oss/typesuite

Or add it to your package.json manually.

Quickstart

import { Configuration, TypeSuiteClient } from "typesuite";

// You can fetch your credentials from your NetSuite instance
// We recommend storing them somewhere secure like AWS Secrets Manager
const config: Configuration = {
  account: "NetSuite Account ID",
  apiVersion: "NetSuite API Version",
  token: {
    consumerKey: "NetSuite Consumer Key",
    consumerSecret: "NetSuite Consumer Secret",
    tokenKey: "NetSuite Token Key",
    tokenSecret: "NetSuite Token Secret",
  },
};

// Create NetSuite client using above credentials
const client = new TypeSuiteClient(config);

API Details

Configuration

The Configuration object holds generic NetSuite configuration information, including the account ID and auth credentials, API version information, and can even contain shared query options, if desired.

const config: Configuration = {
  account: "NetSuite Account ID",
  apiVersion: "2019_2",
  token: {
    ...
  },
};

Preferences

The Configuration can optionally contain preferences, which will be passed in each request.

const client = new TypesSuiteClient({
  ...,
  preferences: {
    ignoreReadOnlyFields: true
  }
})

See here for supported preferences.

Sending per-request preferences is not currently supported.

API Version

Currently, TypeSuite only supports the 2019_2 WSDL; therefore, the only acceptable configuration option for apiVersion is "2019_2".

We aim to support additional API versions in future versions of TypeSuite, and will update the docs accordingly.

Authentication

TypeSuite uses NetSuite Token Based Auth (TBA), which requires a consumerKey, consumerSecret, tokenKey, and tokenSecret.

const config: Configuration = {
  account: "...",
  apiVersion: "...",
  token: {
    consumerKey: "NetSuite Consumer Key",
    consumerSecret: "NetSuite Consumer Secret",
    tokenKey: "NetSuite Token Key",
    tokenSecret: "NetSuite Token Secret",
  },
};

Reading from NetSuite

Searching for Records

You can search NetSuite for all records of a certain type (e.g. a _purchaseOrder), matching all other criteria (e.g. a status of "pending receipt") in a given time period:

// Add additional imports from our API version
import { SearchRequest } from "typesuite/2019_2/platform_messages";
import { TransactionSearchAdvanced } from "typesuite/2019_2/transactions_sales";

// Set up the correct time you'd like to start the search from
const dateTime = ZonedDateTime.of(
  LocalDateTime.parse("2020-01-01T00:00"),
  ZoneId.UTC
);
const isoFormatter = new DateTimeFormatterBuilder()
  .appendInstant(3)
  .toFormatter(ResolverStyle.STRICT);

// Construct the search request
const searchAdvancedRequest = new SearchRequest({
  searchRecord: new TransactionSearchAdvanced({
    columns: {
      basic: {
        internalId: [{}],
      },
      itemJoin: {
        internalId: [{}],
      },
    },
    criteria: {
      basic: {
        closed: false,
        mainLine: true,
        status: {
          operator: "anyOf",
          searchValue: ["_purchaseOrderPendingReceipt"],
        },
        type: {
          operator: "anyOf",
          searchValue: ["_purchaseOrder"],
        },
        dateCreated: {
          operator: "after",
          searchValue: dateTime.format(isoFormatter),
        },
      },
    },
  }),
});

// Perform NetSuite Search
const response: any = await client
  .search(searchAdvancedRequest)
  .catch((error: any) => {
    console.log("Error during search");
    throw error;
  });

// Do interesting things with the response
console.log("Found %d purchase orders", response.searchResult.totalRecords);

Note that this will return the record references, not the actual record. You'll need to fetch a record, as shown below, to get the full contents.

Resolving a Record

You can fetch an individual record (e.g. a particular purchase order) from NetSuite:

// Add additional imports
import { GetRequest } from "typesuite/2019_2/platform_messages";
import { PurchaseOrder } from "typesuite/2019_2/transactions_purchases";

// Create a PO GET request
const getRequest = new GetRequest({
  baseRef: new RecordRef({
    internalId: "NetSuite Document ID",
    type: "purchaseOrder",
  }),
});

// Perform the request
const response = await client.get(getRequest).catch(function (error: any) {
  console.log("Error fetching purchaseOrder");
  throw error;
});

// Cast the response record appropriately
const purchaseOrder = response.readResponse.record as PurchaseOrder;

Writing to NetSuite

While TypeSuite currently supports types that can be written back to NetSuite, we don't yet have examples. Stay tuned for more!

A note on instantiated objects vs object literals

Building requests to the NetSuite SuiteTalk API frequently involves instantiating quite a few objects. In order to minimize the amount of code required to build all the necessary objects, in many cases an object literal can be provided instead of a fully instantiated object. There are two cases where a fully instantiated object is required. The first case is the outermost object, typically the Request object, which must be created by calling the class' constructor. In the example below, a SearchRequest is explicitly instantiated via new.

const SearchRequest = new SearchRequest({
  ...
  });

The second case where a fully instantiated object is required is where you provide an object that is a subclass of type that is expected for that field. For example, SearchRequest has single field called searchRecord whose type is PlatformCore.SearchRecord. PlatformCore.SearchRecord is an abstract type that isn't meant to be used directly. Instead, you provide one of its subclasses, which includes TransactionSearchBasic. In order for the correct xml for this request to be generated, you must provide a fully instantiated TransactionSearchBasic.

const SearchRequest = new SearchRequest({
  searchRecord: new TransactionSearchBasic({
      ...
    }),
  });

In all other cases you can simply supply an object literal with the data needed for your request. For example, the status and type fields of TransactionSearchBasic have a type of PlatformCore.SearchEnumMultiSelectField, but it is not necessary to create these objects by calling new.

const searchRequest = new SearchRequest({
  searchRecord: new TransactionSearchBasic({
    status: {
      operator: "anyOf",
      searchValue: ["_purchaseOrderPendingReceipt"],
    },
    type: {
      operator: "anyOf",
      searchValue: ["_purchaseOrder"],
    },
  }),
});

Current limitations

API Version

As mentioned above, TypeSuite only supports the 2019_2 WSDL.

Date handling

Right now, you must convert Dates to a string manually. This is due to a complication with one of the underlying libraries that TypeSuite uses and will be fixed in a later release. However, it will always be possible to provide a string for any field in the NetSuite API that holds a Date.

const dateTime = ZonedDateTime.of(
  LocalDateTime.parse("2020-01-01T00:00"),
  ZoneId.UTC
);
const isoFormatter = new DateTimeFormatterBuilder()
  .appendInstant(3)
  .toFormatter(ResolverStyle.STRICT);

const searchRequest = new SearchRequest({
  searchRecord: new TransactionSearchBasic({
    dateCreated: {
      operator: "after",
      searchValue: dateTime.format(isoFormatter),
    },
  }),
});

Development

Build

To build TypeSuite, run npm run build. Source code is located in /src.

Test

To test TypeSuite, run npm run test. Tests are located in /test and use Jest.