@revoengine/sdk 2.0.0 → 3.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/README.md CHANGED
@@ -1,17 +1,25 @@
1
1
  # @revoengine/sdk
2
2
 
3
3
  Official Node.js SDK for RevoEngine. It provides the modern `api`, `utils`,
4
- `storage`, and `agents` namespaces, top-level `execute()`, and the `batch` controller in both
4
+ `storage`, `transport`, `vault`, `serviceAccount`, and `agents` namespaces, top-level `execute()`, and the `batch` controller in both
5
5
  Revo-hosted `CUSTOM_NODEJS` components and standalone Node.js applications.
6
6
 
7
7
  Requirements: Node.js 22 or newer.
8
8
 
9
- ## SDK 2.0.0 compatibility
9
+ Development and GitLab CI use Node.js 24.21.0. Run `nvm use` to select the checked-in `.nvmrc`.
10
10
 
11
- This major release synchronizes the complete public SDK contract with the current
12
- platform low-code declarations. Remote calls require a platform runtime that admits
11
+ ## SDK 3.0.0 compatibility
12
+
13
+ This major release synchronizes the complete public SDK contract with RevoEngine
14
+ 1.7.1 and removes deprecated compatibility methods and legacy Files types. Remote calls require a platform runtime that admits
13
15
  the bundled contract revision; publishing the SDK alone does not deploy that runtime.
14
- Use SDK 1.0.1 with older deployments until their platform contract is upgraded.
16
+ Use the SDK version supported by the target platform deployment until its contract is upgraded.
17
+
18
+ Storage declarations include physical-line reads, quote-disabled CSV dialects,
19
+ per-record byte limits, and the opt-in `onError: 'skipRow'` read policy. That policy
20
+ skips records with the wrong source column count and returns bounded locations in
21
+ `csvReport`; syntax and record-size errors still abort. The report describes the
22
+ whole source and must not be summed across pages.
15
23
 
16
24
  HTTP Storage requests/responses now use `requestType: 'storage'` and
17
25
  `responseType: 'storage'`, with flat Storage-only `source` / `target` objects.
@@ -21,6 +29,42 @@ network or hosted bridge dispatch. Automation schedules use `{ scheduleFor }`
21
29
  options instead of positional dates. Regenerated types also include the current
22
30
  Storage and database contracts; use those declarations when migrating callers.
23
31
 
32
+ The `transport` namespace exposes `sftpImport`, `sftpExport`, and `sftpCommands`
33
+ with active Secret names or IDs instead of inline credentials. Storage references
34
+ use the same namespace and effective access rules as other file operations.
35
+ Legacy SFTP helpers and the removed thread-goal methods are not exposed by the
36
+ current SDK contract. Refer to the [transfer guide](https://docs.revoengine.com/low-code/sftp)
37
+ for Secret formats and file-transfer examples.
38
+
39
+ This release retains portable Component digest declarations and one readable-relation
40
+ contract for Databases, live Views, and Materialized Views. Use `api.exportDatabase()`
41
+ for all three relation types, and `api.getDatabaseData()` for structured reads.
42
+ Account data uses `metadata` and `metadataAdvanced`; use `vault.get()` for Secret
43
+ values and `storage.*` for file content. The instance-data source list excludes
44
+ legacy Files resources.
45
+
46
+ Database exports can select CSV, TSV, NDJSON, or XLSX. An asynchronous export
47
+ returns its job ID for operation tracking. The import workflow starts with
48
+ `api.importDatabase()`, then permits a reviewed mapping update and an explicit
49
+ `api.commitDatabaseImport()` after preview validation. The generated declarations
50
+ describe the current request and response shapes; the platform still enforces
51
+ permissions and validates source and target state before committing an import.
52
+
53
+ Assistant model inputs follow the current platform: `gpt-6.1-sol` and
54
+ `gpt-6-luna`; Fast mode is supported for Luna. Update older Sol model identifiers.
55
+
56
+ Remote MCP server configurations in this contract use public HTTPS destinations.
57
+ Private-network access is not an accepted SDK setting; review the server URL,
58
+ provider consent, Vault binding, and tool permissions before enabling a plugin.
59
+
60
+ The SDK includes `agents.createResponse()` and the saved Assistant conversation
61
+ contract: `instructions`, `contextMode` and text or validated JSON `responseFormat`.
62
+ The typed answer is in `output.text` or `output.json`; retain the returned thread
63
+ for an ordinary `agents.sendMessage()` continuation. Provider refusal, incomplete
64
+ output and invalid JSON do not become a successful parsed answer.
65
+ Native Assistant SSE handles and `watchMessage()` remain local to managed V8
66
+ Components and are excluded from the remote SDK contract.
67
+
24
68
  ## Choose your runtime
25
69
 
26
70
  | Environment | How to start | Authentication |
@@ -28,14 +72,14 @@ Storage and database contracts; use those declarations when migrating callers.
28
72
  | Revo-hosted `CUSTOM_NODEJS` | Export `async function init(runtime)` | Revo injects an execution-bound runtime; user code receives no API key. |
29
73
  | Standalone Node.js | Create `new RevoClient(options)` | Supply a RevoEngine API key explicitly or through an environment variable. |
30
74
 
31
- Both modes expose the same `api`, `utils`, `storage`, `agents`, `execute`, and `batch`
75
+ Both modes expose the same `api`, `utils`, `storage`, `transport`, `vault`, `serviceAccount`, `agents`, `execute`, and `batch`
32
76
  properties, but return types reflect where the work happens:
33
77
 
34
78
  | Call kind | Revo-hosted | Standalone |
35
79
  | --- | --- | --- |
36
80
  | Execution snapshot, cache, debug, and logging | Synchronous | Throws synchronously because no execution context exists |
37
81
  | Current user and instance | Synchronous injected snapshot | Asynchronous lazy `/api/v1/me` discovery |
38
- | Remote `api`, `storage`, `agents`, and `execute()` calls | Asynchronous | Asynchronous |
82
+ | Remote `api`, `storage`, `transport`, `vault`, `serviceAccount`, `agents`, and `execute()` calls | Asynchronous | Asynchronous |
39
83
  | Local `utils` and `batch.configure()` | Synchronous unless the utility is inherently asynchronous | Same |
40
84
 
41
85
  ## Installation
@@ -52,7 +96,7 @@ RevoEngine pins that version again in the deployment package and injects the
52
96
  runtime into the component entrypoint. Component code does not construct a
53
97
  `RevoClient`.
54
98
 
55
- The platform chooses the hosted package version; publishing SDK 2.0.0 does not
99
+ The platform chooses the hosted package version; publishing a new SDK does not
56
100
  upgrade existing hosted deployments or their generated package pins.
57
101
 
58
102
  Hosted user code receives neither a tenant API key nor the private runtime
@@ -71,7 +115,7 @@ separate initialization method.
71
115
  ```js
72
116
  /** @param {import('@revoengine/sdk').RevoRuntime} runtime */
73
117
  export async function init(runtime) {
74
- const { api, utils, storage, agents, execute, batch } = runtime;
118
+ const { api, utils, storage, vault, agents, execute, batch } = runtime;
75
119
  const { data: rows, next } = await api.getDatabaseData('Sales', {
76
120
  fields: ['saleId', 'customerId', 'total', 'createdAt'],
77
121
  sort: ['-createdAt'],
@@ -102,14 +146,16 @@ JavaScript ignores the additional runtime argument.
102
146
 
103
147
  Hosted context comes from the current execution snapshot and is synchronous, just
104
148
  like the low-code surface. Only platform-backed work returns a promise.
149
+ Account metadata is available through `currentUser.metadata` and
150
+ `currentUser.metadataAdvanced`.
105
151
 
106
152
  ```js
107
153
  export async function init(runtime) {
108
- const { api } = runtime;
154
+ const { api, vault } = runtime;
109
155
  const input = api.input();
110
156
  const currentUser = api.currentUser();
111
157
  const instance = api.getInstanceDetails();
112
- const signingSecret = await api.getSecret('WEBHOOK_SIGNING_SECRET');
158
+ const signingSecret = (await vault.get('WEBHOOK_SIGNING_SECRET', { scope: 'instance' })).revision.value;
113
159
 
114
160
  api.log({
115
161
  message: 'Processing custom component',
@@ -129,6 +175,8 @@ Execution-only methods such as `api.input()`, `api.getContext()`,
129
175
  `api.getExecutionId()`, and `api.getOperationId()` are available only in hosted
130
176
  executions.
131
177
 
178
+ Use `runtime.execute(code, { readOnly: true })` for transient code that must not write platform state. `readOnly: false` selects full execution for an authorized standalone client; a hosted execution inherits its mode and cannot escalate a restricted parent.
179
+
132
180
  ### Configure hosted batching
133
181
 
134
182
  Configure batching before the first remote call:
@@ -196,7 +244,7 @@ There is no `init()` or connection method.
196
244
  ## Execute active low-code libraries
197
245
 
198
246
  `execute(code, options)` runs one transient JavaScript or TypeScript component inside
199
- RevoEngine. The source has the normal low-code `api` and active tenant `libs.*`
247
+ RevoEngine. The source has the normal low-code `api` and active tenant `lib.*`
200
248
  surface. Library functions and source never move into the Node.js process; only the
201
249
  JSON-serializable request and execution result cross the runtime transport.
202
250
 
@@ -209,8 +257,8 @@ export async function init(runtime) {
209
257
  const execution = await runtime.execute(
210
258
  `
211
259
  const customerId = api.input('customerId');
212
- const customer = await libs.Customers.Queries.get(customerId);
213
- const balance = await libs.Billing.Balance.current(customerId);
260
+ const customer = await lib.Customers.Queries.get(customerId);
261
+ const balance = await lib.Billing.Balance.current(customerId);
214
262
  return { customer, balance };
215
263
  `,
216
264
  {
@@ -245,7 +293,7 @@ type CustomerSummary = {
245
293
  const execution = await revo.execute<CustomerSummary>(
246
294
  `
247
295
  const customerId = api.input('customerId');
248
- return libs.Customers.Summary.build(customerId);
296
+ return lib.Customers.Summary.build(customerId);
249
297
  `,
250
298
  {
251
299
  inputs: { customerId: 'customer-1' },
@@ -259,7 +307,7 @@ console.log(execution.results);
259
307
  JavaScript is selected with `language: 'javascript'`; TypeScript is the default.
260
308
  The default timeout is 60 seconds. Standalone `executionDefaults` set reusable
261
309
  language, timeout, or memory defaults, and per-call options override them.
262
- One `execute()` call creates one isolated execution. Put related `libs.*`
310
+ One `execute()` call creates one isolated execution. Put related `lib.*`
263
311
  operations in the same source when they belong to one workflow. Concurrent separate
264
312
  calls still use the SDK's automatic JSON-RPC batching but execute in separate isolates.
265
313
  Low-code runtime batches are not retried because source can perform writes.
@@ -317,11 +365,12 @@ Calls queued in the same microtask are grouped. `Promise.all` is the normal way
317
365
  to issue a batch:
318
366
 
319
367
  ```ts
320
- const [customers, crmToken, activeAgents] = await Promise.all([
368
+ const [customers, crmSecret, activeAgents] = await Promise.all([
321
369
  revo.api.getDatabaseData('Customers', { take: 100 }),
322
- revo.api.getSecret('CRM_API_TOKEN'),
370
+ revo.vault.get('CRM_API_TOKEN', { scope: 'instance' }),
323
371
  revo.agents.list(),
324
372
  ]);
373
+ const crmToken = crmSecret.revision.value;
325
374
  ```
326
375
 
327
376
  Sequential `await` statements naturally produce separate batches:
@@ -387,7 +436,8 @@ export async function init(runtime) {
387
436
  args: { userId: currentUser.userId, instanceId, hasInput: input != null },
388
437
  });
389
438
 
390
- return runtime.api.getSecret('SIGNING_SECRET');
439
+ const signingSecret = await runtime.vault.get('SIGNING_SECRET', { scope: 'instance' });
440
+ return { configured: Boolean(signingSecret.revision.value) };
391
441
  }
392
442
  ```
393
443
 
@@ -763,3 +813,85 @@ Common subclasses include:
763
813
  - Deprecated low-code methods and aliases are excluded.
764
814
  - `api.transactionDatabaseData` is excluded.
765
815
  - Runtime batches are non-transactional and are not retried automatically.
816
+
817
+ ## Vault manager
818
+
819
+ The native `client.vault` manager uses the same get/create/update/delete/rotate
820
+ contract for instance (default) and verified user scope. Get alone returns
821
+ `secret.revision.value` as a Buffer containing the stored UTF-8 text; Rotate returns metadata without values.
822
+ Revision versions are normalized validFrom timestamps. validFrom accepts null,
823
+ Date, ISO or epoch milliseconds; a future Rotate preserves current availability.
824
+ `listRevisions` exposes paginated metadata history.
825
+
826
+ ```ts
827
+ const secret = await client.vault.get('TOKEN', { scope: 'user' });
828
+ const token = secret.revision.value.toString('utf8');
829
+ await client.vault.rotate('TOKEN', { value: replacement }, { scope: 'user', validFrom: null });
830
+ ```
831
+
832
+ Do not log values or access tokens. Instance access requires Secret roles and
833
+ creator ownership or administrator rights. User scope uses the verified account;
834
+ management requires owner rights and does not inherit saved Component/Tool grants.
835
+ Writes throw `READ_ONLY_OPERATION_FORBIDDEN` when the execution has `readOnly: true`. See the
836
+ [Vault guide](https://docs.revoengine.com/low-code/reference/vault) for all methods.
837
+
838
+ The same flat manager exposes `getAccessToken`, `getIntegrationMetadata`,
839
+ `discoverIntegration`, `connectIntegration`, and `disconnectIntegration`. Token reads
840
+ return the access token with its matching ISO expiry and refresh when necessary.
841
+ Connect requires nullable `expectedRevision` (null to create) and returns an
842
+ authorization URL for interactive consent through the existing frontend callback.
843
+ Disconnect retains definition/history/grants and does not revoke provider access.
844
+ Saved Component/Tool reads preserve exact personal grants; direct SDK owner/admin
845
+ reads and management are authorized separately.
846
+
847
+
848
+ ## Bulk Jobs and Webhooks
849
+
850
+ Use `api.cancelJobs`, `retryJobs`, `deleteJobs`, `cancelWebhooks`, `retryWebhooks`,
851
+ and `deleteWebhooks` with exactly one non-empty platform `filter` or an ID array
852
+ (`jobIds` / `webhookIds`, 1–1000 IDs). A filter selects every matching row beyond
853
+ list pagination. An optional actor-scoped `idempotencyKey` protects repeat admission.
854
+ The SDK never automatically retries mutations.
855
+
856
+ ```ts
857
+ const input = {
858
+ filter: { field: 'status', op: 'eq', value: 'ERROR' },
859
+ idempotencyKey: 'retry-errors-2026-10-01',
860
+ };
861
+ const preview = await client.api.previewAutomationOperation('jobs', 'retry', input);
862
+ // Review advisory preview.matched / preview.eligible before submitting.
863
+ const operation = await client.api.retryJobs(input);
864
+ const progress = await client.api.getAutomationOperation(operation.operationId);
865
+ const outcomes = await client.api.getAutomationOperationItems(operation.operationId);
866
+ // Fetch subsequent pages with outcomes.nextCursor as the second argument.
867
+ ```
868
+
869
+ Operations report `PENDING`, `PROCESSING`, `FINISHED`, or `ERROR`, plus
870
+ `total`, `processed`, `skipped`, and `failed`. `FINISHED` means lifecycle requests
871
+ were processed; downstream execution/delivery may continue and failed can be non-zero.
872
+ Item pages contain safe source/result IDs and error codes. Preview is advisory;
873
+ admission freezes selection and the worker rechecks state and permissions.
874
+ Cancel/delete require Automation Admin; retry accepts Automation Runner/Admin.
875
+
876
+ `retryWebhooks` accepts `requestPatch`: url/method/body replace whole fields;
877
+ headers/query accept `set` and `remove`, and `maskDetails` adds masks while preserving
878
+ existing masks. Masked original values cannot be recovered: provide explicit
879
+ replacements or the item fails with `REPLAY_PAYLOAD_UNAVAILABLE`. If the entire
880
+ headers section was masked, `headers.set` supplies its complete replacement.
881
+ Request patches are limited to 1 MiB of serialized JSON. Never log replacement
882
+ credentials. The operation result does not expose saved request bodies.
883
+
884
+ ```ts
885
+ await client.api.retryWebhooks({
886
+ webhookIds: selectedWebhookIds,
887
+ idempotencyKey: retryAdmissionKey,
888
+ requestPatch: {
889
+ headers: { set: { Authorization: `Bearer ${replacementToken}` }, remove: ['X-Old-Key'] },
890
+ query: { set: { apiVersion: '2' }, remove: ['legacy'] },
891
+ maskDetails: ['headers.Authorization'],
892
+ },
893
+ });
894
+ ```
895
+
896
+ The target platform requires the bulk-operation migration and an active API worker
897
+ lane. Publishing this SDK does not deploy them or change the hosted SDK pin.