@bitavu/n8n-nodes-bitavu 0.1.2 → 0.1.4

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.
@@ -0,0 +1,331 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.bitavuListSearch = exports.versionPicker = exports.templatePicker = exports.bitavuNodeDefaults = void 0;
4
+ exports.executeBitavu = executeBitavu;
5
+ const node_crypto_1 = require("node:crypto");
6
+ const n8n_workflow_1 = require("n8n-workflow");
7
+ const BitavuApi_1 = require("./BitavuApi");
8
+ exports.bitavuNodeDefaults = {
9
+ group: ['transform'],
10
+ version: 1,
11
+ inputs: [n8n_workflow_1.NodeConnectionTypes.Main],
12
+ outputs: [n8n_workflow_1.NodeConnectionTypes.Main],
13
+ credentials: [{ name: 'bitavuApi', required: true }],
14
+ };
15
+ exports.templatePicker = {
16
+ displayName: 'Template',
17
+ name: 'templateId',
18
+ type: 'resourceLocator',
19
+ required: true,
20
+ default: { mode: 'id', value: '' },
21
+ modes: [
22
+ {
23
+ displayName: 'From List',
24
+ name: 'list',
25
+ type: 'list',
26
+ typeOptions: { searchListMethod: 'searchTemplates', searchable: true },
27
+ },
28
+ {
29
+ displayName: 'By ID',
30
+ name: 'id',
31
+ type: 'string',
32
+ placeholder: 'invoice',
33
+ },
34
+ ],
35
+ description: 'Choose an accessible template with Read templates permission, or enter a template ID or expression',
36
+ };
37
+ exports.versionPicker = {
38
+ type: 'resourceLocator',
39
+ default: { mode: 'number', value: '' },
40
+ typeOptions: { loadOptionsDependsOn: ['templateId'] },
41
+ modes: [
42
+ {
43
+ displayName: 'From List',
44
+ name: 'list',
45
+ type: 'list',
46
+ typeOptions: { searchListMethod: 'searchVersions' },
47
+ },
48
+ {
49
+ displayName: 'By Number',
50
+ name: 'number',
51
+ type: 'string',
52
+ placeholder: '1',
53
+ },
54
+ ],
55
+ };
56
+ const templateNameOrder = new Intl.Collator('en', { numeric: true, sensitivity: 'base' });
57
+ exports.bitavuListSearch = {
58
+ async searchVersions(_filter, paginationToken) {
59
+ const templateId = locatorValue(this.getCurrentNodeParameter('templateId'));
60
+ if (typeof templateId !== 'string' || !validTemplateId.test(templateId.trim())) {
61
+ throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Select a template to list its saved versions.');
62
+ }
63
+ const page = paginationToken === undefined ? 1 : Number(paginationToken);
64
+ if (!Number.isSafeInteger(page) || page < 1 || page > 10000) {
65
+ throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Invalid template version page.');
66
+ }
67
+ const response = await (0, BitavuApi_1.requestBitavu)(this, undefined, {
68
+ path: `/v1/templates/${templateId.trim()}/versions?summary=true&page=${page}&pageSize=50`,
69
+ permission: 'Read templates',
70
+ });
71
+ const value = (0, BitavuApi_1.hasMediaType)(response, 'application/json') ? (0, BitavuApi_1.parseJson)(response.body) : undefined;
72
+ if (!(0, BitavuApi_1.isVersionPage)(value)) {
73
+ throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Bitavu returned an unexpected version list.');
74
+ }
75
+ return {
76
+ results: [...value.versions]
77
+ .sort((a, b) => b.revision - a.revision)
78
+ .map(({ revision, title }) => {
79
+ const publication = revision === value.publishedRevision ? ' (Published)' : '';
80
+ return {
81
+ name: `Version ${revision}${publication}${title ? ` - ${title}` : ''}`,
82
+ value: String(revision),
83
+ };
84
+ }),
85
+ ...(value.page < value.pages ? { paginationToken: String(value.page + 1) } : {}),
86
+ };
87
+ },
88
+ async searchTemplates(filter = '') {
89
+ const response = await (0, BitavuApi_1.requestBitavu)(this, undefined, {
90
+ path: '/v1/templates',
91
+ permission: 'Read templates',
92
+ });
93
+ const value = (0, BitavuApi_1.hasMediaType)(response, 'application/json') ? (0, BitavuApi_1.parseJson)(response.body) : undefined;
94
+ if (!(0, BitavuApi_1.isCatalog)(value)) {
95
+ throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Bitavu returned an unexpected template list.');
96
+ }
97
+ const search = filter.trim().toLowerCase();
98
+ return {
99
+ results: value.templates
100
+ .filter((entry) => [entry.id, entry.name, ...entry.path].some((label) => label.toLowerCase().includes(search)))
101
+ .map((entry) => ({
102
+ name: entry.path.join(' / ') || entry.name,
103
+ value: entry.id,
104
+ }))
105
+ .sort((a, b) => templateNameOrder.compare(a.name, b.name) || a.value.localeCompare(b.value, 'en')),
106
+ };
107
+ },
108
+ };
109
+ async function executeBitavu(operation) {
110
+ var _a, _b;
111
+ const items = this.getInputData();
112
+ const output = [];
113
+ for (let itemIndex = 0; itemIndex < items.length; itemIndex++) {
114
+ try {
115
+ const invalid = (message) => {
116
+ throw new n8n_workflow_1.NodeOperationError(this.getNode(), message, { itemIndex });
117
+ };
118
+ const result = operation === 'generate'
119
+ ? await generatePdf(this, itemIndex, invalid)
120
+ : { bitavu: await runTemplateOperation(this, itemIndex, operation, invalid) };
121
+ const item = items[itemIndex];
122
+ const binary = result.binary ? { ...item.binary, ...result.binary } : item.binary;
123
+ output.push({
124
+ json: { ...item.json, bitavu: result.bitavu },
125
+ ...(binary ? { binary } : {}),
126
+ pairedItem: { item: itemIndex },
127
+ });
128
+ }
129
+ catch (error) {
130
+ const knownError = error instanceof n8n_workflow_1.NodeApiError || error instanceof n8n_workflow_1.NodeOperationError;
131
+ const message = knownError
132
+ ? error.message
133
+ : 'The Bitavu operation failed. Check the node configuration.';
134
+ if (!this.continueOnFail()) {
135
+ if (error instanceof n8n_workflow_1.NodeApiError) {
136
+ const apiError = new n8n_workflow_1.NodeApiError(this.getNode(), { message }, {
137
+ message,
138
+ description: (_a = error.description) !== null && _a !== void 0 ? _a : undefined,
139
+ httpCode: (_b = error.httpCode) !== null && _b !== void 0 ? _b : undefined,
140
+ itemIndex,
141
+ });
142
+ apiError.context.bitavu = error.context.bitavu;
143
+ throw apiError;
144
+ }
145
+ throw new n8n_workflow_1.NodeOperationError(this.getNode(), message, { itemIndex });
146
+ }
147
+ output.push({
148
+ json: {
149
+ error: message,
150
+ ...(error instanceof n8n_workflow_1.NodeApiError ? { bitavu: error.context.bitavu } : {}),
151
+ },
152
+ pairedItem: { item: itemIndex },
153
+ });
154
+ }
155
+ }
156
+ return [output];
157
+ }
158
+ const validTemplateId = /^[A-Za-z0-9_-]{1,80}$/;
159
+ function locatorValue(parameter) {
160
+ return (0, BitavuApi_1.isRecord)(parameter) && parameter.__rl === true ? parameter.value : parameter;
161
+ }
162
+ function versionValue(parameter) {
163
+ const raw = locatorValue(parameter);
164
+ if (typeof raw !== 'string')
165
+ return raw;
166
+ const value = raw.trim();
167
+ if (!value)
168
+ return null;
169
+ return /^\d+$/.test(value) ? Number(value) : value;
170
+ }
171
+ function templateIdParameter(context, itemIndex, invalid) {
172
+ const value = locatorValue(context.getNodeParameter('templateId', itemIndex));
173
+ const id = typeof value === 'string' ? value.trim() : '';
174
+ if (!validTemplateId.test(id))
175
+ invalid('Enter a valid Template ID from Bitavu Integrations.');
176
+ return id;
177
+ }
178
+ function integer(value, name, invalid, maximum = Number.MAX_SAFE_INTEGER) {
179
+ if (typeof value !== 'number' || !Number.isSafeInteger(value) || value < 1 || value > maximum) {
180
+ return invalid(maximum === Number.MAX_SAFE_INTEGER
181
+ ? `${name} must be a positive integer.`
182
+ : `${name} must be an integer from 1 to ${maximum}.`);
183
+ }
184
+ return value;
185
+ }
186
+ function jsonObject(raw, name, invalid) {
187
+ const value = typeof raw === 'string' ? (0, BitavuApi_1.parseJson)(raw) : raw;
188
+ if (!(0, BitavuApi_1.isRecord)(value))
189
+ invalid(`${name} must be a valid JSON object.`);
190
+ let serialized;
191
+ try {
192
+ serialized = (0, BitavuApi_1.parseJson)(JSON.stringify(value));
193
+ }
194
+ catch {
195
+ }
196
+ if (!(0, BitavuApi_1.isRecord)(serialized))
197
+ return invalid(`${name} must be serializable as a JSON object.`);
198
+ return serialized;
199
+ }
200
+ async function generatePdf(context, itemIndex, invalid) {
201
+ var _a;
202
+ const templateId = templateIdParameter(context, itemIndex, invalid);
203
+ const selection = context.getNodeParameter('versionSelection', itemIndex, 'pinned');
204
+ if (selection !== 'pinned' && selection !== 'latest-published')
205
+ invalid('Choose Pinned or Latest Published for Version Selection.');
206
+ const options = context.getNodeParameter('options', itemIndex, {});
207
+ const selectedVersion = versionValue(context.getNodeParameter('revision', itemIndex, null));
208
+ const revision = selection === 'latest-published'
209
+ ? selection
210
+ : integer(selectedVersion !== null && selectedVersion !== void 0 ? selectedVersion : 1, 'Pinned Version', invalid);
211
+ const data = jsonObject(context.getNodeParameter('data', itemIndex), 'Document Data', invalid);
212
+ const body = { templateId, revision, data };
213
+ const baseVersion = selectedVersion !== null && selectedVersion !== void 0 ? selectedVersion : options.baseRevision;
214
+ if (selection === 'latest-published' && baseVersion != null) {
215
+ body.baseRevision = integer(baseVersion, 'Base Version', invalid);
216
+ }
217
+ if (options.mappingId !== undefined && options.mappingId !== '') {
218
+ const mappingId = options.mappingId;
219
+ if (typeof mappingId !== 'string' || !mappingId.trim())
220
+ return invalid('Mapping ID must be a non-empty string.');
221
+ body.mappingId = mappingId.trim();
222
+ }
223
+ const outputField = String(options.outputField || 'pdf');
224
+ if (!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(outputField) ||
225
+ ['__proto__', 'constructor', 'prototype'].includes(outputField))
226
+ invalid('Output Binary Field must be a simple field name, such as pdf.');
227
+ const fileName = String(options.fileName || `${templateId}.pdf`).trim();
228
+ if (!fileName ||
229
+ /[/\\]/.test(fileName) ||
230
+ [...fileName].some((char) => char.charCodeAt(0) < 32 || char.charCodeAt(0) === 127) ||
231
+ !fileName.toLowerCase().endsWith('.pdf'))
232
+ invalid('File Name must end in .pdf and contain no path separators or control characters.');
233
+ const operationId = String(options.operationId ||
234
+ `bitavu-${(0, node_crypto_1.createHash)('sha256')
235
+ .update(JSON.stringify([
236
+ context.getExecutionId(),
237
+ context.getNode().id,
238
+ context.evaluateExpression('{{ $runIndex }}', itemIndex),
239
+ itemIndex,
240
+ ]))
241
+ .digest('hex')}`);
242
+ if (!/^[a-zA-Z0-9_-]{16,128}$/.test(operationId))
243
+ invalid('Operation ID must contain 16–128 letters, digits, underscores or hyphens.');
244
+ const response = await (0, BitavuApi_1.requestBitavu)(context, itemIndex, {
245
+ path: '/v1/render',
246
+ permission: 'Generate PDFs',
247
+ body,
248
+ idempotencyKey: operationId,
249
+ });
250
+ if (response.statusCode !== 200 ||
251
+ !(0, BitavuApi_1.hasMediaType)(response, 'application/pdf') ||
252
+ !response.body.subarray(0, 5).equals(Buffer.from('%PDF-')))
253
+ invalid('Bitavu returned an unexpected response instead of a PDF.');
254
+ const binary = await context.helpers.prepareBinaryData(response.body, fileName, 'application/pdf');
255
+ return {
256
+ bitavu: {
257
+ templateId,
258
+ revision: (_a = (0, BitavuApi_1.readPositiveHeader)(response, 'x-bitavu-revision')) !== null && _a !== void 0 ? _a : (typeof revision === 'number' ? revision : null),
259
+ requestedRevision: revision,
260
+ pageCount: (0, BitavuApi_1.readPositiveHeader)(response, 'x-bitavu-pages'),
261
+ requestId: (0, BitavuApi_1.readRequestId)(response),
262
+ operationId,
263
+ fileName,
264
+ outputField,
265
+ },
266
+ binary: { [outputField]: binary },
267
+ };
268
+ }
269
+ async function runTemplateOperation(context, itemIndex, operation, invalid) {
270
+ var _a, _b;
271
+ let path = '/v1/templates';
272
+ let body;
273
+ let validate = BitavuApi_1.isCatalog;
274
+ if (operation !== 'listTemplates') {
275
+ path += '/' + templateIdParameter(context, itemIndex, invalid);
276
+ switch (operation) {
277
+ case 'getTemplate': {
278
+ const revision = integer(versionValue(context.getNodeParameter('templateRevision', itemIndex)), 'Version to Read', invalid);
279
+ path += '?revision=' + revision;
280
+ validate = BitavuApi_1.isTemplateRevision;
281
+ break;
282
+ }
283
+ case 'listVersions': {
284
+ const options = context.getNodeParameter('versionOptions', itemIndex, {});
285
+ const page = integer((_a = options.page) !== null && _a !== void 0 ? _a : 1, 'Page', invalid, 10000);
286
+ const pageSize = integer((_b = options.pageSize) !== null && _b !== void 0 ? _b : 10, 'Page Size', invalid, 50);
287
+ const query = new URLSearchParams({
288
+ summary: 'true',
289
+ page: String(page),
290
+ pageSize: String(pageSize),
291
+ });
292
+ if (options.selectedRevision !== undefined) {
293
+ query.set('revision', String(integer(options.selectedRevision, 'Selected Version', invalid)));
294
+ }
295
+ path += '/versions?' + query;
296
+ break;
297
+ }
298
+ case 'saveExample':
299
+ path += '/example';
300
+ body = {
301
+ expectedRevision: integer(context.getNodeParameter('expectedRevision', itemIndex), 'Expected Version', invalid, Number.MAX_SAFE_INTEGER - 1),
302
+ exampleJson: jsonObject(context.getNodeParameter('exampleJson', itemIndex), 'Example JSON', invalid),
303
+ };
304
+ validate = BitavuApi_1.isTemplateRevision;
305
+ break;
306
+ }
307
+ }
308
+ const response = await (0, BitavuApi_1.requestBitavu)(context, itemIndex, {
309
+ path,
310
+ permission: body === undefined ? 'Read templates' : 'Save template examples',
311
+ body,
312
+ });
313
+ const value = (0, BitavuApi_1.hasMediaType)(response, 'application/json') ? (0, BitavuApi_1.parseJson)(response.body) : undefined;
314
+ if (operation === 'listVersions') {
315
+ if (!(0, BitavuApi_1.isVersionPage)(value))
316
+ invalid('Bitavu returned an unexpected template response.');
317
+ if (value.publishedRevision === undefined)
318
+ return value;
319
+ return {
320
+ ...value,
321
+ versions: value.versions.map((version) => ({
322
+ ...version,
323
+ published: version.revision === value.publishedRevision,
324
+ })),
325
+ };
326
+ }
327
+ if (!validate(value))
328
+ invalid('Bitavu returned an unexpected template response.');
329
+ return value;
330
+ }
331
+ //# sourceMappingURL=BitavuAction.js.map
@@ -0,0 +1,187 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.requestBitavu = requestBitavu;
4
+ exports.hasMediaType = hasMediaType;
5
+ exports.readPositiveHeader = readPositiveHeader;
6
+ exports.readRequestId = readRequestId;
7
+ exports.parseJson = parseJson;
8
+ exports.isRecord = isRecord;
9
+ exports.isCatalog = isCatalog;
10
+ exports.isVersionPage = isVersionPage;
11
+ exports.isTemplateRevision = isTemplateRevision;
12
+ const n8n_workflow_1 = require("n8n-workflow");
13
+ const origin = 'https://api.bitavu.com';
14
+ const messages = {
15
+ INVALID_API_KEY: 'Your API key is invalid, expired or revoked. Check your Bitavu credential.',
16
+ KEY_REPORT: 'This key cannot access the template. Grant it access in Bitavu Integrations.',
17
+ NOT_PUBLISHED: 'Publish a saved version in Bitavu Studio before using Latest Published.',
18
+ JSON_COMPATIBILITY: 'The published version is incompatible with your base version or saved mapping. Review the JSON contract in Studio or pin a tested version.',
19
+ TEMPLATE_REVISION_CONFLICT: 'The template changed. Get the latest saved version and check its bindings before saving the example again.',
20
+ IDEMPOTENCY_CONFLICT: 'This operation ID was already used with different input. Use a new ID for a new document.',
21
+ API_VERSION_LIMIT: 'This template reached its rolling saved-version limit. Use a previously rendered version or wait for the limit to reset.',
22
+ };
23
+ async function requestBitavu(context, itemIndex, { path, permission, body, idempotencyKey }) {
24
+ var _a, _b;
25
+ const headers = {
26
+ Accept: permission === 'Generate PDFs' ? 'application/pdf' : 'application/json',
27
+ };
28
+ const request = {
29
+ method: body === undefined ? 'GET' : 'POST',
30
+ url: origin + path,
31
+ headers,
32
+ encoding: 'arraybuffer',
33
+ returnFullResponse: true,
34
+ ignoreHttpStatusErrors: true,
35
+ disableFollowRedirect: true,
36
+ timeout: 120000,
37
+ };
38
+ if (body !== undefined) {
39
+ headers['Content-Type'] = 'application/json';
40
+ request.body = JSON.stringify(body);
41
+ }
42
+ if (idempotencyKey !== undefined)
43
+ headers['Idempotency-Key'] = idempotencyKey;
44
+ let response;
45
+ try {
46
+ response = await context.helpers.httpRequestWithAuthentication.call(context, 'bitavuApi', request);
47
+ }
48
+ catch {
49
+ const guidance = {
50
+ 'Generate PDFs': ' Retry with the same operation ID if the result is uncertain.',
51
+ 'Read templates': '',
52
+ 'Save template examples': ' Check the latest saved version before retrying the save.',
53
+ }[permission];
54
+ throw new n8n_workflow_1.NodeOperationError(context.getNode(), 'Could not complete the Bitavu request. Check your credential and network connection.' +
55
+ guidance, { itemIndex });
56
+ }
57
+ const result = {
58
+ body: Buffer.isBuffer(response.body) ? response.body : Buffer.from((_a = response.body) !== null && _a !== void 0 ? _a : ''),
59
+ headers: (_b = response.headers) !== null && _b !== void 0 ? _b : {},
60
+ statusCode: response.statusCode,
61
+ };
62
+ if (result.statusCode < 200 || result.statusCode >= 300) {
63
+ throw apiError(context, itemIndex, result, permission);
64
+ }
65
+ return result;
66
+ }
67
+ function apiError(context, itemIndex, response, permission) {
68
+ const status = response.statusCode;
69
+ const payload = response.body.length <= 65536 && hasMediaType(response, 'application/json')
70
+ ? parseJson(response.body)
71
+ : undefined;
72
+ const value = isRecord(payload) ? payload.code : undefined;
73
+ const code = typeof value === 'string' &&
74
+ (value === 'KEY_SCOPE' || Object.prototype.hasOwnProperty.call(messages, value))
75
+ ? value
76
+ : null;
77
+ const fallback = {
78
+ 400: 'Check your Bitavu node settings and input against the template.',
79
+ 401: messages.INVALID_API_KEY,
80
+ 402: 'The workspace cannot complete this request. Check your Bitavu subscription.',
81
+ 403: `Check the key’s ${permission} permission and template access in Bitavu Integrations.`,
82
+ 404: 'Check the Template ID, version and saved mapping in Bitavu Studio.',
83
+ 409: 'Bitavu reported a conflict. Check the template version and input before retrying.',
84
+ 422: 'Check the JSON fields and saved mapping against the Bitavu template.',
85
+ 429: 'Bitavu is limiting requests or your render allowance is exhausted.',
86
+ };
87
+ const message = code === 'KEY_SCOPE'
88
+ ? `Enable ${permission} permission for this key in Bitavu Integrations.`
89
+ : (code && messages[code]) || fallback[status] || 'Bitavu could not complete the request.';
90
+ const requestId = readRequestId(response);
91
+ const retryAfter = readHeader(response, 'retry-after');
92
+ const delay = /^\d+$/.test(retryAfter)
93
+ ? Number(retryAfter) * 1000
94
+ : Math.max(0, Date.parse(retryAfter) - Date.now());
95
+ const retryAfterMs = Number.isSafeInteger(delay) ? delay : null;
96
+ const description = [
97
+ `Bitavu returned HTTP ${status}${code ? ` (${code})` : ''}.`,
98
+ ...(requestId === null ? [] : [`Request ID ${requestId}.`]),
99
+ ...(retryAfterMs === null
100
+ ? []
101
+ : [`Wait at least ${Math.ceil(retryAfterMs / 1000)} seconds before retrying.`]),
102
+ ].join(' ');
103
+ const error = new n8n_workflow_1.NodeApiError(context.getNode(), { message }, { message, description, httpCode: String(status), itemIndex });
104
+ error.context.bitavu = { status, code, requestId, retryAfterMs };
105
+ return error;
106
+ }
107
+ function readHeader(response, name) {
108
+ const entry = Object.entries(response.headers).find(([key]) => key.toLowerCase() === name);
109
+ return typeof (entry === null || entry === void 0 ? void 0 : entry[1]) === 'string' ? entry[1].trim() : '';
110
+ }
111
+ function hasMediaType(response, type) {
112
+ return readHeader(response, 'content-type').split(';', 1)[0].trim().toLowerCase() === type;
113
+ }
114
+ function readPositiveHeader(response, name) {
115
+ const value = readHeader(response, name);
116
+ const number = Number(value);
117
+ return /^\d+$/.test(value) && isInteger(number, 1) ? number : null;
118
+ }
119
+ function readRequestId(response) {
120
+ const id = readHeader(response, 'x-bitavu-request-id');
121
+ return /^[\da-f]{8}(?:-[\da-f]{4}){3}-[\da-f]{12}$/i.test(id) ? id : null;
122
+ }
123
+ function parseJson(value) {
124
+ try {
125
+ return JSON.parse(value.toString());
126
+ }
127
+ catch {
128
+ return undefined;
129
+ }
130
+ }
131
+ function isRecord(value) {
132
+ return value !== null && typeof value === 'object' && !Array.isArray(value);
133
+ }
134
+ function isInteger(value, minimum) {
135
+ return typeof value === 'number' && Number.isSafeInteger(value) && value >= minimum;
136
+ }
137
+ function isStringList(value) {
138
+ return Array.isArray(value) && value.every((entry) => typeof entry === 'string');
139
+ }
140
+ function isRevisionSummary(value) {
141
+ return (isRecord(value) &&
142
+ typeof value.id === 'string' &&
143
+ typeof value.name === 'string' &&
144
+ typeof value.studioUrl === 'string' &&
145
+ isInteger(value.revision, 1) &&
146
+ (value.createdAt === null || isInteger(value.createdAt, 0)) &&
147
+ (value.updatedAt === null || isInteger(value.updatedAt, 0)));
148
+ }
149
+ function isInputPath(value) {
150
+ return isRecord(value) && typeof value.path === 'string' && typeof value.required === 'boolean';
151
+ }
152
+ function isCatalog(value) {
153
+ return (isRecord(value) &&
154
+ Array.isArray(value.templates) &&
155
+ value.templates.every((entry) => isRecord(entry) &&
156
+ typeof entry.id === 'string' &&
157
+ typeof entry.name === 'string' &&
158
+ typeof entry.studioUrl === 'string' &&
159
+ isStringList(entry.path) &&
160
+ isInteger(entry.latestRevision, 1)));
161
+ }
162
+ function isVersionPage(value) {
163
+ return (isRecord(value) &&
164
+ Array.isArray(value.versions) &&
165
+ value.versions.every((entry) => isRevisionSummary(entry) && (entry.title === null || typeof entry.title === 'string')) &&
166
+ isRevisionSummary(value.latest) &&
167
+ (value.publishedRevision == null || isInteger(value.publishedRevision, 1)) &&
168
+ (value.selected === null || isRevisionSummary(value.selected)) &&
169
+ isInteger(value.page, 1) &&
170
+ isInteger(value.pageSize, 1) &&
171
+ isInteger(value.total, 0) &&
172
+ isInteger(value.pages, 0));
173
+ }
174
+ function isTemplateRevision(value) {
175
+ if (!isRevisionSummary(value))
176
+ return false;
177
+ const review = value.inputReview;
178
+ return (Array.isArray(value.bindings) &&
179
+ value.bindings.every((entry) => isInputPath(entry) && typeof entry.type === 'string') &&
180
+ (value.exampleJson === null || isRecord(value.exampleJson)) &&
181
+ (review === null ||
182
+ (isRecord(review) &&
183
+ Array.isArray(review.missing) &&
184
+ review.missing.every(isInputPath) &&
185
+ isStringList(review.unused))));
186
+ }
187
+ //# sourceMappingURL=BitavuApi.js.map
@@ -0,0 +1,35 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.BitavuGetTemplateVersion = void 0;
4
+ const BitavuAction_1 = require("../Bitavu/BitavuAction");
5
+ class BitavuGetTemplateVersion {
6
+ constructor() {
7
+ this.description = {
8
+ ...BitavuAction_1.bitavuNodeDefaults,
9
+ displayName: 'Get Template Version',
10
+ icon: { light: 'file:../Bitavu/bitavu.svg', dark: 'file:../Bitavu/bitavu.svg' },
11
+ usableAsTool: undefined,
12
+ subtitle: '',
13
+ name: 'bitavuGetTemplateVersion',
14
+ description: 'Read a saved Bitavu template version, its bindings, and example JSON',
15
+ defaults: { name: 'Get Template Version' },
16
+ properties: [
17
+ BitavuAction_1.templatePicker,
18
+ {
19
+ ...BitavuAction_1.versionPicker,
20
+ displayName: 'Version to Read',
21
+ name: 'templateRevision',
22
+ default: { mode: 'number', value: '1' },
23
+ required: true,
24
+ description: 'The saved version to read',
25
+ },
26
+ ],
27
+ };
28
+ this.methods = { listSearch: BitavuAction_1.bitavuListSearch };
29
+ }
30
+ async execute() {
31
+ return await BitavuAction_1.executeBitavu.call(this, 'getTemplate');
32
+ }
33
+ }
34
+ exports.BitavuGetTemplateVersion = BitavuGetTemplateVersion;
35
+ //# sourceMappingURL=BitavuGetTemplateVersion.node.js.map
@@ -0,0 +1,17 @@
1
+ {
2
+ "node": "@bitavu/n8n-nodes-bitavu.bitavuGetTemplateVersion",
3
+ "nodeVersion": "1.0",
4
+ "codexVersion": "1.0",
5
+ "alias": ["Bitavu"],
6
+ "categories": [
7
+ "Productivity",
8
+ "Utility"
9
+ ],
10
+ "resources": {
11
+ "primaryDocumentation": [
12
+ {
13
+ "url": "https://bitavu.com/support/n8n"
14
+ }
15
+ ]
16
+ }
17
+ }
@@ -0,0 +1,60 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.BitavuListTemplateVersions = void 0;
4
+ const BitavuAction_1 = require("../Bitavu/BitavuAction");
5
+ class BitavuListTemplateVersions {
6
+ constructor() {
7
+ this.description = {
8
+ ...BitavuAction_1.bitavuNodeDefaults,
9
+ displayName: 'List Template Versions',
10
+ icon: { light: 'file:../Bitavu/bitavu.svg', dark: 'file:../Bitavu/bitavu.svg' },
11
+ usableAsTool: undefined,
12
+ subtitle: '',
13
+ name: 'bitavuListTemplateVersions',
14
+ description: 'List saved versions of a Bitavu template and identify the current publication',
15
+ defaults: { name: 'List Template Versions' },
16
+ properties: [
17
+ BitavuAction_1.templatePicker,
18
+ {
19
+ displayName: 'Options',
20
+ name: 'versionOptions',
21
+ type: 'collection',
22
+ placeholder: 'Add Option',
23
+ default: {},
24
+ options: [
25
+ {
26
+ displayName: 'Page',
27
+ name: 'page',
28
+ type: 'number',
29
+ default: 1,
30
+ typeOptions: { minValue: 1, maxValue: 10000, numberPrecision: 0 },
31
+ description: 'The page of saved versions, starting at 1',
32
+ },
33
+ {
34
+ displayName: 'Page Size',
35
+ name: 'pageSize',
36
+ type: 'number',
37
+ default: 10,
38
+ typeOptions: { minValue: 1, maxValue: 50, numberPrecision: 0 },
39
+ description: 'How many versions to return per page',
40
+ },
41
+ {
42
+ displayName: 'Selected Version',
43
+ name: 'selectedRevision',
44
+ type: 'number',
45
+ default: 1,
46
+ typeOptions: { minValue: 1, numberPrecision: 0 },
47
+ description: 'Include this version’s summary even if it is on a different page',
48
+ },
49
+ ],
50
+ },
51
+ ],
52
+ };
53
+ this.methods = { listSearch: { searchTemplates: BitavuAction_1.bitavuListSearch.searchTemplates } };
54
+ }
55
+ async execute() {
56
+ return await BitavuAction_1.executeBitavu.call(this, 'listVersions');
57
+ }
58
+ }
59
+ exports.BitavuListTemplateVersions = BitavuListTemplateVersions;
60
+ //# sourceMappingURL=BitavuListTemplateVersions.node.js.map
@@ -0,0 +1,17 @@
1
+ {
2
+ "node": "@bitavu/n8n-nodes-bitavu.bitavuListTemplateVersions",
3
+ "nodeVersion": "1.0",
4
+ "codexVersion": "1.0",
5
+ "alias": ["Bitavu"],
6
+ "categories": [
7
+ "Productivity",
8
+ "Utility"
9
+ ],
10
+ "resources": {
11
+ "primaryDocumentation": [
12
+ {
13
+ "url": "https://bitavu.com/support/n8n"
14
+ }
15
+ ]
16
+ }
17
+ }
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.BitavuListTemplates = void 0;
4
+ const BitavuAction_1 = require("../Bitavu/BitavuAction");
5
+ class BitavuListTemplates {
6
+ constructor() {
7
+ this.description = {
8
+ ...BitavuAction_1.bitavuNodeDefaults,
9
+ displayName: 'List Templates',
10
+ icon: { light: 'file:../Bitavu/bitavu.svg', dark: 'file:../Bitavu/bitavu.svg' },
11
+ usableAsTool: undefined,
12
+ subtitle: '',
13
+ name: 'bitavuListTemplates',
14
+ description: 'List the Bitavu templates accessible to your API key',
15
+ defaults: { name: 'List Templates' },
16
+ properties: [],
17
+ };
18
+ }
19
+ async execute() {
20
+ return await BitavuAction_1.executeBitavu.call(this, 'listTemplates');
21
+ }
22
+ }
23
+ exports.BitavuListTemplates = BitavuListTemplates;
24
+ //# sourceMappingURL=BitavuListTemplates.node.js.map