@beam-network/sdk 0.2.1 → 0.2.2

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.d.ts CHANGED
@@ -28,6 +28,7 @@ export declare class BeamClient {
28
28
  urlsExpiresAt?: string;
29
29
  }): Promise<AttachSignedUrlsResponse>;
30
30
  prepareProviderTransfer(input: ProviderTransferCreateInput): Promise<TransferPrepareResponse>;
31
+ private signProviderRoute;
31
32
  createAndDistribute(input: RawTransferCreateInput): Promise<TransferCreateResponse>;
32
33
  waitForTransfer(transferId: string, options?: {
33
34
  timeoutMs?: number;
package/dist/client.js CHANGED
@@ -1,4 +1,4 @@
1
- import { abortMultipartUpload, createMultipartUpload, nowIso, prepareProviderDestination, prepareProviderSource, signAbortMultipartUpload, signCompleteMultipartUpload, signDestinationRoute, signListMultipartUpload } from "./provider-signing.js";
1
+ import { abortMultipartUpload, createMultipartUpload, nowIso, prepareProviderDestination, prepareProviderSource, signAbortMultipartUpload, signCompleteMultipartUpload, signDeleteObject, signDestinationRoute, signListMultipartUpload, signUploadPartCopy } from "./provider-signing.js";
2
2
  export const BEAM_DEFAULT_URL = "https://beamcore.b1m.ai";
3
3
  export class BeamApiError extends Error {
4
4
  status;
@@ -139,23 +139,17 @@ export class BeamClient {
139
139
  }
140
140
  multipartUploads.set(multipartKey, upload);
141
141
  }
142
- routes.push(await signDestinationRoute({
142
+ routes.push(await this.signProviderRoute({
143
143
  chunk,
144
144
  target,
145
145
  destination,
146
146
  expiresIn,
147
- uploadId: upload.uploadId,
147
+ upload,
148
+ transferId: prepared.transfer_id,
149
+ finalObjectKey,
148
150
  partNumber: typeof metadata.part_number === "number"
149
151
  ? metadata.part_number
150
- : chunk.source_chunk_index + 1,
151
- multipartObjectKey: finalObjectKey,
152
- completeUrl: upload.completeUrl,
153
- abortUrl: upload.abortUrl,
154
- listUrl: upload.listUrl,
155
- transferId: prepared.transfer_id,
156
- multipartGroupId: upload.multipartGroupId,
157
- multipartCreatedAt: upload.multipartCreatedAt,
158
- fetchImpl: this.fetchImpl
152
+ : chunk.source_chunk_index + 1
159
153
  }));
160
154
  }
161
155
  }
@@ -182,6 +176,46 @@ export class BeamClient {
182
176
  }
183
177
  return prepared;
184
178
  }
179
+ async signProviderRoute(input) {
180
+ if (isHippiusDestination(input.destination)) {
181
+ return signDestinationRoute({
182
+ chunk: input.chunk,
183
+ target: input.target,
184
+ destination: input.destination,
185
+ expiresIn: input.expiresIn,
186
+ transferId: input.transferId,
187
+ multipartGroupId: input.upload.multipartGroupId,
188
+ multipartCreatedAt: input.upload.multipartCreatedAt,
189
+ fetchImpl: this.fetchImpl
190
+ });
191
+ }
192
+ if (!input.target.object_key) {
193
+ throw new Error("destination signing target is missing object_key");
194
+ }
195
+ const { copyUrl, copySource } = await signUploadPartCopy(input.destination, input.finalObjectKey, input.target.object_key, input.upload.uploadId, input.partNumber, input.expiresIn);
196
+ const deleteUrl = await signDeleteObject(input.destination, input.target.object_key, input.expiresIn);
197
+ return signDestinationRoute({
198
+ chunk: input.chunk,
199
+ target: input.target,
200
+ destination: input.destination,
201
+ expiresIn: input.expiresIn,
202
+ uploadId: input.upload.uploadId,
203
+ partNumber: input.partNumber,
204
+ multipartObjectKey: input.finalObjectKey,
205
+ completeUrl: input.upload.completeUrl,
206
+ abortUrl: input.upload.abortUrl,
207
+ listUrl: input.upload.listUrl,
208
+ transferId: input.transferId,
209
+ multipartGroupId: input.upload.multipartGroupId,
210
+ multipartCreatedAt: input.upload.multipartCreatedAt,
211
+ commitMethod: "upload_part_copy",
212
+ stagingObjectKey: input.target.object_key,
213
+ copyUrl,
214
+ copySource,
215
+ deleteUrl,
216
+ fetchImpl: this.fetchImpl
217
+ });
218
+ }
185
219
  async createAndDistribute(input) {
186
220
  const transfer = await this.createRawTransfer(input);
187
221
  if (transfer.success) {
@@ -14,6 +14,11 @@ 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<{
18
+ copyUrl: string;
19
+ copySource: string;
20
+ }>;
21
+ export declare function signDeleteObject(destination: ProviderDestinationConfig, objectKey: string, expiresIn: number): Promise<string>;
17
22
  export declare function abortMultipartUpload(destination: ProviderDestinationConfig, objectKey: string, uploadId: string): Promise<void>;
18
23
  export declare function signDestinationRoute(input: {
19
24
  chunk: ChunkSigningPlanItem;
@@ -29,6 +34,11 @@ export declare function signDestinationRoute(input: {
29
34
  transferId?: string;
30
35
  multipartGroupId?: string;
31
36
  multipartCreatedAt?: string;
37
+ commitMethod?: "upload_part_copy";
38
+ stagingObjectKey?: string;
39
+ copyUrl?: string;
40
+ copySource?: string;
41
+ deleteUrl?: string;
32
42
  fetchImpl?: typeof fetch;
33
43
  }): Promise<SignedChunkRoute>;
34
44
  export declare function isS3CompatibleProvider(config: ProviderSourceConfig | ProviderDestinationConfig): config is AnyS3CompatibleProviderConfig;
@@ -1,4 +1,4 @@
1
- import { AbortMultipartUploadCommand, CompleteMultipartUploadCommand, CreateMultipartUploadCommand, GetObjectCommand, HeadObjectCommand, ListPartsCommand, PutObjectCommand, S3Client, UploadPartCommand } from "@aws-sdk/client-s3";
1
+ import { AbortMultipartUploadCommand, CompleteMultipartUploadCommand, CreateMultipartUploadCommand, DeleteObjectCommand, GetObjectCommand, HeadObjectCommand, ListPartsCommand, PutObjectCommand, S3Client, UploadPartCopyCommand, UploadPartCommand } from "@aws-sdk/client-s3";
2
2
  import { getSignedUrl } from "@aws-sdk/s3-request-presigner";
3
3
  export function nowIso() {
4
4
  return new Date().toISOString();
@@ -103,6 +103,30 @@ 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) {
107
+ if (isS3CompatibleProvider(destination)) {
108
+ const client = createS3CompatibleClient(destination);
109
+ const copySource = copySourceHeader(destination, stagingObjectKey);
110
+ return {
111
+ copySource,
112
+ copyUrl: await getSignedUrl(client, new UploadPartCopyCommand({
113
+ Bucket: destination.bucket,
114
+ Key: finalObjectKey,
115
+ UploadId: uploadId,
116
+ PartNumber: partNumber,
117
+ CopySource: copySource
118
+ }), { expiresIn })
119
+ };
120
+ }
121
+ throw new Error(`multipart copy is not supported for ${destination.provider}`);
122
+ }
123
+ export async function signDeleteObject(destination, objectKey, expiresIn) {
124
+ if (isS3CompatibleProvider(destination)) {
125
+ const client = createS3CompatibleClient(destination);
126
+ return getSignedUrl(client, new DeleteObjectCommand({ Bucket: destination.bucket, Key: objectKey }), { expiresIn });
127
+ }
128
+ throw new Error(`object delete signing is not supported for ${destination.provider}`);
129
+ }
106
130
  export async function abortMultipartUpload(destination, objectKey, uploadId) {
107
131
  if (isS3CompatibleProvider(destination)) {
108
132
  await createS3CompatibleClient(destination).send(new AbortMultipartUploadCommand({ Bucket: destination.bucket, Key: objectKey, UploadId: uploadId }));
@@ -123,6 +147,7 @@ export async function signDestinationRoute(input) {
123
147
  expiresIn: input.expiresIn,
124
148
  uploadId: input.uploadId,
125
149
  partNumber: input.partNumber,
150
+ useStagingPut: input.commitMethod === "upload_part_copy",
126
151
  fetchImpl: input.fetchImpl
127
152
  });
128
153
  return {
@@ -139,6 +164,11 @@ export async function signDestinationRoute(input) {
139
164
  ...(input.transferId ? { transfer_id: input.transferId } : {}),
140
165
  ...(input.multipartGroupId ? { multipart_group_id: input.multipartGroupId } : {}),
141
166
  ...(input.multipartCreatedAt ? { multipart_created_at: input.multipartCreatedAt } : {}),
167
+ ...(input.commitMethod ? { commit_method: input.commitMethod } : {}),
168
+ ...(input.stagingObjectKey ? { staging_object_key: input.stagingObjectKey } : {}),
169
+ ...(input.copyUrl ? { copy_url: input.copyUrl } : {}),
170
+ ...(input.copySource ? { copy_source: input.copySource } : {}),
171
+ ...(input.deleteUrl ? { delete_url: input.deleteUrl } : {}),
142
172
  ...(input.uploadId ? { upload_id: input.uploadId } : {}),
143
173
  ...(input.partNumber ? { part_number: input.partNumber } : {}),
144
174
  ...(input.completeUrl ? { complete_url: input.completeUrl } : {}),
@@ -150,7 +180,7 @@ export async function signDestinationRoute(input) {
150
180
  async function signDestinationUrl(input) {
151
181
  if (isS3CompatibleProvider(input.destination)) {
152
182
  const client = createS3CompatibleClient(input.destination);
153
- if (input.uploadId && input.partNumber) {
183
+ if (input.uploadId && input.partNumber && !input.useStagingPut) {
154
184
  return getSignedUrl(client, new UploadPartCommand({
155
185
  Bucket: input.destination.bucket,
156
186
  Key: input.uploadPartObjectKey,
@@ -269,3 +299,6 @@ function hasText(value) {
269
299
  function unsupportedProviderConfig(value) {
270
300
  throw new Error(`Unsupported provider config: ${JSON.stringify(value)}`);
271
301
  }
302
+ function copySourceHeader(destination, objectKey) {
303
+ return `/${destination.bucket}/${objectKey.split("/").map(encodeURIComponent).join("/")}`;
304
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@beam-network/sdk",
3
- "version": "0.2.1",
3
+ "version": "0.2.2",
4
4
  "description": "TypeScript SDK for BEAM transfer creation and management.",
5
5
  "type": "module",
6
6
  "license": "MIT",