Security News
Research
Data Theft Repackaged: A Case Study in Malicious Wrapper Packages on npm
The Socket Research Team breaks down a malicious wrapper package that uses obfuscation to harvest credentials and exfiltrate sensitive data.
@anvilco/anvil
Advanced tools
This library will allow you to interact with the Anvil API in JavaScript / NodeJS.
Anvil provides easy APIs for all things paperwork.
Learn more on our Anvil developer page. See the API guide and the GraphQL reference for full documentation.
This library and the Anvil APIs are intended to be used on a server or server-like environment. It will fail in a browser environment.
yarn add @anvilco/anvil
npm install @anvilco/anvil
A basic example converting your JSON to a filled PDF, then saving the PDF to a file:
import fs from 'fs'
import Anvil from '@anvilco/anvil'
// The ID of the PDF template to fill
const pdfTemplateID = 'kA6Da9CuGqUtc6QiBDRR'
// Your API key from your Anvil organization settings
const apiKey = '7j2JuUWmN4fGjBxsCltWaybHOEy3UEtt'
// JSON data to fill the PDF
const exampleData = {
"title": "My PDF Title",
"fontSize": 10,
"textColor": "#CC0000",
"data": {
"someFieldId": "Hello World!"
}
}
const anvilClient = new Anvil({ apiKey })
const { statusCode, data } = await anvilClient.fillPDF(pdfTemplateID, exampleData)
// By default, if the PDF has been published then the published version is what will
// be filled. If the PDF has not been published, then the most recent version will
// be filled.
//
// However, a version number can also be passed in that will be used retrieve and
// fill a specific version of the PDF.
// You can also use the constant `Anvil.VERSION_LATEST` (or `-1`) to fill the most
// recent version of your PDF, whether that version has been published or not.
// Use this if you'd like to fill out a draft version of your template/PDF.
const options = { versionNumber: Anvil.VERSION_LATEST }
const { statusCode, data } = await anvilClient.fillPDF(pdfTemplateID, exampleData, options)
console.log(statusCode) // => 200
// Data will be the filled PDF raw bytes
fs.writeFileSync('output.pdf', data, { encoding: null })
Creates an Anvil client instance.
options
(Object) - Options for the Anvil Client instance.const anvilClient = new Anvil({ apiKey: 'abc123' })
Fills a PDF template with your JSON data.
First, you will need to have uploaded a PDF to Anvil. You can find the PDF template's id on the API Info
tab of your PDF template's page:
An example:
const fs = require('fs')
// PDF template you uploaded to Anvil
const pdfTemplateID = 'kA6Da9CuGqUtc6QiBDRR'
// Your API key from your Anvil organization settings
const apiKey = '7j2JuUWmN4fGjBxsCltWaybHOEy3UEtt'
// JSON data to fill the PDF
const payload = {
"title": "My PDF Title",
"fontSize": 10,
"textColor": "#CC0000",
"data": {
"someFieldId": "Hello World!"
}
}
// The 'options' parameter is optional
const options = {
"dataType": "buffer"
}
const anvilClient = new Anvil({ apiKey })
const { statusCode, data } = await anvilClient.fillPDF(pdfTemplateID, payload, options)
// Be sure to write the file as raw bytes
fs.writeFileSync('filled.pdf', data, { encoding: null })
pdfTemplateID
(String) - The id of your PDF template from the Anvil UIpayload
(Object) - The JSON data that will fill the PDF template
title
(String) - optional Set the title encoded into the PDF documentfontSize
(Number) - optional Set the fontSize of all filled text. Default is 10.color
(String) - optional Set the text color of all filled text. Default is dark blue.data
(Object) - The data to fill the PDF. The keys in this object will correspond to a field's ID in the PDF. These field IDs and their types are available on the API Info
tab on your PDF template's page in the Anvil dashboard.
{ "someFieldId": "Hello World!" }
options
(Object) - optional Any additional options for the request
dataType
(Enum[String]) - optional Set the type of the data
value that is returned in the resolved Promise
. Defaults to 'buffer'
, but 'arrayBuffer'
and 'stream'
are also supported.Promise
that resolves to an Object
statusCode
(Number) - the HTTP status code; 200
is successdata
(Buffer | ArrayBuffer | Stream) - The raw binary data of the filled PDF if success. Will be either a Buffer, ArrayBuffer, or a Stream, depending on dataType
option supplied to the request.errors
(Array of Objects) - Will be present if status >= 400. See Errors
message
(String)Dynamically generate a new PDF from your HTML and CSS or markdown.
Useful for agreements, invoices, disclosures, or any other text-heavy documents. This does not require you do anything in the Anvil UI other than setup your API key, just send it data, get a PDF. See the generate PDF docs for full details.
Check out our HTML invoice template for a complete HTML to PDF example.
An example:
const fs = require('fs')
// Your API key from your Anvil organization settings
const apiKey = '7j2JuUWmN4fGjBxsCltWaybHOEy3UEtt'
// An example using an HTML to PDF payload
const payload = {
title: 'Example',
type: 'html',
data: {
html: `
<h1 class='header-one'>What is Lorem Ipsum?</h1>
<p>
Lorem Ipsum is simply dummy text...
</p>
<h3 class='header-two'>Where does it come from?</h3>
<p>
Contrary to popular belief, Lorem Ipsum is not simply <i>random text</i>
</p>
`,
css: `
body { font-size: 14px; color: #171717; }
.header-one { text-decoration: underline; }
.header-two { font-style: underline; }
`,
},
}
// An example using a Markdown payload
const payload = {
title: 'Example Invoice',
data: [{
label: 'Name',
content: 'Sally Jones',
}, {
content: 'Lorem **ipsum** dolor sit _amet_',
}, {
table: {
firstRowHeaders: true,
rows: [
['Description', 'Quantity', 'Price'],
['4x Large Widgets', '4', '$40.00'],
['10x Medium Sized Widgets in dark blue', '10', '$100.00'],
['10x Small Widgets in white', '6', '$60.00'],
],
},
}],
}
// The 'options' parameter is optional
const options = {
"dataType": "buffer"
}
const anvilClient = new Anvil({ apiKey })
const { statusCode, data } = await anvilClient.generatePDF(payload, options)
// Be sure to write the file as raw bytes
fs.writeFileSync('generated.pdf', data, { encoding: null })
payload
(Object) - The JSON data that will fill the PDF template
title
(String) - optional Set the title encoded into the PDF documentdata
(Array of Objects) - The data that generates the PDF. See the docs for all supported objects
[{ "label": "Hello World!", "content": "Test" }]
options
(Object) - optional Any additional options for the request
dataType
(Enum[String]) - optional Set the type of the data
value that is returned in the resolved Promise
. Defaults to 'buffer'
, but 'arrayBuffer'
and 'stream'
are also supported.Promise
that resolves to an Object
statusCode
(Number) - the HTTP status code; 200
is successdata
(Buffer | ArrayBuffer | Stream) - The raw binary data of the filled PDF if success. Will be either a Buffer, ArrayBuffer, or a Stream, depending on dataType
option supplied to the request.errors
(Array of Objects) - Will be present if status >= 400. See Errors
message
(String)Creates an Etch Packet and optionally sends it to the first signer.
options
(Object) - An object with the following structure:
variables
(Object) - See the API Documentation area for details. See Examples area for examples.responseQuery
(String) - optional A GraphQL Query compliant query to use for the data desired in the mutation response. Can be left out to use default.mutation
(String) - optional If you'd like complete control of the GraphQL mutation, you can pass in a GraphQL Mutation compliant string that will be used in the mutation call. This string should also include your response query, as the responseQuery
param is ignored if mutation
is passed. Example:
mutation CreateEtchPacket (
$name: String,
...
) {
createEtchPacket (
name: $name,
...
) {
id
eid
...
}
}
Gets the details of an Etch Packet.
options
(Object) - An object with the following structure:
variables
(Object) - Requires eid
eid
(String) - your Etch Packet eidresponseQuery
(String) - optional A GraphQL Query compliant query to use for the data desired in the query response. Can be left out to use default.Generates an Etch sign URL for an Etch Packet signer. The Etch Packet and its signers must have already been created.
options
(Object) - An object with the following structure:
variables
(Object) - Requires clientUserId
and signerEid
clientUserId
(String) - your user eidsignerEid
(String) - the eid of the Etch Packet signer, found in the response of the createEtchPacket
instance methodReturns a Buffer, ArrayBuffer, or Stream of the document group specified by the documentGroupEid in Zip file format.
documentGroupEid
(string) - the eid of the document group to downloadoptions
(Object) - optional Any additional options for the request
dataType
(Enum[String]) - optional Set the type of the data
value that is returned in the resolved Promise
. Defaults to 'buffer'
, but 'arrayBuffer'
and 'stream'
are also supported.Promise
that resolves to an Object
statusCode
(Number) - the HTTP status code, 200
is successresponse
(Object) - the Response object resulting from the client's request to the Anvil appdata
(Buffer | ArrayBuffer | Stream) - The raw binary data of the downloaded documents if success. Will be in the format of either a Buffer, ArrayBuffer, or a Stream, depending on dataType
option supplied to the request.errors
(Array of Objects) - Will be present if status >= 400. See Errors
message
(String)A fallback function for queries and mutations without a specialized function in this client.
See the GraphQL reference for a listing on all possible queries
const result = await client.requestGraphQL({
query: `
query WeldDataQuery ($eid: String!) {
weldData (eid: $eid) {
eid
isComplete
isTest
}
}
`,
variables: { eid: 'nxflNZqxDUbltLUbYWK' },
})
const statusCode = result.statusCode
const httpErrors = result.errors
// These will only be available if the statusCode === 200
const graphqlErrors = result.data.errors
const resultObject = result.data.data.weldData
queryInfo
(Object) - The JSON data that will fill the PDF template
query
(String) - GraphQL query or mutation to run. See the GraphQL reference for a listing on all possible queriesvariables
(Object) - GraphQL variables for the queryPromise
that resolves to an Object
statusCode
(Number) - 200 when successful or when there is a GraphQL error. You will only see > 200 if your query is not found or malformederrors
(String) - HTTP errors when status code > 200data
(Object) - Contains query result and any GraphQL errors
errors
(Array of Objects) - If there are validation errors or errors running the query, they will show heredata
(Object) - Contains the actual result of the query
[queryName]
(Object) - Use the query or mutation name to reference the data that you requested!A fallback function for REST endpoints without a specialized function in this client.
See the GraphQL reference for a listing on all possible queries
const result = await this.requestREST(
`/api/v1/fill/${pdfTemplateID}.pdf`,
{
method: 'POST',
body: JSON.stringify(payload),
headers: {
'Content-Type': 'application/json',
},
},
{
dataType: 'stream',
},
)
url
(String) - URL from the baseURL. e.g. /api/v1/fill
fetchOptions
(Object) - Options passed to node-fetchclientOptions
(Object) - optional Any additional options for the request
dataType
(Enum[String]) - optional Set the type of the data
value that is returned in the resolved Promise
. Defaults to 'buffer'
, 'arrayBuffer'
, 'stream'
, and 'json'
are also supported.Promise
that resolves to an Object
statusCode
(Number) - the HTTP status code; 200
is successdata
(Buffer | ArrayBuffer | Stream) - The raw binary data of the filled PDF if success. Will be either a Buffer, ArrayBuffer, or a Stream, depending on dataType
option supplied to the request.errors
(Array of Objects) - Will be present if status >= 400. See Errors
message
(String)A nice helper to prepare a File upload for use with our GraphQL API. By default, this will upload your files as multipart uploads over the jaydenseric / GraphQL multipart request spec. We use node-fetch
under the hood, and you can see this example to get a bit of an understanding of what's happening behind the scenes. NOTE: Please see below about certain scenarios where you may need to manually provide a filename
.
pathOrSupportedInstance
(String | File | Blob | Stream | Buffer) - Can be one of several things. Here's a list of what's supported, in order of preference:
File
instance.Blob
instance.string
that is a path to a file to be used.ReadStream
instance that must either have either:
path
property (this will usually be present when the stream was loaded from the local file system)filename
provided in the options
parameter.Buffer
instance with a filename
provided in the options
parameter.options
(Object) - Options that may be required when providing certain types of values as the first parameter. For example, Blob
s, Buffer
s and certain kinds of ReadStream
s will not have any notion of what the name of the file is or should be when uploaded.
filename
(String) - Override the filename of the uploaded file here. If providing a generic ReadStream or Buffer, you will be required to provide a filename heremimetype
(String) - Optional mimetype to specify with the resulting file that can be used when a string
path, Buffer
or ReadStream
are provided as the first parameter.Object
that is properly formatted to be coerced by the client for use against our GraphQL API wherever an Upload
type is required.Options for the Anvil Client. Defaults are shown after each option key.
{
apiKey: <your_api_key>, // Required. Your API key from your Anvil organization settings
}
Our API has request rate limits in place. The initial request made by this client will parse the limits for your account from the response headers, and then handle the throttling of subsequent requests for you automatically. In the event that this client still receives a 429 Too Many Requests
error response, it will wait the specified duration then retry the request. The client attempts to avoid 429
errors by throttling requests after the number of requests within the specified time period has been reached.
See the Anvil API docs for more information on the specifics of the rate limits.
Our general API Documentation can be found here. It's the best resource for up-to-date information about our API and its capabilities.
See the PDF filling API docs for more information about the fillPDF
method.
Check out the example folder for running usage examples!
First install the dependencies
yarn install
Running tests
yarn test
yarn test:watch
Building with babel will output in the /lib
directory.
yarn test
# Watches the `src` and `test` directories
yarn test:watch
[v3.3.1]
NodeError
type. https://github.com/anvilco/node-anvil/issues/476FAQs
Anvil API Client
We found that @anvilco/anvil demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 0 open source maintainers collaborating on the project.
Did you know?
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.
Security News
Research
The Socket Research Team breaks down a malicious wrapper package that uses obfuscation to harvest credentials and exfiltrate sensitive data.
Research
Security News
Attackers used a malicious npm package typosquatting a popular ESLint plugin to steal sensitive data, execute commands, and exploit developer systems.
Security News
The Ultralytics' PyPI Package was compromised four times in one weekend through GitHub Actions cache poisoning and failure to rotate previously compromised API tokens.