@bitavu/n8n-nodes-bitavu 0.0.0-stage → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +110 -3
- package/dist/credentials/BitavuApi.credentials.js +76 -0
- package/dist/nodes/Bitavu/Bitavu.node.js +232 -0
- package/dist/nodes/Bitavu/Bitavu.node.json +16 -0
- package/dist/nodes/Bitavu/bitavu.svg +1 -0
- package/examples/bitavu-generate-pdf.json +130 -0
- package/package.json +72 -6
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Bitavu
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,110 @@
|
|
|
1
|
-
#
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
# @bitavu/n8n-nodes-bitavu
|
|
2
|
+
|
|
3
|
+
Generate PDFs from [Bitavu](https://bitavu.com)'s visual templates and data in
|
|
4
|
+
your n8n workflow. Design and test the layout in Studio, save a version, then
|
|
5
|
+
use **Bitavu → Generate PDF**.
|
|
6
|
+
|
|
7
|
+
The [HTTP Request guide](https://bitavu.com/support/n8n) remains available for
|
|
8
|
+
n8n Cloud and self-hosted instances. n8n verification of this node is pending.
|
|
9
|
+
|
|
10
|
+
## Installation
|
|
11
|
+
|
|
12
|
+
Self-hosted n8n owners can install `@bitavu/n8n-nodes-bitavu`
|
|
13
|
+
through **Settings → Community nodes → Install**. Follow
|
|
14
|
+
[n8n's installation instructions](https://docs.n8n.io/integrations/community-nodes/installation/).
|
|
15
|
+
n8n Cloud requires a verified community node; this package is not yet verified.
|
|
16
|
+
|
|
17
|
+
## Credentials
|
|
18
|
+
|
|
19
|
+
Create a **Bitavu API** credential and paste your API key. In Studio's
|
|
20
|
+
**Integrations → API keys**, reuse a suitable active key or create one with
|
|
21
|
+
**Generate PDFs** permission for the report. **Read templates** is not needed.
|
|
22
|
+
Keep the secret in Credentials, never in exported workflow JSON.
|
|
23
|
+
|
|
24
|
+
Credential testing sends an authenticated, read-only `GET /v1/credentials/check`
|
|
25
|
+
request. It does not read reports, generate a PDF or consume render credits.
|
|
26
|
+
A successful check confirms the key is recognized; report access, subscription
|
|
27
|
+
and remaining allowance are checked when rendering.
|
|
28
|
+
|
|
29
|
+
## Generate a PDF
|
|
30
|
+
|
|
31
|
+
1. Design a report in [Studio](https://studio.bitavu.com), bind the changing
|
|
32
|
+
content to fields, save a version and test it.
|
|
33
|
+
2. Copy **templateId**, numeric **revision** and **data** from **Integrations →
|
|
34
|
+
Prepare a template request → Use in your app**.
|
|
35
|
+
3. Add **Bitavu → Generate PDF** and select your credential.
|
|
36
|
+
4. Set **Template ID**, **Saved Version** and **Document Data**. Map the JSON
|
|
37
|
+
object using an expression such as `{{ $json.data }}` or `{{ $json }}`.
|
|
38
|
+
5. Execute. Each input item produces a PDF in the **pdf** binary field, ready
|
|
39
|
+
for an email, file-storage or other node accepting binary data.
|
|
40
|
+
|
|
41
|
+
The node calls `POST https://api.bitavu.com/v1/render`, handles Bearer
|
|
42
|
+
authentication and binary PDF output, and keeps TLS verification enabled.
|
|
43
|
+
It preserves input JSON, existing binary fields and item pairing, and adds
|
|
44
|
+
`bitavu` metadata with the template, version, operation ID and filename.
|
|
45
|
+
|
|
46
|
+
Any saved Bitavu report works when the supplied data matches that version.
|
|
47
|
+
`examples/bitavu-generate-pdf.json` uses fictional data with the starter invoice
|
|
48
|
+
(`invoice`, saved version 1) and contains no credentials.
|
|
49
|
+
|
|
50
|
+
## Options and retries
|
|
51
|
+
|
|
52
|
+
- **File Name:** defaults to `<templateId>.pdf`.
|
|
53
|
+
- **Output Binary Field:** defaults to `pdf`.
|
|
54
|
+
- **Operation ID:** optional 16–128 letters, digits, underscores or hyphens.
|
|
55
|
+
Reuse only for identical input.
|
|
56
|
+
|
|
57
|
+
Automatic IDs distinguish executions, nodes, loop iterations and items and stay
|
|
58
|
+
stable when n8n retries the node within one execution. A new execution creates
|
|
59
|
+
new IDs and can consume new credits. For retries across executions, retain a
|
|
60
|
+
unique ID upstream and map it to **Options → Operation ID**. Reusing an ID with
|
|
61
|
+
different data returns a conflict; the node does not hide it by changing the ID.
|
|
62
|
+
|
|
63
|
+
There are no internal automatic retries. Configure retries in n8n and respect
|
|
64
|
+
`Retry-After` for rate limits. After an uncertain network result, retry with the
|
|
65
|
+
same ID and input. Request timeout: 120 seconds.
|
|
66
|
+
|
|
67
|
+
## Errors and privacy
|
|
68
|
+
|
|
69
|
+
Errors explain invalid keys, missing permissions, template/version/data
|
|
70
|
+
mismatches, operation conflicts and allowance limits. Use n8n error workflows
|
|
71
|
+
or **On Error** settings to handle failures.
|
|
72
|
+
|
|
73
|
+
The node does not log keys, document data or PDFs, read files or access
|
|
74
|
+
environment variables. It calls only `api.bitavu.com` and follows no redirects.
|
|
75
|
+
n8n may store execution data and files according to your retention settings.
|
|
76
|
+
Bitavu does not retain render payloads or generated PDFs; explicitly saved
|
|
77
|
+
templates and account records remain stored.
|
|
78
|
+
|
|
79
|
+
## Development and release
|
|
80
|
+
|
|
81
|
+
Scaffolded with n8n's official node CLI. No runtime dependencies. Development
|
|
82
|
+
uses `n8n-workflow` 2.46.5, matching the tested n8n 2.46.7 instance.
|
|
83
|
+
|
|
84
|
+
```sh
|
|
85
|
+
npm ci --ignore-scripts
|
|
86
|
+
npm test
|
|
87
|
+
npm run lint
|
|
88
|
+
npm run typecheck
|
|
89
|
+
npm run vetting:check
|
|
90
|
+
npm run dev
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
Vetting checks both source and the packed package with n8n's scanner, with inline
|
|
94
|
+
lint suppressions disabled. The build restores the pinned TypeScript compiler's
|
|
95
|
+
command shim because the scanner brings a separate TypeScript compiler for its
|
|
96
|
+
own development tooling.
|
|
97
|
+
|
|
98
|
+
Programmatic execution keeps PDF validation, binary output, item pairing and
|
|
99
|
+
execution/node/run/item idempotency together. PDF binary output remains a
|
|
100
|
+
regular workflow result, with AI tool generation disabled. Credentials use
|
|
101
|
+
n8n's standard declarative credential test.
|
|
102
|
+
|
|
103
|
+
Run the Publish workflow manually on the tag for the package version. Supply
|
|
104
|
+
the SHA-256 of the reviewed tarball. The workflow builds and audits the package,
|
|
105
|
+
then publishes with npm provenance if the tarball matches. Configure npm trusted
|
|
106
|
+
publishing for `bitavu/n8n-nodes-bitavu`, workflow `publish.yml`, environment `npm`.
|
|
107
|
+
|
|
108
|
+
## License
|
|
109
|
+
|
|
110
|
+
[MIT](LICENSE)
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.BitavuApi = void 0;
|
|
4
|
+
class BitavuApi {
|
|
5
|
+
constructor() {
|
|
6
|
+
this.name = 'bitavuApi';
|
|
7
|
+
this.displayName = 'Bitavu API';
|
|
8
|
+
this.documentationUrl = 'https://bitavu.com/support/n8n';
|
|
9
|
+
this.icon = {
|
|
10
|
+
light: 'file:../nodes/Bitavu/bitavu.svg',
|
|
11
|
+
dark: 'file:../nodes/Bitavu/bitavu.svg',
|
|
12
|
+
};
|
|
13
|
+
this.httpRequestNode = {
|
|
14
|
+
name: 'Bitavu',
|
|
15
|
+
docsUrl: 'https://bitavu.com/support/n8n',
|
|
16
|
+
apiBaseUrl: 'https://api.bitavu.com',
|
|
17
|
+
};
|
|
18
|
+
this.properties = [
|
|
19
|
+
{
|
|
20
|
+
displayName: 'API Key',
|
|
21
|
+
name: 'apiKey',
|
|
22
|
+
type: 'string',
|
|
23
|
+
typeOptions: { password: true },
|
|
24
|
+
required: true,
|
|
25
|
+
default: '',
|
|
26
|
+
description: 'A Bitavu key with Generate PDFs permission for your saved report. Paste only the key, without Bearer.',
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
displayName: 'Allowed HTTP Request Domains',
|
|
30
|
+
name: 'allowedHttpRequestDomains',
|
|
31
|
+
type: 'hidden',
|
|
32
|
+
default: 'domains',
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
displayName: 'Allowed Domains',
|
|
36
|
+
name: 'allowedDomains',
|
|
37
|
+
type: 'hidden',
|
|
38
|
+
default: 'api.bitavu.com',
|
|
39
|
+
},
|
|
40
|
+
];
|
|
41
|
+
this.authenticate = {
|
|
42
|
+
type: 'generic',
|
|
43
|
+
properties: { headers: { Authorization: '=Bearer {{$credentials.apiKey}}' } },
|
|
44
|
+
};
|
|
45
|
+
this.test = {
|
|
46
|
+
request: {
|
|
47
|
+
baseURL: 'https://api.bitavu.com',
|
|
48
|
+
url: '/v1/credentials/check',
|
|
49
|
+
method: 'GET',
|
|
50
|
+
json: true,
|
|
51
|
+
disableFollowRedirect: true,
|
|
52
|
+
timeout: 15000,
|
|
53
|
+
},
|
|
54
|
+
rules: [
|
|
55
|
+
{
|
|
56
|
+
type: 'responseSuccessBody',
|
|
57
|
+
properties: {
|
|
58
|
+
key: 'authenticated',
|
|
59
|
+
value: false,
|
|
60
|
+
message: 'Bitavu did not accept this API key.',
|
|
61
|
+
},
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
type: 'responseSuccessBody',
|
|
65
|
+
properties: {
|
|
66
|
+
key: 'authenticated',
|
|
67
|
+
value: undefined,
|
|
68
|
+
message: 'Bitavu returned an unexpected credential-check response.',
|
|
69
|
+
},
|
|
70
|
+
},
|
|
71
|
+
],
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
exports.BitavuApi = BitavuApi;
|
|
76
|
+
//# sourceMappingURL=BitavuApi.credentials.js.map
|
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Bitavu = void 0;
|
|
4
|
+
const node_crypto_1 = require("node:crypto");
|
|
5
|
+
const n8n_workflow_1 = require("n8n-workflow");
|
|
6
|
+
const endpoint = 'https://api.bitavu.com/v1/render';
|
|
7
|
+
const messages = {
|
|
8
|
+
INVALID_API_KEY: 'Your API key is invalid, expired or revoked. Check your Bitavu credential.',
|
|
9
|
+
KEY_REPORT: 'This key cannot access the report. Grant it access in Bitavu Integrations.',
|
|
10
|
+
KEY_SCOPE: 'Enable Generate PDFs permission for this key in Bitavu Integrations.',
|
|
11
|
+
IDEMPOTENCY_CONFLICT: 'This operation ID was already used with different data. Use a new ID for a new document.',
|
|
12
|
+
API_VERSION_LIMIT: 'This report reached its rolling saved-version limit. Use a previously tested version or wait for the limit to reset.',
|
|
13
|
+
};
|
|
14
|
+
class Bitavu {
|
|
15
|
+
constructor() {
|
|
16
|
+
this.description = {
|
|
17
|
+
displayName: 'Bitavu',
|
|
18
|
+
name: 'bitavu',
|
|
19
|
+
icon: { light: 'file:bitavu.svg', dark: 'file:bitavu.svg' },
|
|
20
|
+
group: ['transform'],
|
|
21
|
+
version: 1,
|
|
22
|
+
usableAsTool: undefined,
|
|
23
|
+
subtitle: '={{$parameter["operation"] === "generate" ? "Generate PDF" : ""}}',
|
|
24
|
+
description: 'Generate PDFs from visual templates and JSON data',
|
|
25
|
+
defaults: { name: 'Bitavu' },
|
|
26
|
+
inputs: [n8n_workflow_1.NodeConnectionTypes.Main],
|
|
27
|
+
outputs: [n8n_workflow_1.NodeConnectionTypes.Main],
|
|
28
|
+
credentials: [{ name: 'bitavuApi', required: true }],
|
|
29
|
+
properties: [
|
|
30
|
+
{ displayName: 'Resource', name: 'resource', type: 'hidden', default: 'document' },
|
|
31
|
+
{
|
|
32
|
+
displayName: 'Operation',
|
|
33
|
+
name: 'operation',
|
|
34
|
+
type: 'options',
|
|
35
|
+
noDataExpression: true,
|
|
36
|
+
options: [
|
|
37
|
+
{
|
|
38
|
+
name: 'Generate PDF',
|
|
39
|
+
value: 'generate',
|
|
40
|
+
description: 'Fill a saved visual template with JSON data',
|
|
41
|
+
action: 'Generate a PDF',
|
|
42
|
+
},
|
|
43
|
+
],
|
|
44
|
+
default: 'generate',
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
displayName: 'Template ID',
|
|
48
|
+
name: 'templateId',
|
|
49
|
+
type: 'string',
|
|
50
|
+
required: true,
|
|
51
|
+
default: '',
|
|
52
|
+
placeholder: 'invoice',
|
|
53
|
+
description: 'Copy templateId from your saved report in Bitavu Integrations → Use in your app',
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
displayName: 'Saved Version',
|
|
57
|
+
name: 'revision',
|
|
58
|
+
type: 'number',
|
|
59
|
+
required: true,
|
|
60
|
+
default: 1,
|
|
61
|
+
typeOptions: { minValue: 1, numberPrecision: 0 },
|
|
62
|
+
description: 'The numeric revision of the saved report. Keep the tested version pinned so layout changes do not change your automation.',
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
displayName: 'Document Data',
|
|
66
|
+
name: 'data',
|
|
67
|
+
type: 'json',
|
|
68
|
+
required: true,
|
|
69
|
+
default: '={{ $json.data }}',
|
|
70
|
+
description: 'The JSON object expected by your template. Map incoming fields or use an expression such as the entire incoming item.',
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
displayName: 'Options',
|
|
74
|
+
name: 'options',
|
|
75
|
+
type: 'collection',
|
|
76
|
+
placeholder: 'Add Option',
|
|
77
|
+
default: {},
|
|
78
|
+
options: [
|
|
79
|
+
{
|
|
80
|
+
displayName: 'File Name',
|
|
81
|
+
name: 'fileName',
|
|
82
|
+
type: 'string',
|
|
83
|
+
default: '',
|
|
84
|
+
placeholder: 'invoice.pdf',
|
|
85
|
+
description: 'Name for the generated PDF. Defaults to the template ID followed by .pdf.',
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
displayName: 'Operation ID',
|
|
89
|
+
name: 'operationId',
|
|
90
|
+
type: 'string',
|
|
91
|
+
default: '',
|
|
92
|
+
description: 'Optional idempotency key: 16–128 letters, digits, underscores or hyphens. Reuse only for retries with identical input. Automatic IDs stay stable for retries within the same execution; retries in a new execution need an upstream ID.',
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
displayName: 'Output Binary Field',
|
|
96
|
+
name: 'outputField',
|
|
97
|
+
type: 'string',
|
|
98
|
+
default: 'pdf',
|
|
99
|
+
description: 'The binary field containing the PDF for the next node',
|
|
100
|
+
},
|
|
101
|
+
],
|
|
102
|
+
},
|
|
103
|
+
],
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
async execute() {
|
|
107
|
+
var _a, _b;
|
|
108
|
+
const items = this.getInputData();
|
|
109
|
+
const output = [];
|
|
110
|
+
for (let itemIndex = 0; itemIndex < items.length; itemIndex++) {
|
|
111
|
+
try {
|
|
112
|
+
const templateId = this.getNodeParameter('templateId', itemIndex).trim();
|
|
113
|
+
const revision = this.getNodeParameter('revision', itemIndex);
|
|
114
|
+
const options = this.getNodeParameter('options', itemIndex, {});
|
|
115
|
+
const raw = this.getNodeParameter('data', itemIndex);
|
|
116
|
+
let data;
|
|
117
|
+
try {
|
|
118
|
+
data = typeof raw === 'string' ? JSON.parse(raw) : raw;
|
|
119
|
+
}
|
|
120
|
+
catch {
|
|
121
|
+
throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Document Data must be valid JSON.', {
|
|
122
|
+
itemIndex,
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
const invalid = (message) => {
|
|
126
|
+
throw new n8n_workflow_1.NodeOperationError(this.getNode(), message, { itemIndex });
|
|
127
|
+
};
|
|
128
|
+
if (!/^[a-zA-Z0-9_-]{1,80}$/.test(templateId))
|
|
129
|
+
invalid('Enter a valid Template ID from Bitavu Integrations.');
|
|
130
|
+
if (!Number.isSafeInteger(revision) || revision < 1)
|
|
131
|
+
invalid('Saved Version must be a positive integer.');
|
|
132
|
+
if (!data || typeof data !== 'object' || Array.isArray(data))
|
|
133
|
+
invalid('Document Data must be a JSON object, rather than an array or a primitive value.');
|
|
134
|
+
const outputField = String(options.outputField || 'pdf');
|
|
135
|
+
if (!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(outputField) ||
|
|
136
|
+
['__proto__', 'constructor', 'prototype'].includes(outputField))
|
|
137
|
+
invalid('Output Binary Field must be a simple field name, such as pdf.');
|
|
138
|
+
const fileName = String(options.fileName || `${templateId}.pdf`).trim();
|
|
139
|
+
if (!fileName ||
|
|
140
|
+
/[/\\]/.test(fileName) ||
|
|
141
|
+
[...fileName].some((char) => char.charCodeAt(0) < 32 || char.charCodeAt(0) === 127) ||
|
|
142
|
+
!fileName.toLowerCase().endsWith('.pdf'))
|
|
143
|
+
invalid('File Name must end in .pdf and contain no path separators or control characters.');
|
|
144
|
+
const operationId = String(options.operationId ||
|
|
145
|
+
`bitavu-${(0, node_crypto_1.createHash)('sha256')
|
|
146
|
+
.update(JSON.stringify([
|
|
147
|
+
this.getExecutionId(),
|
|
148
|
+
this.getNode().id,
|
|
149
|
+
this.evaluateExpression('{{ $runIndex }}', itemIndex),
|
|
150
|
+
itemIndex,
|
|
151
|
+
]))
|
|
152
|
+
.digest('hex')}`);
|
|
153
|
+
if (!/^[a-zA-Z0-9_-]{16,128}$/.test(operationId))
|
|
154
|
+
invalid('Operation ID must contain 16–128 letters, digits, underscores or hyphens.');
|
|
155
|
+
let response;
|
|
156
|
+
try {
|
|
157
|
+
response = await this.helpers.httpRequestWithAuthentication.call(this, 'bitavuApi', {
|
|
158
|
+
method: 'POST',
|
|
159
|
+
url: endpoint,
|
|
160
|
+
headers: {
|
|
161
|
+
'Idempotency-Key': operationId,
|
|
162
|
+
Accept: 'application/pdf',
|
|
163
|
+
'Content-Type': 'application/json',
|
|
164
|
+
},
|
|
165
|
+
body: JSON.stringify({ templateId, revision, data }),
|
|
166
|
+
encoding: 'arraybuffer',
|
|
167
|
+
returnFullResponse: true,
|
|
168
|
+
ignoreHttpStatusErrors: true,
|
|
169
|
+
disableFollowRedirect: true,
|
|
170
|
+
timeout: 120000,
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
catch {
|
|
174
|
+
throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Could not reach Bitavu. Check your credential and network connection. Retry with the same operation ID if the result is uncertain.', { itemIndex });
|
|
175
|
+
}
|
|
176
|
+
const body = Buffer.isBuffer(response.body)
|
|
177
|
+
? response.body
|
|
178
|
+
: Buffer.from((_a = response.body) !== null && _a !== void 0 ? _a : '');
|
|
179
|
+
if (response.statusCode !== 200) {
|
|
180
|
+
let details = {};
|
|
181
|
+
try {
|
|
182
|
+
details = JSON.parse(body.toString('utf8'));
|
|
183
|
+
}
|
|
184
|
+
catch {
|
|
185
|
+
}
|
|
186
|
+
const code = typeof details.code === 'string' && /^[A-Z0-9_]+$/.test(details.code)
|
|
187
|
+
? details.code
|
|
188
|
+
: '';
|
|
189
|
+
const message = messages[code] ||
|
|
190
|
+
(response.statusCode === 401
|
|
191
|
+
? messages.INVALID_API_KEY
|
|
192
|
+
: response.statusCode === 429
|
|
193
|
+
? 'Bitavu is limiting requests or your render allowance is exhausted. Check your subscription and respect Retry-After before retrying.'
|
|
194
|
+
: response.statusCode === 403
|
|
195
|
+
? 'The key or workspace does not permit this render. Check report access and your subscription.'
|
|
196
|
+
: [400, 404, 422].includes(response.statusCode)
|
|
197
|
+
? 'Check the Template ID, saved version and document fields against your tested Bitavu request.'
|
|
198
|
+
: 'Bitavu could not generate the PDF. Retry later with the same operation ID.');
|
|
199
|
+
throw new n8n_workflow_1.NodeApiError(this.getNode(), { message, code, statusCode: response.statusCode }, { message, httpCode: String(response.statusCode), itemIndex });
|
|
200
|
+
}
|
|
201
|
+
if (!String(response.headers['content-type'] || '').includes('application/pdf') ||
|
|
202
|
+
!body.subarray(0, 5).equals(Buffer.from('%PDF-')))
|
|
203
|
+
invalid('Bitavu returned an unexpected response instead of a PDF. Contact support with the execution reference.');
|
|
204
|
+
const binary = await this.helpers.prepareBinaryData(body, fileName, 'application/pdf');
|
|
205
|
+
output.push({
|
|
206
|
+
json: {
|
|
207
|
+
...items[itemIndex].json,
|
|
208
|
+
bitavu: { templateId, revision, operationId, fileName, outputField },
|
|
209
|
+
},
|
|
210
|
+
binary: { ...items[itemIndex].binary, [outputField]: binary },
|
|
211
|
+
pairedItem: { item: itemIndex },
|
|
212
|
+
});
|
|
213
|
+
}
|
|
214
|
+
catch (error) {
|
|
215
|
+
if (!this.continueOnFail()) {
|
|
216
|
+
if (error instanceof n8n_workflow_1.NodeApiError)
|
|
217
|
+
throw new n8n_workflow_1.NodeApiError(this.getNode(), { message: error.message }, { message: error.message, httpCode: (_b = error.httpCode) !== null && _b !== void 0 ? _b : undefined, itemIndex });
|
|
218
|
+
throw new n8n_workflow_1.NodeOperationError(this.getNode(), error instanceof n8n_workflow_1.NodeOperationError
|
|
219
|
+
? error.message
|
|
220
|
+
: 'Bitavu PDF generation failed. Check the node configuration.', { itemIndex });
|
|
221
|
+
}
|
|
222
|
+
output.push({
|
|
223
|
+
json: { error: error instanceof Error ? error.message : 'Bitavu PDF generation failed.' },
|
|
224
|
+
pairedItem: { item: itemIndex },
|
|
225
|
+
});
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
return [output];
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
exports.Bitavu = Bitavu;
|
|
232
|
+
//# sourceMappingURL=Bitavu.node.js.map
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"node": "@bitavu/n8n-nodes-bitavu.bitavu",
|
|
3
|
+
"nodeVersion": "1.0",
|
|
4
|
+
"codexVersion": "1.0",
|
|
5
|
+
"categories": [
|
|
6
|
+
"Productivity",
|
|
7
|
+
"Data & Storage"
|
|
8
|
+
],
|
|
9
|
+
"resources": {
|
|
10
|
+
"primaryDocumentation": [
|
|
11
|
+
{
|
|
12
|
+
"url": "https://bitavu.com/support/n8n"
|
|
13
|
+
}
|
|
14
|
+
]
|
|
15
|
+
}
|
|
16
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" role="img" aria-label="Bitavu icon"><rect width="512" height="512" rx="112" fill="#ecd06f"/><path d="M160 92H294L384 182V380C384 404 364 424 340 424H160C136 424 116 404 116 380V136C116 112 136 92 160 92ZM182 222V272H280C295 272 306 261 306 247C306 233 295 222 280 222H182ZM182 306V362H286C302 362 314 350 314 334C314 318 302 306 286 306H182Z" fill="#2779a7" fill-rule="evenodd"/><path d="M294 92V144C294 168 308 182 332 182H384L294 92Z" fill="#49c5b6"/></svg>
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "Bitavu - Generate a PDF with the Bitavu node",
|
|
3
|
+
"nodes": [
|
|
4
|
+
{
|
|
5
|
+
"parameters": {},
|
|
6
|
+
"id": "manual-trigger",
|
|
7
|
+
"name": "Run example",
|
|
8
|
+
"type": "n8n-nodes-base.manualTrigger",
|
|
9
|
+
"typeVersion": 1,
|
|
10
|
+
"position": [
|
|
11
|
+
0,
|
|
12
|
+
0
|
|
13
|
+
]
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
"parameters": {
|
|
17
|
+
"assignments": {
|
|
18
|
+
"assignments": [
|
|
19
|
+
{
|
|
20
|
+
"id": "template",
|
|
21
|
+
"name": "templateId",
|
|
22
|
+
"value": "invoice",
|
|
23
|
+
"type": "string"
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
"id": "revision",
|
|
27
|
+
"name": "revision",
|
|
28
|
+
"value": 1,
|
|
29
|
+
"type": "number"
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
"id": "input",
|
|
33
|
+
"name": "data",
|
|
34
|
+
"value": {
|
|
35
|
+
"invoice": {
|
|
36
|
+
"number": "N8N-2087",
|
|
37
|
+
"date": "2026-11-10",
|
|
38
|
+
"due": "2026-11-24"
|
|
39
|
+
},
|
|
40
|
+
"client": {
|
|
41
|
+
"name": "Workflow demo customer",
|
|
42
|
+
"address": "Fictional workflow address"
|
|
43
|
+
},
|
|
44
|
+
"items": [
|
|
45
|
+
{
|
|
46
|
+
"description": "Workflow setup",
|
|
47
|
+
"quantity": 1,
|
|
48
|
+
"unitPrice": 240
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
"description": "Monthly automation",
|
|
52
|
+
"quantity": 2,
|
|
53
|
+
"unitPrice": 90
|
|
54
|
+
}
|
|
55
|
+
],
|
|
56
|
+
"notes": "Generated with data supplied by n8n. Fictional sample data."
|
|
57
|
+
},
|
|
58
|
+
"type": "object"
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
"id": "operation",
|
|
62
|
+
"name": "operationId",
|
|
63
|
+
"value": "={{ 'bitavu-n8n-operation-' + $execution.id + '-' + $itemIndex }}",
|
|
64
|
+
"type": "string"
|
|
65
|
+
}
|
|
66
|
+
]
|
|
67
|
+
},
|
|
68
|
+
"options": {}
|
|
69
|
+
},
|
|
70
|
+
"id": "sample-data",
|
|
71
|
+
"name": "Invoice data",
|
|
72
|
+
"type": "n8n-nodes-base.set",
|
|
73
|
+
"typeVersion": 3.4,
|
|
74
|
+
"position": [
|
|
75
|
+
280,
|
|
76
|
+
0
|
|
77
|
+
]
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
"id": "generate-pdf",
|
|
81
|
+
"name": "Generate PDF with Bitavu",
|
|
82
|
+
"type": "@bitavu/n8n-nodes-bitavu.bitavu",
|
|
83
|
+
"typeVersion": 1,
|
|
84
|
+
"position": [
|
|
85
|
+
560,
|
|
86
|
+
0
|
|
87
|
+
],
|
|
88
|
+
"parameters": {
|
|
89
|
+
"resource": "document",
|
|
90
|
+
"operation": "generate",
|
|
91
|
+
"templateId": "={{ $json.templateId }}",
|
|
92
|
+
"revision": "={{ $json.revision }}",
|
|
93
|
+
"data": "={{ $json.data }}",
|
|
94
|
+
"options": {
|
|
95
|
+
"operationId": "={{ $json.operationId }}"
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
],
|
|
100
|
+
"connections": {
|
|
101
|
+
"Run example": {
|
|
102
|
+
"main": [
|
|
103
|
+
[
|
|
104
|
+
{
|
|
105
|
+
"node": "Invoice data",
|
|
106
|
+
"type": "main",
|
|
107
|
+
"index": 0
|
|
108
|
+
}
|
|
109
|
+
]
|
|
110
|
+
]
|
|
111
|
+
},
|
|
112
|
+
"Invoice data": {
|
|
113
|
+
"main": [
|
|
114
|
+
[
|
|
115
|
+
{
|
|
116
|
+
"node": "Generate PDF with Bitavu",
|
|
117
|
+
"type": "main",
|
|
118
|
+
"index": 0
|
|
119
|
+
}
|
|
120
|
+
]
|
|
121
|
+
]
|
|
122
|
+
}
|
|
123
|
+
},
|
|
124
|
+
"settings": {
|
|
125
|
+
"executionOrder": "v1"
|
|
126
|
+
},
|
|
127
|
+
"active": false,
|
|
128
|
+
"pinData": {},
|
|
129
|
+
"tags": []
|
|
130
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,72 @@
|
|
|
1
|
-
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
1
|
+
{
|
|
2
|
+
"name": "@bitavu/n8n-nodes-bitavu",
|
|
3
|
+
"version": "0.1.1",
|
|
4
|
+
"description": "Generate PDFs from saved Bitavu visual templates and workflow data",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"homepage": "https://bitavu.com/support/n8n",
|
|
7
|
+
"keywords": [
|
|
8
|
+
"n8n-community-node-package"
|
|
9
|
+
],
|
|
10
|
+
"author": {
|
|
11
|
+
"name": "bitavu.com",
|
|
12
|
+
"email": "integration+n8n@bitavu.com",
|
|
13
|
+
"url": "https://bitavu.com"
|
|
14
|
+
},
|
|
15
|
+
"repository": {
|
|
16
|
+
"type": "git",
|
|
17
|
+
"url": "git+https://github.com/bitavu/n8n-nodes-bitavu.git"
|
|
18
|
+
},
|
|
19
|
+
"scripts": {
|
|
20
|
+
"prebuild": "npm rebuild typescript --ignore-scripts --offline --no-audit --no-fund",
|
|
21
|
+
"build": "n8n-node build",
|
|
22
|
+
"build:watch": "tsc --watch",
|
|
23
|
+
"dev": "n8n-node dev",
|
|
24
|
+
"lint": "n8n-node lint",
|
|
25
|
+
"lint:fix": "n8n-node lint --fix",
|
|
26
|
+
"test": "npm run build && node --test tests/*.test.cjs",
|
|
27
|
+
"typecheck": "node node_modules/typescript/bin/tsc --noEmit --incremental false",
|
|
28
|
+
"pack:check": "node scripts/check-package.mjs",
|
|
29
|
+
"vetting:check": "npm run pack:check && node scripts/check-vetting.mjs",
|
|
30
|
+
"privacy:check": "node scripts/check-privacy.mjs",
|
|
31
|
+
"publish:artifact": "node scripts/publish-package.mjs",
|
|
32
|
+
"prepublishOnly": "npm run lint && npm test"
|
|
33
|
+
},
|
|
34
|
+
"files": [
|
|
35
|
+
"dist/credentials/*.js",
|
|
36
|
+
"dist/nodes/Bitavu/*.js",
|
|
37
|
+
"dist/nodes/Bitavu/*.json",
|
|
38
|
+
"dist/nodes/Bitavu/*.svg",
|
|
39
|
+
"examples/*.json"
|
|
40
|
+
],
|
|
41
|
+
"n8n": {
|
|
42
|
+
"n8nNodesApiVersion": 1,
|
|
43
|
+
"strict": true,
|
|
44
|
+
"credentials": [
|
|
45
|
+
"dist/credentials/BitavuApi.credentials.js"
|
|
46
|
+
],
|
|
47
|
+
"nodes": [
|
|
48
|
+
"dist/nodes/Bitavu/Bitavu.node.js"
|
|
49
|
+
]
|
|
50
|
+
},
|
|
51
|
+
"devDependencies": {
|
|
52
|
+
"@n8n/node-cli": "0.57.0",
|
|
53
|
+
"@n8n/scan-community-package": "0.43.0",
|
|
54
|
+
"@types/node": "22.19.19",
|
|
55
|
+
"eslint": "9.32.0",
|
|
56
|
+
"n8n-workflow": "2.46.5",
|
|
57
|
+
"prettier": "3.6.2",
|
|
58
|
+
"typescript": "5.9.2"
|
|
59
|
+
},
|
|
60
|
+
"peerDependencies": {
|
|
61
|
+
"n8n-workflow": "*"
|
|
62
|
+
},
|
|
63
|
+
"engines": {
|
|
64
|
+
"node": ">=22.16"
|
|
65
|
+
},
|
|
66
|
+
"publishConfig": {
|
|
67
|
+
"access": "public"
|
|
68
|
+
},
|
|
69
|
+
"bugs": {
|
|
70
|
+
"url": "https://github.com/bitavu/n8n-nodes-bitavu/issues"
|
|
71
|
+
}
|
|
72
|
+
}
|