@beam-network/sdk 0.2.15 → 0.2.16

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
@@ -91,4 +91,4 @@ Use `S3ProviderConfig` for ordinary AWS S3 if preferred, and keep using
91
91
  `S3CompatibleProviderConfig` when a provider needs a custom S3-compatible
92
92
  endpoint.
93
93
 
94
- For low-level BeamCore `/transfers/create` calls with raw HTTP-style configs, use `createRawTransfer`.
94
+ For low-level raw transfer configs, use `createRawTransfer`; lifecycle transport still goes through NATS.
package/dist/client.d.ts CHANGED
@@ -1,15 +1,18 @@
1
1
  import type { AttachSignedUrlsResponse, BeamClientOptions, DistributeResponse, PlanningHttpSource, PreparedDestination, PreparedHttpSource, ProviderTransferCreateInput, RawTransferCreateInput, SignedChunkRoute, SignedUrlFlow, TransferCancelResponse, TransferCreateResponse, TransferPlanResponse, TransferPrepareResponse, TransferStatusInfo } from "./models.js";
2
- export declare const BEAM_DEFAULT_URL = "https://beamcore.b1m.ai";
2
+ import { BEAM_DEFAULT_NATS_URL } from "./nats-control.js";
3
+ export { BEAM_DEFAULT_NATS_URL };
3
4
  export declare class BeamApiError extends Error {
4
5
  readonly status: number;
5
6
  readonly body: string;
6
7
  constructor(message: string, status: number, body: string);
7
8
  }
8
9
  export declare class BeamClient {
9
- readonly baseUrl: string;
10
10
  readonly apiKey: string;
11
+ readonly natsUrl: string;
11
12
  private readonly fetchImpl;
13
+ private readonly control;
12
14
  constructor(options?: BeamClientOptions);
15
+ close(): Promise<void>;
13
16
  createRawTransfer(input: RawTransferCreateInput): Promise<TransferCreateResponse>;
14
17
  createTransfer(input: ProviderTransferCreateInput): Promise<TransferPrepareResponse>;
15
18
  transferStatus(transferId: string): Promise<TransferStatusInfo>;
@@ -45,7 +48,6 @@ export declare class BeamClient {
45
48
  timeoutMs?: number;
46
49
  pollIntervalMs?: number;
47
50
  }): Promise<TransferStatusInfo>;
48
- private request;
49
51
  }
50
52
  export declare function calculateOptimalChunkSize(totalSize: number): number;
51
53
  export declare function buildStagingObjectPrefix(input: {
package/dist/client.js CHANGED
@@ -1,5 +1,6 @@
1
1
  import { abortMultipartUpload, computeChunksContentMd5, createMultipartUpload, nowIso, prepareProviderDestination, prepareProviderSource, prepareProviderSourceForPlan, isS3CompatibleProvider, listPartsPageMarker, listPartsVerifyMarker, signAbortMultipartUpload, signCompleteMultipartUpload, signDeleteObject, signDestinationRoute, signListMultipartUpload, signListObjects, signUploadPartCopy } from "./provider-signing.js";
2
- export const BEAM_DEFAULT_URL = "https://beamcore.b1m.ai";
2
+ import { BeamTransferControl, BEAM_DEFAULT_NATS_URL } from "./nats-control.js";
3
+ export { BEAM_DEFAULT_NATS_URL };
3
4
  export class BeamApiError extends Error {
4
5
  status;
5
6
  body;
@@ -11,26 +12,41 @@ export class BeamApiError extends Error {
11
12
  }
12
13
  }
13
14
  export class BeamClient {
14
- baseUrl;
15
15
  apiKey;
16
+ natsUrl;
16
17
  fetchImpl;
18
+ control;
17
19
  constructor(options = {}) {
18
20
  if (!options.apiKey?.trim()) {
19
21
  throw new Error("apiKey is required.");
20
22
  }
21
- this.baseUrl = normalizeBaseUrl(resolveBaseUrl(options));
22
23
  this.apiKey = options.apiKey;
24
+ this.natsUrl = options.natsUrl ?? options.natsWsUrl ?? BEAM_DEFAULT_NATS_URL;
25
+ this.control = new BeamTransferControl({
26
+ apiKey: this.apiKey,
27
+ natsUrl: options.natsUrl,
28
+ natsWsUrl: options.natsWsUrl,
29
+ environment: options.environment,
30
+ subjectPrefix: options.transferClientSubjectPrefix,
31
+ transferRuntimeShardCount: options.transferRuntimeShardCount,
32
+ requestTimeoutMs: options.requestTimeoutMs,
33
+ maxPayloadBytes: options.maxPayloadBytes
34
+ });
23
35
  this.fetchImpl = options.fetch ?? globalThis.fetch;
24
36
  if (!this.fetchImpl) {
25
37
  throw new Error("A fetch implementation is required.");
26
38
  }
27
39
  }
40
+ close() {
41
+ return this.control.close();
42
+ }
28
43
  createRawTransfer(input) {
29
44
  const body = compact({
45
+ transfer_id: newTransferId(),
30
46
  sources: input.sources,
31
47
  destinations: input.destinations,
32
48
  total_size: input.totalSize,
33
- chunk_size: input.chunkSize ?? calculateOptimalChunkSize(input.totalSize),
49
+ chunk_size: input.chunkSize,
34
50
  name: input.name,
35
51
  merkle_root: input.merkleRoot,
36
52
  chunk_hashes: input.chunkHashes,
@@ -40,27 +56,25 @@ export class BeamClient {
40
56
  progressive_mode: input.progressiveMode || undefined,
41
57
  signed_url_flow: input.signedUrlFlow
42
58
  });
43
- return this.request("POST", "/transfers/create", body);
59
+ return this.control.request("transfer.create", body);
44
60
  }
45
61
  createTransfer(input) {
46
62
  return this.prepareProviderTransfer(input);
47
63
  }
48
64
  transferStatus(transferId) {
49
65
  validateId(transferId, "transferId");
50
- return this.request("GET", `/transfers/${encodeURIComponent(transferId)}/status`);
66
+ return this.control.request("transfer.status", { transfer_id: transferId }, transferId);
51
67
  }
52
68
  distributeTransfer(transferId) {
53
69
  validateId(transferId, "transferId");
54
- return this.request("POST", "/transfers/distribute", {
55
- transfer_id: transferId
56
- });
70
+ return this.control.request("transfer.distribute", { transfer_id: transferId }, transferId);
57
71
  }
58
72
  cancelTransfer(transferId) {
59
73
  validateId(transferId, "transferId");
60
- return this.request("DELETE", `/transfers/${encodeURIComponent(transferId)}`);
74
+ return this.control.request("transfer.cancel", { transfer_id: transferId }, transferId);
61
75
  }
62
76
  planTransfer(input) {
63
- return this.request("POST", "/transfers/plan", compact({
77
+ return this.control.request("transfer.plan", compact({
64
78
  sources: input.sources,
65
79
  destinations: input.destinations,
66
80
  name: input.name,
@@ -71,7 +85,9 @@ export class BeamClient {
71
85
  }));
72
86
  }
73
87
  prepareTransfer(input) {
74
- return this.request("POST", "/transfers/prepare", compact({
88
+ const transferId = newTransferId();
89
+ return this.control.request("transfer.prepare", compact({
90
+ transfer_id: transferId,
75
91
  sources: input.sources,
76
92
  destinations: input.destinations,
77
93
  name: input.name,
@@ -79,16 +95,33 @@ export class BeamClient {
79
95
  experimental: input.experimental || undefined,
80
96
  urls_expires_at: input.urlsExpiresAt,
81
97
  signed_url_flow: input.signedUrlFlow
82
- }));
98
+ }), transferId);
83
99
  }
84
- attachSignedUrls(transferId, input) {
100
+ async attachSignedUrls(transferId, input) {
85
101
  validateId(transferId, "transferId");
86
- return this.request("POST", "/transfers/attach-signed-urls", compact({
102
+ const attachmentId = newTransferId();
103
+ await this.control.request("transfer.attach_signed_urls.begin", compact({
87
104
  transfer_id: transferId,
88
- chunk_routes: input.chunkRoutes,
89
- transfer_key: input.transferKey,
105
+ attachment_id: attachmentId,
106
+ total_routes: input.chunkRoutes.length,
90
107
  urls_expires_at: input.urlsExpiresAt
91
- }));
108
+ }), transferId);
109
+ const chunks = this.control.splitRoutesForPayload("transfer.attach_signed_urls.chunk", {
110
+ transfer_id: transferId,
111
+ attachment_id: attachmentId
112
+ }, input.chunkRoutes);
113
+ for (let chunkIndex = 0; chunkIndex < chunks.length; chunkIndex += 1) {
114
+ await this.control.request("transfer.attach_signed_urls.chunk", {
115
+ transfer_id: transferId,
116
+ attachment_id: attachmentId,
117
+ chunk_index: chunkIndex,
118
+ chunk_routes: chunks[chunkIndex]
119
+ }, transferId);
120
+ }
121
+ return this.control.request("transfer.attach_signed_urls.commit", {
122
+ transfer_id: transferId,
123
+ attachment_id: attachmentId
124
+ }, transferId);
92
125
  }
93
126
  async prepareProviderTransfer(input) {
94
127
  const expiresIn = input.expiresIn ?? 3600;
@@ -409,27 +442,6 @@ export class BeamClient {
409
442
  await sleep(pollIntervalMs);
410
443
  }
411
444
  }
412
- async request(method, path, body) {
413
- const headers = {
414
- Accept: "application/json",
415
- "X-Api-Key": this.apiKey
416
- };
417
- let payload;
418
- if (body !== undefined) {
419
- headers["Content-Type"] = "application/json";
420
- payload = JSON.stringify(body);
421
- }
422
- const response = await this.fetchImpl(`${this.baseUrl}${path}`, {
423
- method,
424
- headers,
425
- body: payload
426
- });
427
- const text = await response.text();
428
- if (!response.ok) {
429
- throw new BeamApiError(`BEAM API request failed with ${response.status}`, response.status, text);
430
- }
431
- return (text ? JSON.parse(text) : {});
432
- }
433
445
  }
434
446
  function checksumChunksBySource(chunkPlan, destinationsById) {
435
447
  const chunksBySource = new Map();
@@ -710,14 +722,11 @@ export function calculateOptimalChunkSize(totalSize) {
710
722
  }
711
723
  return maxChunk;
712
724
  }
713
- function resolveBaseUrl(options) {
714
- if (options.baseUrl) {
715
- return options.baseUrl;
716
- }
717
- return BEAM_DEFAULT_URL;
718
- }
719
- function normalizeBaseUrl(value) {
720
- return value.replace(/\/+$/, "");
725
+ function newTransferId() {
726
+ const cryptoApi = globalThis.crypto;
727
+ if (cryptoApi?.randomUUID)
728
+ return cryptoApi.randomUUID();
729
+ return `${Date.now().toString(36)}-${Math.random().toString(36).slice(2)}`;
721
730
  }
722
731
  function compact(input) {
723
732
  return Object.fromEntries(Object.entries(input).filter(([, value]) => value !== undefined));
package/dist/models.d.ts CHANGED
@@ -1,7 +1,13 @@
1
1
  export type SignedUrlFlow = "signed_url_v1" | "signed_url_v2";
2
2
  export interface BeamClientOptions {
3
3
  apiKey?: string;
4
- baseUrl?: string;
4
+ natsUrl?: string;
5
+ natsWsUrl?: string;
6
+ environment?: string;
7
+ transferClientSubjectPrefix?: string;
8
+ transferRuntimeShardCount?: number;
9
+ requestTimeoutMs?: number;
10
+ maxPayloadBytes?: number;
5
11
  fetch?: typeof fetch;
6
12
  }
7
13
  export interface SourceConfig {
@@ -71,6 +77,7 @@ export interface RawTransferCreateInput {
71
77
  export interface TransferCreateResponse {
72
78
  success: boolean;
73
79
  transfer_id: string;
80
+ transfer_key?: string;
74
81
  experimental?: boolean;
75
82
  total_chunks: number;
76
83
  total_sources: number;
@@ -113,11 +120,16 @@ export interface DestinationStatusInfo {
113
120
  }
114
121
  export interface TransferStatusInfo {
115
122
  transfer_id: string;
123
+ name?: string;
116
124
  status: string;
117
125
  error_message: string | null;
118
126
  experimental?: boolean;
119
127
  started_at: string | null;
120
128
  completed_at: string | null;
129
+ total_bytes?: number;
130
+ total_size?: number;
131
+ total_chunks?: number;
132
+ chunks_completed?: number;
121
133
  }
122
134
  export interface S3ProviderConfig {
123
135
  provider: "s3";
@@ -0,0 +1,36 @@
1
+ export declare const TRANSFER_CLIENT_CONTROL_SCHEMA_VERSION = "transfer-client-control/v1";
2
+ export declare const BEAM_DEFAULT_NATS_URL = "tls://nats.b1m.ai:4222";
3
+ export declare const BEAM_DEFAULT_NATS_WS_URL = "wss://nats.b1m.ai:443";
4
+ export type TransferClientMessageType = "transfer.plan" | "transfer.create" | "transfer.prepare" | "transfer.attach_signed_urls.begin" | "transfer.attach_signed_urls.chunk" | "transfer.attach_signed_urls.commit" | "transfer.distribute" | "transfer.status" | "transfer.cancel";
5
+ export interface TransferControlOptions {
6
+ apiKey: string;
7
+ natsUrl?: string;
8
+ natsWsUrl?: string;
9
+ environment?: string;
10
+ subjectPrefix?: string;
11
+ transferRuntimeShardCount?: number;
12
+ requestTimeoutMs?: number;
13
+ maxPayloadBytes?: number;
14
+ }
15
+ export declare class BeamTransferControl {
16
+ readonly environment: string;
17
+ readonly keyPrefix: string;
18
+ readonly shardCount: number;
19
+ readonly maxPayloadBytes: number;
20
+ private readonly subjectPrefix;
21
+ private readonly requestTimeoutMs;
22
+ private readonly natsUrl;
23
+ private readonly apiKey;
24
+ private nc;
25
+ private authToken;
26
+ private authTokenExpiresAt;
27
+ constructor(options: TransferControlOptions);
28
+ close(): Promise<void>;
29
+ request<T>(messageType: TransferClientMessageType, payload: Record<string, unknown>, transferId?: string): Promise<T>;
30
+ splitRoutesForPayload(messageType: TransferClientMessageType, basePayload: Record<string, unknown>, routes: unknown[]): unknown[][];
31
+ private connection;
32
+ private resolveAuthToken;
33
+ private authSubject;
34
+ private requestSubject;
35
+ }
36
+ export declare function transferShardId(transferId: string, shardCount: number): number;
@@ -0,0 +1,162 @@
1
+ import { encode, decode } from "@msgpack/msgpack";
2
+ import { connect } from "nats";
3
+ export const TRANSFER_CLIENT_CONTROL_SCHEMA_VERSION = "transfer-client-control/v1";
4
+ export const BEAM_DEFAULT_NATS_URL = "tls://nats.b1m.ai:4222";
5
+ export const BEAM_DEFAULT_NATS_WS_URL = "wss://nats.b1m.ai:443";
6
+ export class BeamTransferControl {
7
+ environment;
8
+ keyPrefix;
9
+ shardCount;
10
+ maxPayloadBytes;
11
+ subjectPrefix;
12
+ requestTimeoutMs;
13
+ natsUrl;
14
+ apiKey;
15
+ nc = null;
16
+ authToken = null;
17
+ authTokenExpiresAt = 0;
18
+ constructor(options) {
19
+ this.apiKey = options.apiKey;
20
+ this.keyPrefix = options.apiKey.slice(0, 12);
21
+ this.environment = options.environment ?? "prod";
22
+ this.subjectPrefix = normalizeSubjectPrefix(options.subjectPrefix ?? "beam.transfer.client");
23
+ this.shardCount = options.transferRuntimeShardCount ?? 1;
24
+ this.requestTimeoutMs = options.requestTimeoutMs ?? 30_000;
25
+ this.maxPayloadBytes = options.maxPayloadBytes ?? 6 * 1024 * 1024;
26
+ this.natsUrl = options.natsUrl ?? options.natsWsUrl ?? BEAM_DEFAULT_NATS_URL;
27
+ if (/^https?:\/\//i.test(this.natsUrl) || /^wss?:\/\//i.test(this.natsUrl) && !options.natsWsUrl) {
28
+ throw new Error("Beam SDK lifecycle endpoint must be nats://, tls://, or configured as natsWsUrl.");
29
+ }
30
+ if (!Number.isInteger(this.shardCount) || this.shardCount < 1) {
31
+ throw new Error("transferRuntimeShardCount must be a positive integer.");
32
+ }
33
+ }
34
+ async close() {
35
+ if (!this.nc)
36
+ return;
37
+ await this.nc.drain();
38
+ this.nc = null;
39
+ }
40
+ async request(messageType, payload, transferId) {
41
+ const nc = await this.connection();
42
+ const authToken = await this.resolveAuthToken();
43
+ const shardId = transferId ? transferShardId(transferId, this.shardCount) : 0;
44
+ const requestId = randomId();
45
+ const envelope = {
46
+ message_id: `${TRANSFER_CLIENT_CONTROL_SCHEMA_VERSION}:${this.environment}:${this.keyPrefix}:${messageType}:${requestId}`,
47
+ schema_version: TRANSFER_CLIENT_CONTROL_SCHEMA_VERSION,
48
+ environment: this.environment,
49
+ key_prefix: this.keyPrefix,
50
+ shard_id: shardId,
51
+ message_type: messageType,
52
+ request_id: requestId,
53
+ auth_token: authToken,
54
+ occurred_at: new Date().toISOString(),
55
+ producer: "sdk",
56
+ payload
57
+ };
58
+ const bytes = encode(envelope);
59
+ if (bytes.byteLength > this.maxPayloadBytes) {
60
+ throw new Error(`NATS lifecycle request is ${bytes.byteLength} bytes, above maxPayloadBytes=${this.maxPayloadBytes}`);
61
+ }
62
+ const subject = this.requestSubject(messageType, shardId);
63
+ const response = await nc.request(subject, bytes, { timeout: this.requestTimeoutMs });
64
+ const decoded = decode(response.data);
65
+ if (!decoded.ok) {
66
+ const body = JSON.stringify(decoded.error ?? {});
67
+ throw new Error(`Beam lifecycle request failed with ${decoded.status}: ${body}`);
68
+ }
69
+ return (decoded.payload ?? {});
70
+ }
71
+ splitRoutesForPayload(messageType, basePayload, routes) {
72
+ const chunks = [];
73
+ let current = [];
74
+ for (const route of routes) {
75
+ const candidate = [...current, route];
76
+ const encoded = encode({
77
+ schema_version: TRANSFER_CLIENT_CONTROL_SCHEMA_VERSION,
78
+ environment: this.environment,
79
+ key_prefix: this.keyPrefix,
80
+ shard_id: 0,
81
+ message_type: messageType,
82
+ request_id: randomId(),
83
+ auth_token: "x".repeat(512),
84
+ occurred_at: new Date().toISOString(),
85
+ producer: "sdk",
86
+ payload: { ...basePayload, chunk_routes: candidate }
87
+ });
88
+ if (current.length > 0 && encoded.byteLength > this.maxPayloadBytes) {
89
+ chunks.push(current);
90
+ current = [route];
91
+ }
92
+ else {
93
+ current = candidate;
94
+ }
95
+ }
96
+ if (current.length > 0)
97
+ chunks.push(current);
98
+ return chunks;
99
+ }
100
+ async connection() {
101
+ if (this.nc && !this.nc.isClosed())
102
+ return this.nc;
103
+ this.nc = await connect({
104
+ servers: this.natsUrl,
105
+ user: this.keyPrefix,
106
+ pass: this.apiKey,
107
+ name: `beam-sdk-${this.keyPrefix}`
108
+ });
109
+ return this.nc;
110
+ }
111
+ async resolveAuthToken() {
112
+ const now = Math.floor(Date.now() / 1000);
113
+ if (this.authToken && this.authTokenExpiresAt - 5 > now)
114
+ return this.authToken;
115
+ const nc = await this.connection();
116
+ const response = await nc.request(this.authSubject(), new TextEncoder().encode("{}"), { timeout: this.requestTimeoutMs });
117
+ const parsed = JSON.parse(new TextDecoder().decode(response.data));
118
+ if (!parsed.ok || !parsed.token) {
119
+ throw new Error(`Beam SDK NATS auth resolve failed: ${parsed.error ?? "unknown_error"}`);
120
+ }
121
+ const claims = decodeJwtPayload(parsed.token);
122
+ this.authToken = parsed.token;
123
+ this.authTokenExpiresAt = claims.exp;
124
+ return parsed.token;
125
+ }
126
+ authSubject() {
127
+ return `${this.subjectPrefix}.${this.environment}.auth.${this.keyPrefix}.resolve`;
128
+ }
129
+ requestSubject(messageType, shardId) {
130
+ return `${this.subjectPrefix}.${this.environment}.sdk.${this.keyPrefix}.shard.${shardId}.${messageType.replace(/\./g, "_")}`;
131
+ }
132
+ }
133
+ export function transferShardId(transferId, shardCount) {
134
+ let hash = 2166136261;
135
+ for (let i = 0; i < transferId.length; i += 1) {
136
+ hash ^= transferId.charCodeAt(i);
137
+ hash = Math.imul(hash, 16777619) >>> 0;
138
+ }
139
+ return hash % shardCount;
140
+ }
141
+ function decodeJwtPayload(jwt) {
142
+ const parts = jwt.split(".");
143
+ if (parts.length < 2)
144
+ throw new Error("invalid JWT");
145
+ return JSON.parse(base64UrlDecode(parts[1]));
146
+ }
147
+ function base64UrlDecode(value) {
148
+ const normalized = value.replace(/-/g, "+").replace(/_/g, "/");
149
+ const padded = normalized.padEnd(Math.ceil(normalized.length / 4) * 4, "=");
150
+ if (typeof Buffer !== "undefined")
151
+ return Buffer.from(padded, "base64").toString("utf8");
152
+ return atob(padded);
153
+ }
154
+ function normalizeSubjectPrefix(value) {
155
+ return value.replace(/^\.+|\.+$/g, "");
156
+ }
157
+ function randomId() {
158
+ const cryptoApi = globalThis.crypto;
159
+ if (cryptoApi?.randomUUID)
160
+ return cryptoApi.randomUUID();
161
+ return `${Date.now().toString(36)}-${Math.random().toString(36).slice(2)}`;
162
+ }
package/package.json CHANGED
@@ -1,36 +1,38 @@
1
1
  {
2
- "name": "@beam-network/sdk",
3
- "version": "0.2.15",
4
- "description": "TypeScript SDK for BEAM transfer creation and management.",
5
- "type": "module",
6
- "license": "MIT",
7
- "sideEffects": false,
8
- "main": "./dist/index.js",
9
- "types": "./dist/index.d.ts",
10
- "exports": {
11
- ".": {
12
- "types": "./dist/index.d.ts",
13
- "import": "./dist/index.js"
14
- }
15
- },
16
- "files": [
17
- "dist",
18
- "README.md"
19
- ],
20
- "scripts": {
21
- "build": "tsc -p tsconfig.json",
22
- "test": "tsc -p tsconfig.json --noEmit && npm run test:functional",
23
- "test:functional": "npm run build && node --test test/*.test.mjs",
24
- "lint": "tsc -p tsconfig.json --noEmit"
25
- },
26
- "publishConfig": {
27
- "access": "public"
28
- },
29
- "dependencies": {
30
- "@aws-sdk/client-s3": "^3.806.0",
31
- "@aws-sdk/s3-request-presigner": "^3.806.0"
32
- },
33
- "devDependencies": {
34
- "typescript": "^5.5.0"
35
- }
2
+ "name": "@beam-network/sdk",
3
+ "version": "0.2.16",
4
+ "description": "TypeScript SDK for BEAM transfer creation and management.",
5
+ "type": "module",
6
+ "license": "MIT",
7
+ "sideEffects": false,
8
+ "main": "./dist/index.js",
9
+ "types": "./dist/index.d.ts",
10
+ "exports": {
11
+ ".": {
12
+ "types": "./dist/index.d.ts",
13
+ "import": "./dist/index.js"
14
+ }
15
+ },
16
+ "files": [
17
+ "dist",
18
+ "README.md"
19
+ ],
20
+ "scripts": {
21
+ "build": "tsc -p tsconfig.json",
22
+ "test": "tsc -p tsconfig.json --noEmit \u0026\u0026 npm run test:functional",
23
+ "test:functional": "npm run build \u0026\u0026 node --test test/client.functional.test.mjs",
24
+ "lint": "tsc -p tsconfig.json --noEmit"
25
+ },
26
+ "publishConfig": {
27
+ "access": "public"
28
+ },
29
+ "dependencies": {
30
+ "@aws-sdk/client-s3": "^3.806.0",
31
+ "@aws-sdk/s3-request-presigner": "^3.806.0",
32
+ "@msgpack/msgpack": "^3.0.0",
33
+ "nats": "^2.29.3"
34
+ },
35
+ "devDependencies": {
36
+ "typescript": "^5.5.0"
37
+ }
36
38
  }