@beam-network/sdk 0.2.3 → 0.2.5

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/dist/client.js CHANGED
@@ -92,6 +92,10 @@ export class BeamClient {
92
92
  preparedDestinations.forEach((preparedDestination, index) => {
93
93
  destinationsById.set(preparedDestination.destination_id, input.destinations[index]);
94
94
  });
95
+ const sourcesById = new Map();
96
+ preparedSources.forEach((preparedSource, index) => {
97
+ sourcesById.set(preparedSource.source_id, input.sources[index]);
98
+ });
95
99
  const routes = [];
96
100
  const multipartUploads = new Map();
97
101
  try {
@@ -101,6 +105,10 @@ export class BeamClient {
101
105
  if (!destination) {
102
106
  throw new Error(`BeamCore returned unknown destination_id: ${target.destination_id}`);
103
107
  }
108
+ const source = sourcesById.get(chunk.source_id);
109
+ if (!source) {
110
+ throw new Error(`BeamCore returned unknown source_id: ${chunk.source_id}`);
111
+ }
104
112
  const metadata = target.metadata ?? {};
105
113
  const finalObjectKey = typeof metadata.final_object_key === "string"
106
114
  ? metadata.final_object_key
@@ -142,6 +150,7 @@ export class BeamClient {
142
150
  routes.push(await this.signProviderRoute({
143
151
  chunk,
144
152
  target,
153
+ source,
145
154
  destination,
146
155
  expiresIn,
147
156
  upload,
@@ -181,6 +190,7 @@ export class BeamClient {
181
190
  return signDestinationRoute({
182
191
  chunk: input.chunk,
183
192
  target: input.target,
193
+ source: input.source,
184
194
  destination: input.destination,
185
195
  expiresIn: input.expiresIn,
186
196
  transferId: input.transferId,
@@ -200,11 +210,13 @@ export class BeamClient {
200
210
  chunkIndex: input.chunk.chunk_index,
201
211
  partNumber: input.partNumber
202
212
  });
203
- const { copyUrl, copySource } = await signUploadPartCopy(input.destination, input.finalObjectKey, stagingObjectKey, input.upload.uploadId, input.partNumber, input.expiresIn);
213
+ const copySourceRange = `bytes=0-${Math.max(0, input.chunk.chunk_size - 1)}`;
214
+ const { copyUrl, copySource } = await signUploadPartCopy(input.destination, input.finalObjectKey, stagingObjectKey, input.upload.uploadId, input.partNumber, input.expiresIn, copySourceRange);
204
215
  const deleteUrl = await signDeleteObject(input.destination, stagingObjectKey, input.expiresIn);
205
216
  return signDestinationRoute({
206
217
  chunk: input.chunk,
207
218
  target: input.target,
219
+ source: input.source,
208
220
  destination: input.destination,
209
221
  expiresIn: input.expiresIn,
210
222
  uploadId: input.upload.uploadId,
@@ -220,6 +232,7 @@ export class BeamClient {
220
232
  stagingObjectKey,
221
233
  copyUrl,
222
234
  copySource,
235
+ copySourceRange,
223
236
  deleteUrl,
224
237
  fetchImpl: this.fetchImpl
225
238
  });
@@ -14,7 +14,7 @@ export declare function createMultipartUpload(destination: ProviderDestinationCo
14
14
  export declare function signCompleteMultipartUpload(destination: ProviderDestinationConfig, objectKey: string, uploadId: string, expiresIn: number): Promise<string>;
15
15
  export declare function signAbortMultipartUpload(destination: ProviderDestinationConfig, objectKey: string, uploadId: string, expiresIn: number): Promise<string>;
16
16
  export declare function signListMultipartUpload(destination: ProviderDestinationConfig, objectKey: string, uploadId: string, expiresIn: number): Promise<string>;
17
- export declare function signUploadPartCopy(destination: ProviderDestinationConfig, finalObjectKey: string, stagingObjectKey: string, uploadId: string, partNumber: number, expiresIn: number): Promise<{
17
+ export declare function signUploadPartCopy(destination: ProviderDestinationConfig, finalObjectKey: string, stagingObjectKey: string, uploadId: string, partNumber: number, expiresIn: number, copySourceRange?: string): Promise<{
18
18
  copyUrl: string;
19
19
  copySource: string;
20
20
  }>;
@@ -23,6 +23,7 @@ export declare function abortMultipartUpload(destination: ProviderDestinationCon
23
23
  export declare function signDestinationRoute(input: {
24
24
  chunk: ChunkSigningPlanItem;
25
25
  target: ChunkDestinationSigningTarget;
26
+ source?: ProviderSourceConfig;
26
27
  destination: ProviderDestinationConfig;
27
28
  expiresIn: number;
28
29
  uploadId?: string;
@@ -38,6 +39,7 @@ export declare function signDestinationRoute(input: {
38
39
  stagingObjectKey?: string;
39
40
  copyUrl?: string;
40
41
  copySource?: string;
42
+ copySourceRange?: string;
41
43
  deleteUrl?: string;
42
44
  fetchImpl?: typeof fetch;
43
45
  }): Promise<SignedChunkRoute>;
@@ -103,7 +103,7 @@ export async function signListMultipartUpload(destination, objectKey, uploadId,
103
103
  }
104
104
  throw new Error(`multipart list-parts is not supported for ${destination.provider}`);
105
105
  }
106
- export async function signUploadPartCopy(destination, finalObjectKey, stagingObjectKey, uploadId, partNumber, expiresIn) {
106
+ export async function signUploadPartCopy(destination, finalObjectKey, stagingObjectKey, uploadId, partNumber, expiresIn, copySourceRange) {
107
107
  if (isS3CompatibleProvider(destination)) {
108
108
  const client = createS3CompatibleClient(destination);
109
109
  const copySource = copySourceHeader(destination, stagingObjectKey);
@@ -114,7 +114,8 @@ export async function signUploadPartCopy(destination, finalObjectKey, stagingObj
114
114
  Key: finalObjectKey,
115
115
  UploadId: uploadId,
116
116
  PartNumber: partNumber,
117
- CopySource: copySource
117
+ CopySource: copySource,
118
+ CopySourceRange: copySourceRange
118
119
  }), { expiresIn })
119
120
  };
120
121
  }
@@ -153,15 +154,23 @@ export async function signDestinationRoute(input) {
153
154
  useStagingPut: input.commitMethod === "upload_part_copy",
154
155
  fetchImpl: input.fetchImpl
155
156
  });
157
+ const sourceRoute = await signSourceRoute({
158
+ source: input.source,
159
+ fallbackUrl: input.chunk.source_url,
160
+ chunk: input.chunk,
161
+ expiresIn: input.expiresIn,
162
+ fetchImpl: input.fetchImpl
163
+ });
156
164
  return {
157
165
  source_id: input.chunk.source_id,
158
166
  destination_id: input.target.destination_id,
159
167
  chunk_index: input.chunk.chunk_index,
160
- source_url: input.chunk.source_url,
168
+ source_url: sourceRoute.url,
161
169
  dest_url: destUrl,
162
170
  source_offset: input.chunk.source_offset,
163
171
  chunk_size: input.chunk.chunk_size,
164
172
  expires_at: expiresAtIso(input.expiresIn),
173
+ headers: sourceRoute.headers,
165
174
  metadata: {
166
175
  ...(input.target.metadata ?? {}),
167
176
  ...(input.transferId ? { transfer_id: input.transferId } : {}),
@@ -171,6 +180,7 @@ export async function signDestinationRoute(input) {
171
180
  ...(input.stagingObjectKey ? { staging_object_key: input.stagingObjectKey } : {}),
172
181
  ...(input.copyUrl ? { copy_url: input.copyUrl } : {}),
173
182
  ...(input.copySource ? { copy_source: input.copySource } : {}),
183
+ ...(input.copySourceRange ? { copy_source_range: input.copySourceRange } : {}),
174
184
  ...(input.deleteUrl ? { delete_url: input.deleteUrl } : {}),
175
185
  ...(input.uploadId ? { upload_id: input.uploadId } : {}),
176
186
  ...(input.partNumber ? { part_number: input.partNumber } : {}),
@@ -180,6 +190,35 @@ export async function signDestinationRoute(input) {
180
190
  }
181
191
  };
182
192
  }
193
+ function rangeHeaderForChunk(chunk) {
194
+ const start = Math.max(0, Math.floor(chunk.source_offset));
195
+ const size = Math.max(1, Math.floor(chunk.chunk_size));
196
+ return `bytes=${start}-${start + size - 1}`;
197
+ }
198
+ async function signSourceRoute(input) {
199
+ const range = rangeHeaderForChunk(input.chunk);
200
+ if (!input.source) {
201
+ return { url: input.fallbackUrl, headers: { Range: range } };
202
+ }
203
+ if (isS3CompatibleProvider(input.source)) {
204
+ const client = createS3CompatibleClient(input.source);
205
+ return {
206
+ url: await getSignedUrl(client, new GetObjectCommand({
207
+ Bucket: input.source.bucket,
208
+ Key: input.source.key,
209
+ Range: range
210
+ }), { expiresIn: input.expiresIn }),
211
+ headers: { Range: range }
212
+ };
213
+ }
214
+ if (isHippiusProvider(input.source)) {
215
+ return {
216
+ url: await hippiusPresign(input.fetchImpl ?? globalThis.fetch, input.source.base_url ?? "https://api.hippius.com", input.source.api_token, input.source.bucket, input.source.key, "get", input.expiresIn),
217
+ headers: { Range: range }
218
+ };
219
+ }
220
+ return unsupportedProviderConfig(input.source);
221
+ }
183
222
  async function signDestinationUrl(input) {
184
223
  if (isS3CompatibleProvider(input.destination)) {
185
224
  const client = createS3CompatibleClient(input.destination);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@beam-network/sdk",
3
- "version": "0.2.3",
3
+ "version": "0.2.5",
4
4
  "description": "TypeScript SDK for BEAM transfer creation and management.",
5
5
  "type": "module",
6
6
  "license": "MIT",