@beam-network/sdk 0.2.23 → 0.4.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.
@@ -1,12 +1,11 @@
1
1
  import { encode, decode } from "@msgpack/msgpack";
2
2
  import { connect } from "nats";
3
- export const TRANSFER_CLIENT_CONTROL_SCHEMA_VERSION = "transfer-client-control/v2";
3
+ export const TRANSFER_CLIENT_CONTROL_SCHEMA_VERSION = "transfer-client-control/v4";
4
4
  export const BEAM_DEFAULT_NATS_URL = "tls://nats.b1m.ai:4222";
5
5
  export const BEAM_DEFAULT_NATS_WS_URL = "wss://nats.b1m.ai:443";
6
6
  // NATS enforces max_payload per message. This guard splits signed-route control
7
7
  // messages before the broker rejects them; transfer bytes never flow through NATS.
8
8
  export const BEAM_DEFAULT_MAX_PAYLOAD_BYTES = 24 * 1024 * 1024;
9
- export const ROUTE_RECOVERY_SIGN_MESSAGE_TYPE = "transfer.route_recovery.sign";
10
9
  function buildConnectionOptions(options) {
11
10
  const connectionOptions = {
12
11
  servers: options.natsUrl,
@@ -36,8 +35,12 @@ export class BeamTransferControl {
36
35
  natsUrl;
37
36
  apiKey;
38
37
  nc = null;
38
+ connectionPromise = null;
39
+ closed = false;
39
40
  authToken = null;
40
41
  authTokenExpiresAt = 0;
42
+ authResolvePromise = null;
43
+ terminalWaitCancellations = new Set();
41
44
  constructor(options) {
42
45
  this.apiKey = options.apiKey;
43
46
  this.keyPrefix = options.apiKey.slice(0, 12);
@@ -54,59 +57,29 @@ export class BeamTransferControl {
54
57
  throw new Error("transferRuntimeShardCount must be a positive integer.");
55
58
  }
56
59
  }
57
- async serveRouteRecoverySigner(transferId, handler) {
58
- const nc = await this.connection();
59
- const subject = this.routeRecoverySignSubject(transferId);
60
- const sub = nc.subscribe(subject);
61
- await nc.flush();
62
- let active = true;
63
- void (async () => {
64
- for await (const msg of sub) {
65
- if (!active)
66
- break;
67
- let request = null;
68
- try {
69
- request = decode(msg.data);
70
- if (request.schema_version !== TRANSFER_CLIENT_CONTROL_SCHEMA_VERSION ||
71
- request.environment !== this.environment ||
72
- request.key_prefix !== this.keyPrefix ||
73
- request.transfer_id !== transferId ||
74
- request.message_type !== ROUTE_RECOVERY_SIGN_MESSAGE_TYPE ||
75
- request.producer !== "transfer-runtime") {
76
- throw new Error("route recovery request envelope mismatch");
77
- }
78
- const payload = await handler(request.payload);
79
- msg.respond(encode(this.buildRouteRecoveryReply(request, true, 200, payload)));
80
- }
81
- catch (error) {
82
- const fallback = request ?? {
83
- message_id: "unknown",
84
- request_id: "unknown",
85
- transfer_id: transferId
86
- };
87
- msg.respond(encode(this.buildRouteRecoveryReply(fallback, false, 500, undefined, {
88
- code: "route_recovery_sign_failed",
89
- message: error instanceof Error ? error.message : String(error)
90
- })));
91
- }
92
- }
93
- })();
94
- return () => {
95
- active = false;
96
- sub.unsubscribe();
97
- };
98
- }
99
60
  async close() {
100
- if (!this.nc)
101
- return;
102
- await this.nc.drain();
61
+ this.closed = true;
62
+ for (const cancel of [...this.terminalWaitCancellations])
63
+ cancel();
64
+ if (this.connectionPromise) {
65
+ try {
66
+ await this.connectionPromise;
67
+ }
68
+ catch {
69
+ // A connection that loses the close race closes itself before rejecting.
70
+ }
71
+ }
72
+ const nc = this.nc;
103
73
  this.nc = null;
74
+ if (nc && !nc.isClosed())
75
+ await nc.drain();
104
76
  }
105
- async request(messageType, payload, transferId) {
106
- const nc = await this.connection();
77
+ async request(messageType, payload, options = {}) {
107
78
  const authToken = await this.resolveAuthToken();
108
- const shardId = transferId ? transferShardId(transferId, this.shardCount) : 0;
109
- const requestId = randomId();
79
+ const shardId = options.transferId ? transferShardId(options.transferId, this.shardCount) : 0;
80
+ const requestId = options.idempotencyKey
81
+ ? await stableRequestId(`${messageType}:${options.idempotencyKey}`)
82
+ : randomId();
110
83
  const envelope = {
111
84
  message_id: `${TRANSFER_CLIENT_CONTROL_SCHEMA_VERSION}:${this.environment}:${this.keyPrefix}:${messageType}:${requestId}`,
112
85
  schema_version: TRANSFER_CLIENT_CONTROL_SCHEMA_VERSION,
@@ -125,16 +98,123 @@ export class BeamTransferControl {
125
98
  throw new Error(`NATS lifecycle request is ${bytes.byteLength} bytes, above maxPayloadBytes=${this.maxPayloadBytes}`);
126
99
  }
127
100
  const subject = this.requestSubject(messageType, shardId);
128
- const response = await nc.request(subject, bytes, { timeout: this.requestTimeoutMs });
129
- const decoded = decode(response.data);
130
- if (!decoded.ok) {
131
- const body = JSON.stringify(decoded.error ?? {});
132
- throw new Error(`Beam lifecycle request failed with ${decoded.status}: ${body}`);
101
+ let lastError;
102
+ for (let attempt = 0; attempt < LIFECYCLE_REQUEST_MAX_ATTEMPTS; attempt += 1) {
103
+ try {
104
+ const nc = await this.connection();
105
+ const response = await nc.request(subject, bytes, { timeout: this.requestTimeoutMs });
106
+ const decoded = decode(response.data);
107
+ if (decoded.ok)
108
+ return (decoded.payload ?? {});
109
+ const body = JSON.stringify(decoded.error ?? {});
110
+ const error = new Error(`Beam lifecycle request failed with ${decoded.status}: ${body}`);
111
+ if (!isRetryableLifecycleStatus(decoded.status) || attempt + 1 >= LIFECYCLE_REQUEST_MAX_ATTEMPTS) {
112
+ throw error;
113
+ }
114
+ lastError = error;
115
+ }
116
+ catch (error) {
117
+ if (!isRetryableLifecycleError(error) || attempt + 1 >= LIFECYCLE_REQUEST_MAX_ATTEMPTS) {
118
+ throw error;
119
+ }
120
+ lastError = error;
121
+ if (this.nc?.isClosed())
122
+ this.nc = null;
123
+ }
124
+ await sleepWithJitter(LIFECYCLE_REQUEST_RETRY_DELAYS_MS[attempt] ?? 1_000);
125
+ }
126
+ throw lastError instanceof Error ? lastError : new Error("Beam lifecycle request failed after retries");
127
+ }
128
+ async openTerminalSignalWaiter(transferId) {
129
+ const nc = await this.connection();
130
+ const pending = [];
131
+ let activeWait = null;
132
+ let closed = false;
133
+ let terminalError = null;
134
+ let subscription = null;
135
+ const settleActive = (event, error) => {
136
+ const wait = activeWait;
137
+ if (!wait)
138
+ return;
139
+ activeWait = null;
140
+ clearTimeout(wait.timer);
141
+ if (error !== undefined)
142
+ wait.reject(error);
143
+ else
144
+ wait.resolve(event);
145
+ };
146
+ const close = async () => {
147
+ if (closed)
148
+ return;
149
+ closed = true;
150
+ this.terminalWaitCancellations.delete(cancel);
151
+ subscription?.unsubscribe();
152
+ settleActive(null);
153
+ };
154
+ const cancel = () => { void close(); };
155
+ try {
156
+ subscription = nc.subscribe(this.terminalSubject(transferId), {
157
+ callback: (error, message) => {
158
+ if (error) {
159
+ terminalError = error;
160
+ subscription?.unsubscribe();
161
+ settleActive(null, error);
162
+ return;
163
+ }
164
+ try {
165
+ const event = parseTerminalEvent(decode(message.data), transferId);
166
+ if (activeWait)
167
+ settleActive(event);
168
+ else if (pending.length === 0)
169
+ pending.push(event);
170
+ }
171
+ catch (decodeError) {
172
+ terminalError = decodeError;
173
+ subscription?.unsubscribe();
174
+ settleActive(null, decodeError);
175
+ }
176
+ }
177
+ });
178
+ await nc.flush();
179
+ if (this.closed) {
180
+ await close();
181
+ throw new Error("NATS lifecycle control is closed");
182
+ }
183
+ this.terminalWaitCancellations.add(cancel);
184
+ if (this.closed) {
185
+ await close();
186
+ throw new Error("NATS lifecycle control is closed");
187
+ }
188
+ return {
189
+ wait: async (timeoutMs) => {
190
+ if (!Number.isFinite(timeoutMs) || timeoutMs <= 0) {
191
+ throw new Error("timeoutMs must be a positive number.");
192
+ }
193
+ if (closed)
194
+ return null;
195
+ if (terminalError !== null)
196
+ throw terminalError;
197
+ const event = pending.shift();
198
+ if (event)
199
+ return event;
200
+ if (activeWait)
201
+ throw new Error("terminal signal waiter already has an active wait");
202
+ return new Promise((resolve, reject) => {
203
+ const timer = setTimeout(() => settleActive(null), timeoutMs);
204
+ activeWait = { resolve, reject, timer };
205
+ });
206
+ },
207
+ close
208
+ };
209
+ }
210
+ catch (error) {
211
+ subscription?.unsubscribe();
212
+ settleActive(null);
213
+ throw error;
133
214
  }
134
- return (decoded.payload ?? {});
135
215
  }
136
216
  splitRoutesForPayload(messageType, basePayload, routes) {
137
- const split = (candidate) => {
217
+ const encodedBytes = (candidate) => {
138
218
  const encoded = encode({
139
219
  schema_version: TRANSFER_CLIENT_CONTROL_SCHEMA_VERSION,
140
220
  environment: this.environment,
@@ -147,67 +227,126 @@ export class BeamTransferControl {
147
227
  producer: "sdk",
148
228
  payload: { ...basePayload, route_batch: compactSignedRoutes(candidate) }
149
229
  });
150
- if (encoded.byteLength <= this.maxPayloadBytes)
151
- return [candidate];
152
- if (candidate.length === 1) {
153
- throw new Error(`single signed route is ${encoded.byteLength} bytes, above maxPayloadBytes=${this.maxPayloadBytes}`);
154
- }
155
- const midpoint = Math.ceil(candidate.length / 2);
156
- return [...split(candidate.slice(0, midpoint)), ...split(candidate.slice(midpoint))];
230
+ return encoded.byteLength;
157
231
  };
158
- return routes.length ? split(routes) : [];
232
+ const chunks = [];
233
+ let offset = 0;
234
+ while (offset < routes.length) {
235
+ let low = 1;
236
+ let high = routes.length - offset;
237
+ let accepted = 0;
238
+ while (low <= high) {
239
+ const count = Math.floor((low + high) / 2);
240
+ if (encodedBytes(routes.slice(offset, offset + count)) <= this.maxPayloadBytes) {
241
+ accepted = count;
242
+ low = count + 1;
243
+ }
244
+ else
245
+ high = count - 1;
246
+ }
247
+ if (accepted === 0) {
248
+ const bytes = encodedBytes(routes.slice(offset, offset + 1));
249
+ throw new Error(`single signed route is ${bytes} bytes, above maxPayloadBytes=${this.maxPayloadBytes}`);
250
+ }
251
+ chunks.push(routes.slice(offset, offset + accepted));
252
+ offset += accepted;
253
+ }
254
+ return chunks;
159
255
  }
160
256
  async connection() {
257
+ if (this.closed)
258
+ throw new Error("NATS lifecycle control is closed");
161
259
  if (this.nc && !this.nc.isClosed())
162
260
  return this.nc;
163
- this.nc = await connect(buildConnectionOptions({
164
- natsUrl: this.natsUrl,
165
- apiKey: this.apiKey,
166
- keyPrefix: this.keyPrefix
167
- }));
168
- return this.nc;
261
+ if (this.connectionPromise)
262
+ return this.connectionPromise;
263
+ const pending = (async () => {
264
+ const nc = await connect(buildConnectionOptions({
265
+ natsUrl: this.natsUrl,
266
+ apiKey: this.apiKey,
267
+ keyPrefix: this.keyPrefix
268
+ }));
269
+ if (this.closed) {
270
+ await nc.drain();
271
+ throw new Error("NATS lifecycle control is closed");
272
+ }
273
+ this.nc = nc;
274
+ return nc;
275
+ })();
276
+ this.connectionPromise = pending;
277
+ try {
278
+ return await pending;
279
+ }
280
+ finally {
281
+ if (this.connectionPromise === pending)
282
+ this.connectionPromise = null;
283
+ }
169
284
  }
170
285
  async resolveAuthToken() {
171
286
  const now = Math.floor(Date.now() / 1000);
172
287
  if (this.authToken && this.authTokenExpiresAt - 5 > now)
173
288
  return this.authToken;
174
- const nc = await this.connection();
175
- const response = await nc.request(this.authSubject(), new TextEncoder().encode("{}"), { timeout: this.requestTimeoutMs });
176
- const parsed = JSON.parse(new TextDecoder().decode(response.data));
177
- if (!parsed.ok || !parsed.token) {
178
- throw new Error(`Beam SDK NATS auth resolve failed: ${parsed.error ?? "unknown_error"}`);
289
+ if (this.authResolvePromise)
290
+ return this.authResolvePromise;
291
+ const pending = this.resolveAuthTokenFresh();
292
+ this.authResolvePromise = pending;
293
+ try {
294
+ return await pending;
295
+ }
296
+ finally {
297
+ if (this.authResolvePromise === pending)
298
+ this.authResolvePromise = null;
179
299
  }
180
- const claims = decodeJwtPayload(parsed.token);
181
- this.authToken = parsed.token;
182
- this.authTokenExpiresAt = claims.exp;
183
- return parsed.token;
300
+ }
301
+ async resolveAuthTokenFresh() {
302
+ let lastError;
303
+ for (let attempt = 0; attempt < LIFECYCLE_REQUEST_MAX_ATTEMPTS; attempt += 1) {
304
+ try {
305
+ const nc = await this.connection();
306
+ const response = await nc.request(this.authSubject(), new TextEncoder().encode("{}"), { timeout: this.requestTimeoutMs });
307
+ const parsed = JSON.parse(new TextDecoder().decode(response.data));
308
+ if (!parsed.ok || !parsed.token) {
309
+ throw new Error(`Beam SDK NATS auth resolve failed: ${parsed.error ?? "unknown_error"}`);
310
+ }
311
+ const claims = decodeJwtPayload(parsed.token);
312
+ this.authToken = parsed.token;
313
+ this.authTokenExpiresAt = claims.exp;
314
+ return parsed.token;
315
+ }
316
+ catch (error) {
317
+ if (!isRetryableLifecycleError(error) || attempt + 1 >= LIFECYCLE_REQUEST_MAX_ATTEMPTS) {
318
+ throw error;
319
+ }
320
+ lastError = error;
321
+ if (this.nc?.isClosed())
322
+ this.nc = null;
323
+ await sleepWithJitter(LIFECYCLE_REQUEST_RETRY_DELAYS_MS[attempt] ?? 1_000);
324
+ }
325
+ }
326
+ throw lastError instanceof Error ? lastError : new Error("Beam SDK NATS auth resolve failed after retries");
184
327
  }
185
328
  authSubject() {
186
329
  return `${this.subjectPrefix}.${this.environment}.auth.${this.keyPrefix}.resolve`;
187
330
  }
188
- routeRecoverySignSubject(transferId) {
189
- return `${this.subjectPrefix}.${this.environment}.sdk.${this.keyPrefix}.transfer.${transferId}.route_recovery_sign`;
190
- }
191
- buildRouteRecoveryReply(request, ok, status, payload, error) {
192
- return {
193
- message_id: request.message_id,
194
- schema_version: TRANSFER_CLIENT_CONTROL_SCHEMA_VERSION,
195
- environment: this.environment,
196
- key_prefix: this.keyPrefix,
197
- transfer_id: request.transfer_id,
198
- message_type: ROUTE_RECOVERY_SIGN_MESSAGE_TYPE,
199
- request_id: request.request_id,
200
- occurred_at: new Date().toISOString(),
201
- producer: "sdk",
202
- ok,
203
- status,
204
- ...(payload ? { payload } : {}),
205
- ...(error ? { error } : {})
206
- };
207
- }
208
331
  requestSubject(messageType, shardId) {
209
332
  return `${this.subjectPrefix}.${this.environment}.sdk.${this.keyPrefix}.shard.${shardId}.${messageType.replace(/\./g, "_")}`;
210
333
  }
334
+ terminalSubject(transferId) {
335
+ return `${this.subjectPrefix}.${this.environment}.events.${this.keyPrefix}.${transferId}.terminal`;
336
+ }
337
+ }
338
+ function parseTerminalEvent(value, transferId) {
339
+ if (!value || typeof value !== "object" || Array.isArray(value))
340
+ throw new Error("invalid transfer terminal event");
341
+ const event = value;
342
+ if (event.schema_version !== TRANSFER_CLIENT_CONTROL_SCHEMA_VERSION ||
343
+ event.producer !== "transfer-runtime" ||
344
+ event.transfer_id !== transferId ||
345
+ !["completed", "failed", "cancelled"].includes(String(event.status)) ||
346
+ typeof event.occurred_at !== "string") {
347
+ throw new Error("invalid transfer terminal event");
348
+ }
349
+ return event;
211
350
  }
212
351
  const ROUTE_ATTEMPT_METADATA_KEYS = new Set([
213
352
  "part_number",
@@ -218,9 +357,7 @@ const ROUTE_ATTEMPT_METADATA_KEYS = new Set([
218
357
  "copy_url",
219
358
  "copy_source",
220
359
  "copy_source_range",
221
- "delete_url",
222
- "part_verify_url",
223
- "list_page_url"
360
+ "delete_url"
224
361
  ]);
225
362
  const ROUTE_IDENTITY_METADATA_KEYS = [
226
363
  "source_id",
@@ -232,8 +369,6 @@ const ROUTE_IDENTITY_METADATA_KEYS = [
232
369
  export function compactSignedRoutes(routes) {
233
370
  const source_chunks = [];
234
371
  const sourceRefs = new Map();
235
- const multipart_groups = [];
236
- const groupRefs = new Map();
237
372
  const compactRoutes = [];
238
373
  for (const [routeIndex, route] of routes.entries()) {
239
374
  const sourceKey = JSON.stringify([
@@ -264,21 +399,12 @@ export function compactSignedRoutes(routes) {
264
399
  const deliveryIndex = route.delivery_index ?? nonNegativeInteger(metadata.delivery_index) ?? routeIndex;
265
400
  for (const key of ROUTE_IDENTITY_METADATA_KEYS)
266
401
  delete metadata[key];
267
- const groupBaseKey = multipartGroupKey(route, metadata);
268
- const groupMetadata = Object.fromEntries(Object.entries(metadata).filter(([key]) => !ROUTE_ATTEMPT_METADATA_KEYS.has(key)));
269
- const groupKey = groupBaseKey ? `${groupBaseKey}:${JSON.stringify(groupMetadata)}` : null;
270
- let groupRef;
271
- if (groupKey) {
272
- groupRef = groupRefs.get(groupKey);
273
- if (groupRef === undefined) {
274
- groupRef = multipart_groups.length;
275
- groupRefs.set(groupKey, groupRef);
276
- multipart_groups.push({ group_ref: groupRef, metadata: groupMetadata });
277
- }
278
- for (const key of Object.keys(metadata)) {
279
- if (!ROUTE_ATTEMPT_METADATA_KEYS.has(key))
280
- delete metadata[key];
281
- }
402
+ const multipartGroupId = typeof metadata.multipart_group_id === "string"
403
+ ? metadata.multipart_group_id
404
+ : undefined;
405
+ for (const key of Object.keys(metadata)) {
406
+ if (!ROUTE_ATTEMPT_METADATA_KEYS.has(key))
407
+ delete metadata[key];
282
408
  }
283
409
  compactRoutes.push(compact({
284
410
  source_ref: sourceRef,
@@ -287,21 +413,11 @@ export function compactSignedRoutes(routes) {
287
413
  dest_url: route.dest_url,
288
414
  expires_at: route.expires_at,
289
415
  dest_headers: route.dest_headers,
290
- multipart_group_ref: groupRef,
416
+ multipart_group_id: multipartGroupId,
291
417
  metadata: Object.keys(metadata).length ? metadata : undefined
292
418
  }));
293
419
  }
294
- return { source_chunks, multipart_groups, routes: compactRoutes };
295
- }
296
- function multipartGroupKey(route, metadata) {
297
- const groupId = typeof metadata.multipart_group_id === "string" ? metadata.multipart_group_id : "";
298
- if (groupId)
299
- return `id:${groupId}`;
300
- const uploadId = typeof metadata.upload_id === "string" ? metadata.upload_id : "";
301
- const finalObjectKey = typeof metadata.final_object_key === "string" ? metadata.final_object_key : "";
302
- return uploadId || finalObjectKey
303
- ? JSON.stringify([route.source_id, route.destination_id, uploadId, finalObjectKey])
304
- : null;
420
+ return { source_chunks, routes: compactRoutes };
305
421
  }
306
422
  function nonNegativeInteger(value) {
307
423
  const parsed = typeof value === "number" ? value : Number(value);
@@ -340,3 +456,41 @@ function randomId() {
340
456
  return cryptoApi.randomUUID();
341
457
  return `${Date.now().toString(36)}-${Math.random().toString(36).slice(2)}`;
342
458
  }
459
+ const LIFECYCLE_REQUEST_MAX_ATTEMPTS = 3;
460
+ const LIFECYCLE_REQUEST_RETRY_DELAYS_MS = [150, 500];
461
+ function isRetryableLifecycleStatus(status) {
462
+ return status === 408 || status === 425 || status === 429 || status >= 500;
463
+ }
464
+ function isRetryableLifecycleError(error) {
465
+ const record = error && typeof error === "object" ? error : null;
466
+ const code = typeof record?.code === "string" ? record.code : "";
467
+ const message = error instanceof Error ? error.message : String(error);
468
+ const combined = `${code} ${message}`.toLowerCase();
469
+ return [
470
+ "timeout",
471
+ "no responders",
472
+ "connection closed",
473
+ "disconnected",
474
+ "econnreset",
475
+ "econnrefused",
476
+ "etimedout",
477
+ "socket",
478
+ "network"
479
+ ].some((token) => combined.includes(token));
480
+ }
481
+ async function sleepWithJitter(baseMs) {
482
+ const jitter = Math.floor(baseMs * (Math.random() * 0.4 - 0.2));
483
+ await new Promise((resolve) => setTimeout(resolve, Math.max(1, baseMs + jitter)));
484
+ }
485
+ async function stableRequestId(identity) {
486
+ const bytes = new TextEncoder().encode(identity);
487
+ let digest;
488
+ if (globalThis.crypto?.subtle) {
489
+ digest = new Uint8Array(await globalThis.crypto.subtle.digest("SHA-256", bytes));
490
+ }
491
+ else {
492
+ const { createHash } = await import("node:crypto");
493
+ digest = new Uint8Array(createHash("sha256").update(bytes).digest());
494
+ }
495
+ return `idempotent-${[...digest].map((byte) => byte.toString(16).padStart(2, "0")).join("")}`;
496
+ }
@@ -14,16 +14,21 @@ export declare function prepareProviderSourceForPlan(source: ProviderSourceConfi
14
14
  export declare function prepareProviderDestination(destination: ProviderDestinationConfig, options?: {
15
15
  index?: number;
16
16
  }): PreparedDestination;
17
- export declare function createMultipartUpload(destination: ProviderDestinationConfig, objectKey: string): Promise<string>;
17
+ export declare function createMultipartUpload(input: {
18
+ destination: ProviderDestinationConfig;
19
+ objectKey: string;
20
+ metadata: Record<string, string>;
21
+ }): Promise<string>;
22
+ export declare function signFinalObjectHead(destination: ProviderDestinationConfig, objectKey: string, expiresIn: number): Promise<string>;
18
23
  export declare function signCompleteMultipartUpload(destination: ProviderDestinationConfig, objectKey: string, uploadId: string, expiresIn: number): Promise<string>;
19
24
  export declare function signAbortMultipartUpload(destination: ProviderDestinationConfig, objectKey: string, uploadId: string, expiresIn: number): Promise<string>;
20
- export declare function signListObjects(destination: ProviderDestinationConfig, prefix: string, expiresIn: number): Promise<string>;
25
+ export declare function signListObjects(destination: ProviderDestinationConfig, prefix: string, expiresIn: number, options?: {
26
+ startAfter?: string;
27
+ }): Promise<string>;
21
28
  export declare function signListMultipartUpload(destination: ProviderDestinationConfig, objectKey: string, uploadId: string, expiresIn: number, options?: {
22
29
  maxParts?: number;
23
30
  partNumberMarker?: number;
24
31
  }): Promise<string>;
25
- export declare function listPartsPageMarker(partNumber: number, pageSize?: number): number | undefined;
26
- export declare function listPartsVerifyMarker(partNumber: number): number | undefined;
27
32
  export declare function signUploadPartCopy(destination: ProviderDestinationConfig, finalObjectKey: string, stagingObjectKey: string, uploadId: string, partNumber: number, expiresIn: number, copySourceRange?: string): Promise<{
28
33
  copyUrl: string;
29
34
  copySource: string;
@@ -36,20 +41,10 @@ export declare function signDestinationRoute(input: {
36
41
  source?: ProviderSourceConfig;
37
42
  destination: ProviderDestinationConfig;
38
43
  expiresIn: number;
39
- uploadId?: string;
40
44
  partNumber?: number;
41
- multipartObjectKey?: string;
42
- completeUrl?: string;
43
- abortUrl?: string;
44
- listUrl?: string;
45
- transferId?: string;
46
45
  multipartGroupId?: string;
47
- multipartCreatedAt?: string;
48
- commitMethod?: "upload_part" | "upload_part_copy";
49
- partVerifyUrl?: string;
50
- listPageUrl?: string;
46
+ commitMethod?: "upload_part_copy";
51
47
  stagingObjectKey?: string;
52
- stagingListUrl?: string;
53
48
  copyUrl?: string;
54
49
  copySource?: string;
55
50
  copySourceRange?: string;