@revoengine/sdk 1.0.0

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 ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 RevoEngine
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 ADDED
@@ -0,0 +1,639 @@
1
+ # @revoengine/sdk
2
+
3
+ Official Node.js SDK for RevoEngine. It provides the modern `api`, `utils`,
4
+ `storage`, and `agents` namespaces plus the `batch` controller in both
5
+ Revo-hosted `CUSTOM_NODEJS` components and standalone Node.js applications.
6
+
7
+ Requirements: Node.js 22 or newer.
8
+
9
+ ## Choose your runtime
10
+
11
+ | Environment | How to start | Authentication |
12
+ | --- | --- | --- |
13
+ | Revo-hosted `CUSTOM_NODEJS` | Export `async function init(runtime)` | Revo injects an execution-bound runtime; user code receives no API key. |
14
+ | Standalone Node.js | Create `new RevoClient(options)` | Supply a RevoEngine API key explicitly or through an environment variable. |
15
+
16
+ Both modes expose the same `api`, `utils`, `storage`, `agents`, and `batch`
17
+ properties, but return types reflect where the work happens:
18
+
19
+ | Call kind | Revo-hosted | Standalone |
20
+ | --- | --- | --- |
21
+ | Execution snapshot, cache, debug, and logging | Synchronous | Throws synchronously because no execution context exists |
22
+ | Current user and instance | Synchronous injected snapshot | Asynchronous lazy `/api/v1/me` discovery |
23
+ | Remote `api`, `storage`, and `agents` calls | Asynchronous | Asynchronous |
24
+ | Local `utils` and `batch.configure()` | Synchronous unless the utility is inherently asynchronous | Same |
25
+
26
+ ## Installation
27
+
28
+ Standalone applications install the SDK normally:
29
+
30
+ ```sh
31
+ npm install @revoengine/sdk
32
+ ```
33
+
34
+ New Revo-hosted components receive `@revoengine/sdk: "1.0.0"` and a JSDoc
35
+ `RevoRuntime` type import in their generated starter files.
36
+ RevoEngine pins that version again in the deployment package and injects the
37
+ runtime into the component entrypoint. Component code does not construct a
38
+ `RevoClient`.
39
+
40
+ The relevant generated `package.json` fields are:
41
+
42
+ ```json
43
+ {
44
+ "type": "module",
45
+ "dependencies": {
46
+ "@revoengine/sdk": "1.0.0"
47
+ }
48
+ }
49
+ ```
50
+
51
+ Hosted user code receives neither a tenant API key nor the private runtime
52
+ credential and does not perform `/api/v1/me` discovery. The generated parent
53
+ worker owns the short-lived, execution-bound bridge. The
54
+ `@revoengine/sdk/hosted` entrypoint is platform-internal and must not be
55
+ imported by a component.
56
+
57
+ ## Revo-hosted CUSTOM_NODEJS
58
+
59
+ ### Basic entrypoint
60
+
61
+ Export a named `init` function. Do not construct `RevoClient` and do not call a
62
+ separate initialization method.
63
+
64
+ ```js
65
+ /** @param {import('@revoengine/sdk').RevoRuntime} runtime */
66
+ export async function init(runtime) {
67
+ const { api, utils, storage, agents, batch } = runtime;
68
+ const { data: rows, next } = await api.getDatabaseData('Sales', {
69
+ fields: ['saleId', 'customerId', 'total', 'createdAt'],
70
+ sort: ['-createdAt'],
71
+ take: 25,
72
+ });
73
+
74
+ const file = await storage.putObject({
75
+ name: `sales-${utils.randomUUID()}.json`,
76
+ data: JSON.stringify({ rows, next }),
77
+ mimeType: 'application/json',
78
+ });
79
+
80
+ return {
81
+ storageEntryId: file.storageEntryId,
82
+ exportedRows: rows.length,
83
+ hasNextPage: next,
84
+ };
85
+ }
86
+ ```
87
+
88
+ `putObject()` is appropriate here because this is a deliberately small JSON
89
+ payload. Use an upload session for larger exports, as shown below.
90
+
91
+ Existing components that export `async function init()` remain compatible;
92
+ JavaScript ignores the additional runtime argument.
93
+
94
+ ### Input, context, and secrets
95
+
96
+ Hosted context comes from the current execution snapshot and is synchronous, just
97
+ like the low-code surface. Only platform-backed work returns a promise.
98
+
99
+ ```js
100
+ export async function init(runtime) {
101
+ const { api } = runtime;
102
+ const input = api.input();
103
+ const currentUser = api.currentUser();
104
+ const instance = api.getInstanceDetails();
105
+ const signingSecret = await api.getSecret('WEBHOOK_SIGNING_SECRET');
106
+
107
+ api.log({
108
+ message: 'Processing custom component',
109
+ args: {
110
+ userId: currentUser.userId,
111
+ instanceId: instance.id,
112
+ hasInput: input != null,
113
+ },
114
+ });
115
+
116
+ // Use the secret without returning or logging its value.
117
+ return { accepted: Boolean(signingSecret) };
118
+ }
119
+ ```
120
+
121
+ Execution-only methods such as `api.input()`, `api.getContext()`,
122
+ `api.getExecutionId()`, and `api.getOperationId()` are available only in hosted
123
+ executions.
124
+
125
+ ### Configure hosted batching
126
+
127
+ Configure batching before the first remote call:
128
+
129
+ ```js
130
+ export async function init(runtime) {
131
+ runtime.batch.configure({
132
+ failureMode: 'stop',
133
+ maxCalls: 16,
134
+ maxInFlight: 2,
135
+ });
136
+
137
+ const [customers, agents] = await Promise.all([
138
+ runtime.api.getDatabaseData('Customers', { take: 100 }),
139
+ runtime.agents.list(),
140
+ ]);
141
+
142
+ return {
143
+ customers: customers.data,
144
+ agents,
145
+ };
146
+ }
147
+ ```
148
+
149
+ `batch.configure()` is synchronous and rejects changes after the first remote
150
+ batch has been dispatched.
151
+
152
+ ## Standalone Node.js
153
+
154
+ ### Basic client
155
+
156
+ Constructing `RevoClient` is synchronous and performs no network I/O. The first
157
+ platform-backed call validates the API key through `/api/v1/me`, reads the
158
+ instance bound to that key, discovers its Sandbox endpoint, and dispatches the
159
+ queued runtime batch.
160
+
161
+ ```ts
162
+ import { RevoClient } from '@revoengine/sdk';
163
+
164
+ const apiKey = process.env.REVO_API_KEY;
165
+ if (!apiKey) throw new Error('REVO_API_KEY is required.');
166
+
167
+ const revo = new RevoClient({
168
+ apiKey,
169
+ });
170
+
171
+ type Sale = {
172
+ saleId: string;
173
+ customerId: string;
174
+ total: number;
175
+ createdAt: string;
176
+ };
177
+
178
+ const result = await revo.api.getDatabaseData<Sale>('Sales', {
179
+ filter: { field: 'total', op: 'gte', value: 100 },
180
+ sort: ['-createdAt'],
181
+ take: 100,
182
+ });
183
+
184
+ console.log(result.data);
185
+ ```
186
+
187
+ There is no `init()` or connection method.
188
+
189
+ ### Environment configuration
190
+
191
+ ```ts
192
+ const revo = new RevoClient();
193
+ ```
194
+
195
+ Supported environment aliases, in precedence order after explicit constructor
196
+ options:
197
+
198
+ - URL: `REVO_URL`, `REVO_BASE_URL`, `REVOENGINE_URL`, `REVOENGINE_BASE_URL`
199
+ - API key: `REVO_TOKEN`, `REVO_API_KEY`, `REVOENGINE_TOKEN`, `REVOENGINE_API_KEY`
200
+
201
+ The default API URL is `https://api.revoengine.com`. The API key already
202
+ identifies its instance, so `RevoClient` has no instance option and sends no
203
+ separate instance header. `/api/v1/me` is the sole source of the bound instance
204
+ identity and Sandbox endpoint.
205
+
206
+ Keep the API key in a server-side secret or environment variable. This SDK is
207
+ for Node.js processes and must not be bundled into browser code with a key.
208
+
209
+ Explicit options always win:
210
+
211
+ ```ts
212
+ const apiKey = process.env.REVO_API_KEY;
213
+ if (!apiKey) throw new Error('REVO_API_KEY is required.');
214
+
215
+ const revo = new RevoClient({
216
+ baseUrl: 'https://api.revoengine.com',
217
+ apiKey,
218
+ requestTimeoutMs: 30_000,
219
+ batch: {
220
+ failureMode: 'independent',
221
+ maxCalls: 16,
222
+ maxRequestBytes: 128 * 1024,
223
+ maxInFlight: 2,
224
+ maxQueuedCalls: 256,
225
+ },
226
+ });
227
+ ```
228
+
229
+ The SDK never reads or writes Revo CLI credential files.
230
+
231
+ ## Automatic batching
232
+
233
+ Calls queued in the same microtask are grouped. `Promise.all` is the normal way
234
+ to issue a batch:
235
+
236
+ ```ts
237
+ const [customers, crmToken, activeAgents] = await Promise.all([
238
+ revo.api.getDatabaseData('Customers', { take: 100 }),
239
+ revo.api.getSecret('CRM_API_TOKEN'),
240
+ revo.agents.list(),
241
+ ]);
242
+ ```
243
+
244
+ Sequential `await` statements naturally produce separate batches:
245
+
246
+ ```ts
247
+ const customers = await revo.api.getDatabaseData('Customers', { take: 100 });
248
+ const agents = await revo.agents.list();
249
+ ```
250
+
251
+ The default `independent` mode executes every valid call and settles each
252
+ promise independently. In `stop` mode calls execute in order; after one call
253
+ fails, later calls in that batch reject with `BATCH_STOPPED`.
254
+
255
+ ```ts
256
+ const revo = new RevoClient({
257
+ batch: { failureMode: 'stop' },
258
+ });
259
+ ```
260
+
261
+ Defaults are 32 calls per request, 256 KiB per request, four in-flight batches,
262
+ and 1,024 queued calls. Client configuration can only lower server ceilings.
263
+ The complete batch is validated before any call executes.
264
+
265
+ Runtime batches are never retried automatically because they may contain
266
+ mutations. If transport is interrupted after dispatch, unresolved calls reject
267
+ with `RevoTransportError` and `indeterminate: true`.
268
+
269
+ Batching is not a transaction. `api.transactionDatabaseData` is intentionally
270
+ not part of SDK 1.0.0.
271
+
272
+ ## Local utils
273
+
274
+ `utils` runs locally and is available before authentication or discovery:
275
+
276
+ ```ts
277
+ const payload = JSON.stringify({ event: 'customer.updated' });
278
+ const secret = process.env.SIGNING_SECRET;
279
+ if (!secret) throw new Error('SIGNING_SECRET is required.');
280
+
281
+ const requestId = revo.utils.randomUUID();
282
+ const signature = revo.utils.hmac(payload, secret);
283
+ const encoded = revo.utils.encodeBase64('RevoEngine');
284
+ ```
285
+
286
+ Only the modern first-class utility surface is exposed; deprecated low-code
287
+ aliases are not included. `utils.sleep()`, `utils.generateHash()`, and
288
+ `utils.compareHash()` remain asynchronous by design; the other local utilities
289
+ return their values directly.
290
+
291
+ ## Runtime context
292
+
293
+ Hosted context reads are synchronous because the generated worker injects an
294
+ immutable execution snapshot before `init(runtime)`:
295
+
296
+ ```js
297
+ export async function init(runtime) {
298
+ const input = runtime.api.input();
299
+ const currentUser = runtime.api.currentUser();
300
+ const instanceId = runtime.api.getCurrentInstance();
301
+
302
+ runtime.api.log({
303
+ message: 'Started',
304
+ args: { userId: currentUser.userId, instanceId, hasInput: input != null },
305
+ });
306
+
307
+ return runtime.api.getSecret('SIGNING_SECRET');
308
+ }
309
+ ```
310
+
311
+ The three standalone identity methods are asynchronous because their first call
312
+ performs lazy `/api/v1/me` discovery and later calls use the cached profile:
313
+
314
+ ```ts
315
+ const [currentUser, instanceId, instance] = await Promise.all([
316
+ revo.api.currentUser(),
317
+ revo.api.getCurrentInstance(),
318
+ revo.api.getInstanceDetails(),
319
+ ]);
320
+ ```
321
+
322
+ Other context methods throw `RevoRuntimeContextUnavailableError` synchronously
323
+ outside a hosted execution. The distinct `RevoApi` and `RevoStandaloneApi` types
324
+ make the hosted snapshot and standalone discovery behavior explicit.
325
+
326
+ ## Storage
327
+
328
+ ### Small text or binary objects
329
+
330
+ `storage.putObject()` is convenient for small payloads that fit the runtime
331
+ batch limit:
332
+
333
+ ```ts
334
+ const settingsFile = await revo.storage.putObject({
335
+ name: 'settings.json',
336
+ data: JSON.stringify({ locale: 'pl-PL', enabled: true }),
337
+ dataEncoding: 'utf8',
338
+ mimeType: 'application/json',
339
+ });
340
+
341
+ async function uploadSmallPdf(pdfBuffer: Buffer) {
342
+ return revo.storage.putObject({
343
+ name: 'invoice.pdf',
344
+ data: pdfBuffer.toString('base64'),
345
+ dataEncoding: 'base64',
346
+ mimeType: 'application/pdf',
347
+ });
348
+ }
349
+ ```
350
+
351
+ ### Large binary uploads
352
+
353
+ Large files must use an upload session or signed URL so their bytes do not enter
354
+ the JSON runtime batch:
355
+
356
+ ```ts
357
+ import type { RevoRuntime } from '@revoengine/sdk';
358
+
359
+ export async function uploadBinary(
360
+ runtime: Pick<RevoRuntime, 'storage'>,
361
+ name: string,
362
+ contentType: string,
363
+ bytes: Uint8Array,
364
+ ) {
365
+ const { session, upload } = await runtime.storage.createUploadSession({
366
+ name,
367
+ contentTypeHint: contentType,
368
+ sizeHint: bytes.byteLength,
369
+ uploadMode: 'direct',
370
+ });
371
+
372
+ const sessionId = session.storageUploadSessionId;
373
+
374
+ try {
375
+ if (!upload.uploadUrl) {
376
+ throw new Error('RevoEngine did not return a direct upload URL.');
377
+ }
378
+
379
+ const headers = new Headers(upload.headers);
380
+ if (!headers.has('content-type')) {
381
+ headers.set('content-type', contentType);
382
+ }
383
+
384
+ const response = await fetch(upload.uploadUrl, {
385
+ method: upload.method,
386
+ headers,
387
+ body: Buffer.from(bytes),
388
+ });
389
+ if (!response.ok) {
390
+ throw new Error(`Upload failed with HTTP ${response.status}.`);
391
+ }
392
+
393
+ const { entry } = await runtime.storage.finalizeUploadSession(sessionId);
394
+ return entry;
395
+ } catch (error) {
396
+ await runtime.storage.abortUploadSession(sessionId).catch(() => undefined);
397
+ throw error;
398
+ }
399
+ }
400
+ ```
401
+
402
+ The helper accepts either a `RevoClient` or the runtime injected into hosted
403
+ `init(runtime)`. Session creation, finalization, and best-effort abort remain
404
+ runtime calls; only the binary bytes bypass the JSON batch.
405
+
406
+ ## Excel export from database data
407
+
408
+ Install `exceljs` in your standalone application or add it to the hosted
409
+ component's `package.json` dependencies.
410
+
411
+ ```ts
412
+ import ExcelJS from 'exceljs';
413
+ import type { RevoRuntime } from '@revoengine/sdk';
414
+ import { uploadBinary } from './upload-binary.js';
415
+
416
+ type SaleRow = {
417
+ saleId: string;
418
+ customerId: string;
419
+ total: number;
420
+ createdAt: string;
421
+ };
422
+
423
+ type ExportRuntime = Pick<RevoRuntime, 'storage'> & {
424
+ readonly api: Pick<RevoRuntime['api'], 'getDatabaseData'>;
425
+ };
426
+
427
+ export async function exportSales(
428
+ runtime: ExportRuntime,
429
+ ) {
430
+ const workbook = new ExcelJS.Workbook();
431
+ const sheet = workbook.addWorksheet('Sales');
432
+ sheet.columns = [
433
+ { header: 'Sale ID', key: 'saleId' },
434
+ { header: 'Customer', key: 'customerId' },
435
+ { header: 'Total', key: 'total' },
436
+ { header: 'Created at', key: 'createdAt' },
437
+ ];
438
+
439
+ let skip = 0;
440
+ for (;;) {
441
+ const page = await runtime.api.getDatabaseData<SaleRow>('Sales', {
442
+ fields: ['saleId', 'customerId', 'total', 'createdAt'],
443
+ sort: { saleId: 'ASC' },
444
+ take: 1_000,
445
+ skip,
446
+ });
447
+
448
+ sheet.addRows(page.data);
449
+ if (!page.next) break;
450
+ if (page.results === 0) {
451
+ throw new Error('Sales pagination did not advance.');
452
+ }
453
+ skip += page.results;
454
+ }
455
+
456
+ const bytes = Buffer.from(await workbook.xlsx.writeBuffer());
457
+ return uploadBinary(
458
+ runtime,
459
+ 'sales-export.xlsx',
460
+ 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
461
+ bytes,
462
+ );
463
+ }
464
+ ```
465
+
466
+ Standalone call site:
467
+
468
+ ```ts
469
+ import { RevoClient } from '@revoengine/sdk';
470
+ import { exportSales } from './export-sales.js';
471
+
472
+ const revo = new RevoClient();
473
+ const file = await exportSales(revo);
474
+ console.log(file.storageEntryId);
475
+ ```
476
+
477
+ The same exporter can be used in Revo-hosted code:
478
+
479
+ ```js
480
+ import { exportSales } from './export-sales.js';
481
+
482
+ export async function init(runtime) {
483
+ const file = await exportSales(runtime);
484
+ return { storageEntryId: file.storageEntryId };
485
+ }
486
+ ```
487
+
488
+ The stable unique sort makes offset pagination deterministic. If the table can
489
+ change during export, filter on an immutable snapshot/version marker so later
490
+ pages describe the same logical dataset.
491
+
492
+ ## PDF generation
493
+
494
+ Install `pdfkit` in your application or hosted component dependencies:
495
+
496
+ ```ts
497
+ import PDFDocument from 'pdfkit';
498
+ import type { RevoRuntime } from '@revoengine/sdk';
499
+ import { uploadBinary } from './upload-binary.js';
500
+
501
+ function renderCustomerPdf(customer: unknown): Promise<Buffer> {
502
+ return new Promise((resolve, reject) => {
503
+ const document = new PDFDocument({ margin: 48 });
504
+ const chunks: Buffer[] = [];
505
+
506
+ document.on('data', (chunk: Buffer) => chunks.push(chunk));
507
+ document.on('error', reject);
508
+ document.on('end', () => resolve(Buffer.concat(chunks)));
509
+
510
+ document.fontSize(18).text('Customer summary');
511
+ document.moveDown();
512
+ document.fontSize(10).text(JSON.stringify(customer, null, 2));
513
+ document.end();
514
+ });
515
+ }
516
+
517
+ type ExportRuntime = Pick<RevoRuntime, 'storage'> & {
518
+ readonly api: Pick<RevoRuntime['api'], 'getDatabaseData'>;
519
+ };
520
+
521
+ export async function exportCustomer(
522
+ runtime: ExportRuntime,
523
+ customerId: string,
524
+ ) {
525
+ const { data } = await runtime.api.getDatabaseData('Customers', {
526
+ filter: { field: 'customerId', op: 'eq', value: customerId },
527
+ take: 1,
528
+ });
529
+ if (!data[0]) throw new Error(`Customer ${customerId} was not found.`);
530
+
531
+ const pdf = await renderCustomerPdf(data[0]);
532
+ return uploadBinary(runtime, `customer-${customerId}.pdf`, 'application/pdf', pdf);
533
+ }
534
+ ```
535
+
536
+ Standalone call site:
537
+
538
+ ```ts
539
+ import { RevoClient } from '@revoengine/sdk';
540
+ import { exportCustomer } from './export-customer.js';
541
+
542
+ const revo = new RevoClient();
543
+ const file = await exportCustomer(revo, 'customer-1');
544
+ console.log(file.storageEntryId);
545
+ ```
546
+
547
+ Revo-hosted call site:
548
+
549
+ ```js
550
+ import { exportCustomer } from './export-customer.js';
551
+
552
+ export async function init(runtime) {
553
+ const input = runtime.api.input();
554
+ if (!input || typeof input.customerId !== 'string') {
555
+ throw new Error('customerId input is required.');
556
+ }
557
+ const file = await exportCustomer(runtime, input.customerId);
558
+ return { storageEntryId: file.storageEntryId };
559
+ }
560
+ ```
561
+
562
+ ## Jobs and agents
563
+
564
+ ```ts
565
+ const jobId = await revo.api.triggerJob(
566
+ '8f1fe47f-90e6-4c16-a9ea-ccba5ca2a8da',
567
+ { customerId: 'customer-1' },
568
+ );
569
+
570
+ const agents = await revo.agents.list();
571
+ const agentId = agents[0]?.agentId;
572
+ if (agentId) {
573
+ const run = await revo.agents.startRun(agentId, {
574
+ instruction: `Process the result of job ${jobId}.`,
575
+ triggerType: 'REQUEST',
576
+ triggerRefType: 'JOB',
577
+ triggerRefId: jobId,
578
+ state: { jobId },
579
+ });
580
+ console.log(run.agentRunId);
581
+ }
582
+ ```
583
+
584
+ Available methods and request types are exported through the package's
585
+ TypeScript declarations. The generated declarations are the canonical SDK
586
+ contract for the installed version.
587
+
588
+ ## Error handling
589
+
590
+ All SDK errors derive from `RevoError`:
591
+
592
+ ```ts
593
+ import {
594
+ RevoError,
595
+ RevoRemoteError,
596
+ RevoTransportError,
597
+ } from '@revoengine/sdk';
598
+
599
+ try {
600
+ await revo.api.insertDatabaseData('Sales', [{ saleId: 'sale-1' }]);
601
+ } catch (error) {
602
+ if (error instanceof RevoTransportError && error.indeterminate) {
603
+ // The request may have reached RevoEngine. Check by idempotency key or
604
+ // business identifier before attempting the mutation again.
605
+ throw error;
606
+ }
607
+ if (error instanceof RevoRemoteError) {
608
+ console.error(error.code, error.statusCode, error.message);
609
+ throw error;
610
+ }
611
+ if (error instanceof RevoError) {
612
+ console.error(error.code, error.message);
613
+ throw error;
614
+ }
615
+ throw error;
616
+ }
617
+ ```
618
+
619
+ Common subclasses include:
620
+
621
+ - `RevoConfigurationError`
622
+ - `RevoAuthenticationError`
623
+ - `RevoPermissionDeniedError`
624
+ - `RevoRuntimeContextUnavailableError`
625
+ - `RevoBatchConfigurationError`
626
+ - `RevoBatchLimitError`
627
+ - `RevoRemoteError`
628
+ - `RevoProtocolError`
629
+ - `RevoTransportError`
630
+
631
+ ## SDK 1.0 compatibility notes
632
+
633
+ - Node.js 22 or newer is required.
634
+ - The package provides ESM, CommonJS, and TypeScript declarations.
635
+ - The package has no runtime dependencies.
636
+ - No package-level `api`, `utils`, `storage`, or `agents` singleton is exported.
637
+ - Deprecated low-code methods and aliases are excluded.
638
+ - `api.transactionDatabaseData` is excluded from 1.0.0.
639
+ - Runtime batches are non-transactional and are not retried automatically.
@@ -0,0 +1,30 @@
1
+ # Third-party notices
2
+
3
+ The published `@revoengine/sdk` JavaScript bundles incorporate the following
4
+ third-party packages. This inventory is generated from the shipped bundle source
5
+ maps and is checked against the repository license policy on every release.
6
+
7
+ | Package | Version | License |
8
+ | --- | ---: | --- |
9
+ | `buffer-equal-constant-time` | `1.0.1` | `BSD-3-Clause` |
10
+ | `copy-anything` | `4.1.0` | `MIT` |
11
+ | `ecdsa-sig-formatter` | `1.0.11` | `Apache-2.0` |
12
+ | `jsonwebtoken` | `9.0.3` | `MIT` |
13
+ | `jwa` | `2.0.1` | `MIT` |
14
+ | `jws` | `4.0.1` | `MIT` |
15
+ | `lodash.includes` | `4.3.0` | `MIT` |
16
+ | `lodash.isboolean` | `3.0.3` | `MIT` |
17
+ | `lodash.isinteger` | `4.0.4` | `MIT` |
18
+ | `lodash.isnumber` | `3.0.3` | `MIT` |
19
+ | `lodash.isplainobject` | `4.0.6` | `MIT` |
20
+ | `lodash.isstring` | `4.0.1` | `MIT` |
21
+ | `lodash.once` | `4.1.1` | `MIT` |
22
+ | `ms` | `2.1.3` | `MIT` |
23
+ | `object-hash` | `3.0.0` | `MIT` |
24
+ | `safe-buffer` | `5.2.1` | `MIT` |
25
+ | `semver` | `7.8.5` | `ISC` |
26
+ | `superjson` | `2.2.6` | `MIT` |
27
+ | `uuid` | `13.0.2` | `MIT` |
28
+
29
+ The complete license texts are distributed in
30
+ [`licenses/THIRD_PARTY_LICENSES.txt`](licenses/THIRD_PARTY_LICENSES.txt).