@edgestore/sdk 1.0.0-next.1 → 1.0.0-next.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/errors.d.ts +17 -0
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +15 -1
- package/dist/generated/api-v2.d.ts +71 -26
- package/dist/generated/api-v2.d.ts.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/internal/managementUploadOperations.d.ts +64 -0
- package/dist/internal/managementUploadOperations.d.ts.map +1 -0
- package/dist/internal/managementUploadOperations.js +72 -0
- package/dist/internal/multipartUpload.d.ts +6 -6
- package/dist/internal/multipartUpload.d.ts.map +1 -1
- package/dist/internal/runtimeOperations.d.ts.map +1 -1
- package/dist/internal/transport.d.ts.map +1 -1
- package/dist/internal/transport.js +20 -7
- package/dist/internal/uploadLifecycle.d.ts +57 -0
- package/dist/internal/uploadLifecycle.d.ts.map +1 -0
- package/dist/internal/uploadLifecycle.js +91 -0
- package/dist/internal/uploadProcessing.d.ts +20 -0
- package/dist/internal/uploadProcessing.d.ts.map +1 -0
- package/dist/internal/uploadProcessing.js +25 -0
- package/dist/internal/uploadSource.d.ts +18 -0
- package/dist/internal/uploadSource.d.ts.map +1 -0
- package/dist/internal/uploadSource.js +75 -0
- package/dist/internal/uploadTransfer.js +15 -1
- package/dist/managementClient.d.ts +2 -1
- package/dist/managementClient.d.ts.map +1 -1
- package/dist/managementClient.js +2 -2
- package/dist/managementResources.d.ts +5 -1
- package/dist/managementResources.d.ts.map +1 -1
- package/dist/managementResources.js +14 -49
- package/dist/managementUpload.d.ts +36 -0
- package/dist/managementUpload.d.ts.map +1 -0
- package/dist/managementUpload.js +74 -0
- package/dist/sdk.js +1 -1
- package/dist/upload.d.ts.map +1 -1
- package/dist/upload.js +42 -189
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +2 -2
- package/src/errors.ts +28 -0
- package/src/generated/api-v2.ts +71 -26
- package/src/generated/openapi-v2.json +237 -16
- package/src/generated/source.ts +2 -2
- package/src/index.ts +6 -0
- package/src/internal/managementUploadOperations.ts +99 -0
- package/src/internal/multipartUpload.ts +8 -8
- package/src/internal/transport.ts +21 -12
- package/src/internal/uploadLifecycle.ts +154 -0
- package/src/internal/uploadProcessing.ts +48 -0
- package/src/internal/uploadSource.ts +104 -0
- package/src/internal/uploadTransfer.ts +20 -1
- package/src/managementClient.ts +6 -2
- package/src/managementResources.ts +21 -51
- package/src/managementUpload.ts +139 -0
- package/src/sdk.ts +1 -1
- package/src/upload.ts +49 -274
- package/src/version.ts +1 -1
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import type { ManagementUploadOperations } from './internal/managementUploadOperations';
|
|
2
|
+
import type { OperationBody, OperationResult } from './internal/operationTypes';
|
|
3
|
+
import type { Transport } from './internal/transport';
|
|
4
|
+
import { executeUploadLifecycle } from './internal/uploadLifecycle';
|
|
5
|
+
import { throwIfAborted } from './internal/uploadRetry';
|
|
6
|
+
import {
|
|
7
|
+
normalizeUploadMetadata,
|
|
8
|
+
prepareUploadSource,
|
|
9
|
+
reportUploadProgress,
|
|
10
|
+
} from './internal/uploadSource';
|
|
11
|
+
import { assertNonNegative } from './internal/uploadValidation';
|
|
12
|
+
import { planMultipartUpload } from './multipartPlan';
|
|
13
|
+
import type {
|
|
14
|
+
UploadDefaults,
|
|
15
|
+
UploadMetadataValue,
|
|
16
|
+
UploadProgress,
|
|
17
|
+
UploadSource,
|
|
18
|
+
} from './uploadTypes';
|
|
19
|
+
import { DEFAULT_PROCESSING_TIMEOUT_MS } from './uploadTypes';
|
|
20
|
+
|
|
21
|
+
type RequestBody = OperationBody<'v2.management.uploads.request'>;
|
|
22
|
+
type RequestResult = OperationResult<'v2.management.uploads.request'>;
|
|
23
|
+
type GetResult = OperationResult<'v2.management.uploads.get'>;
|
|
24
|
+
type CompletedUpload = Extract<GetResult, { upload: { status: 'completed' } }>;
|
|
25
|
+
|
|
26
|
+
/** Input for a complete administrative upload managed by the SDK. */
|
|
27
|
+
export type ManagementUploadInput = Omit<
|
|
28
|
+
RequestBody,
|
|
29
|
+
'sizeBytes' | 'metadata' | 'multipart'
|
|
30
|
+
> & {
|
|
31
|
+
project: string;
|
|
32
|
+
bucket: string;
|
|
33
|
+
source: UploadSource;
|
|
34
|
+
metadata?: Record<string, UploadMetadataValue>;
|
|
35
|
+
signal?: AbortSignal;
|
|
36
|
+
onProgress?: (progress: UploadProgress) => void;
|
|
37
|
+
multipart?:
|
|
38
|
+
| boolean
|
|
39
|
+
| {
|
|
40
|
+
partSizeBytes?: number;
|
|
41
|
+
concurrency?: number;
|
|
42
|
+
};
|
|
43
|
+
processingTimeoutMs?: number;
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
/** Completed administrative file upload. */
|
|
47
|
+
export type ManagementUploadResult = CompletedUpload & {
|
|
48
|
+
signedReadUrl?: RequestResult['signedReadUrl'];
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
export async function uploadManagementFile(
|
|
52
|
+
context: {
|
|
53
|
+
transport: Transport;
|
|
54
|
+
operations: ManagementUploadOperations;
|
|
55
|
+
},
|
|
56
|
+
input: ManagementUploadInput,
|
|
57
|
+
defaults: UploadDefaults = {},
|
|
58
|
+
): Promise<ManagementUploadResult> {
|
|
59
|
+
const { transport, operations } = context;
|
|
60
|
+
const {
|
|
61
|
+
project,
|
|
62
|
+
bucket,
|
|
63
|
+
source,
|
|
64
|
+
metadata,
|
|
65
|
+
signal,
|
|
66
|
+
onProgress,
|
|
67
|
+
multipart,
|
|
68
|
+
processingTimeoutMs = defaults.processingTimeoutMs ??
|
|
69
|
+
DEFAULT_PROCESSING_TIMEOUT_MS,
|
|
70
|
+
...requestInput
|
|
71
|
+
} = input;
|
|
72
|
+
const prepared = prepareUploadSource(source);
|
|
73
|
+
const totalBytes = prepared.sizeBytes;
|
|
74
|
+
assertNonNegative(processingTimeoutMs, 'processingTimeoutMs');
|
|
75
|
+
throwIfAborted(signal);
|
|
76
|
+
reportUploadProgress(onProgress, {
|
|
77
|
+
transferredBytes: 0,
|
|
78
|
+
totalBytes,
|
|
79
|
+
phase: 'preparing',
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
const multipartPlan = planMultipartUpload({
|
|
83
|
+
sizeBytes: totalBytes,
|
|
84
|
+
thresholdBytes: defaults.multipartThresholdBytes,
|
|
85
|
+
preferredPartSizeBytes:
|
|
86
|
+
typeof multipart === 'object'
|
|
87
|
+
? (multipart.partSizeBytes ?? defaults.multipartPartSizeBytes)
|
|
88
|
+
: defaults.multipartPartSizeBytes,
|
|
89
|
+
forceMultipart:
|
|
90
|
+
prepared.kind === 'stream' ||
|
|
91
|
+
multipart === true ||
|
|
92
|
+
typeof multipart === 'object',
|
|
93
|
+
});
|
|
94
|
+
const requested = await operations.request({
|
|
95
|
+
project,
|
|
96
|
+
bucket,
|
|
97
|
+
signal,
|
|
98
|
+
...requestInput,
|
|
99
|
+
fileName: requestInput.fileName ?? prepared.fileName,
|
|
100
|
+
mimeType: requestInput.mimeType ?? prepared.mimeType,
|
|
101
|
+
sizeBytes: totalBytes,
|
|
102
|
+
metadata: normalizeUploadMetadata(metadata),
|
|
103
|
+
multipart: multipartPlan
|
|
104
|
+
? { partNumbers: multipartPlan.partNumbers }
|
|
105
|
+
: undefined,
|
|
106
|
+
});
|
|
107
|
+
const completed = await executeUploadLifecycle<GetResult>({
|
|
108
|
+
transport,
|
|
109
|
+
requested,
|
|
110
|
+
prepared,
|
|
111
|
+
multipartPlan,
|
|
112
|
+
multipartConcurrency:
|
|
113
|
+
typeof multipart === 'object'
|
|
114
|
+
? multipart.concurrency
|
|
115
|
+
: defaults.multipartConcurrency,
|
|
116
|
+
defaultMultipartConcurrency: defaults.multipartConcurrency,
|
|
117
|
+
processingTimeoutMs,
|
|
118
|
+
signal,
|
|
119
|
+
onProgress,
|
|
120
|
+
operations: {
|
|
121
|
+
completeMultipart: ({ uploadId, parts, signal: requestSignal }) =>
|
|
122
|
+
operations.completeMultipart({
|
|
123
|
+
project,
|
|
124
|
+
uploadId,
|
|
125
|
+
parts,
|
|
126
|
+
signal: requestSignal,
|
|
127
|
+
}),
|
|
128
|
+
get: ({ uploadId, signal: requestSignal }) =>
|
|
129
|
+
operations.getWithResponse({
|
|
130
|
+
project,
|
|
131
|
+
uploadId,
|
|
132
|
+
signal: requestSignal,
|
|
133
|
+
}),
|
|
134
|
+
cancel: ({ uploadId }) => operations.cancel({ project, uploadId }),
|
|
135
|
+
},
|
|
136
|
+
cleanupPolicy: 'report-failure',
|
|
137
|
+
});
|
|
138
|
+
return { ...completed, signedReadUrl: requested.signedReadUrl };
|
|
139
|
+
}
|
package/src/sdk.ts
CHANGED
|
@@ -80,7 +80,7 @@ export function createEdgeStoreSdk(
|
|
|
80
80
|
return credentials.kind === 'bearer'
|
|
81
81
|
? {
|
|
82
82
|
runtime: createExplicitProjectRuntimeClient(transport, options.upload),
|
|
83
|
-
management: createManagementClient(transport),
|
|
83
|
+
management: createManagementClient(transport, options.upload),
|
|
84
84
|
system,
|
|
85
85
|
}
|
|
86
86
|
: {
|
package/src/upload.ts
CHANGED
|
@@ -1,39 +1,25 @@
|
|
|
1
|
-
import {
|
|
2
|
-
EdgeStoreAbortError,
|
|
3
|
-
EdgeStoreNetworkError,
|
|
4
|
-
EdgeStoreUploadCanceledError,
|
|
5
|
-
EdgeStoreUploadProcessingTimeoutError,
|
|
6
|
-
} from './errors';
|
|
7
|
-
import { uploadParts, uploadStreamParts } from './internal/multipartUpload';
|
|
1
|
+
import { EdgeStoreAbortError, EdgeStoreNetworkError } from './errors';
|
|
8
2
|
import {
|
|
9
3
|
createGetUploadRequest,
|
|
10
4
|
type RuntimeOperations,
|
|
11
5
|
} from './internal/runtimeOperations';
|
|
12
6
|
import type { Transport } from './internal/transport';
|
|
7
|
+
import { executeUploadLifecycle } from './internal/uploadLifecycle';
|
|
8
|
+
import { isAbortError, throwIfAborted } from './internal/uploadRetry';
|
|
13
9
|
import {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
} from './internal/uploadRetry';
|
|
20
|
-
import { putWithRetry } from './internal/uploadTransfer';
|
|
21
|
-
import {
|
|
22
|
-
assertNonNegative,
|
|
23
|
-
getPositiveInteger,
|
|
24
|
-
} from './internal/uploadValidation';
|
|
10
|
+
normalizeUploadMetadata,
|
|
11
|
+
prepareUploadSource,
|
|
12
|
+
reportUploadProgress,
|
|
13
|
+
} from './internal/uploadSource';
|
|
14
|
+
import { assertNonNegative } from './internal/uploadValidation';
|
|
25
15
|
import { planMultipartUpload } from './multipartPlan';
|
|
26
16
|
import {
|
|
27
|
-
DEFAULT_MULTIPART_CONCURRENCY,
|
|
28
17
|
DEFAULT_PROCESSING_TIMEOUT_MS,
|
|
29
|
-
type CompletedUpload,
|
|
30
18
|
type RuntimeUploadFromUrlInput,
|
|
31
19
|
type RuntimeUploadInput,
|
|
32
20
|
type RuntimeUploadResult,
|
|
33
21
|
type UploadDefaults,
|
|
34
|
-
type UploadMetadataValue,
|
|
35
22
|
type UploadSource,
|
|
36
|
-
type UploadStreamSource,
|
|
37
23
|
} from './uploadTypes';
|
|
38
24
|
|
|
39
25
|
type ExplicitUploadInput = RuntimeUploadInput & { project: string };
|
|
@@ -41,17 +27,6 @@ type ExplicitUploadFromUrlInput = RuntimeUploadFromUrlInput & {
|
|
|
41
27
|
project: string;
|
|
42
28
|
};
|
|
43
29
|
|
|
44
|
-
type PreparedUploadDetails = {
|
|
45
|
-
sizeBytes: number;
|
|
46
|
-
fileName?: string;
|
|
47
|
-
mimeType?: string;
|
|
48
|
-
};
|
|
49
|
-
type PreparedUploadSource =
|
|
50
|
-
| (PreparedUploadDetails & { kind: 'body'; body: Blob })
|
|
51
|
-
| (PreparedUploadDetails & {
|
|
52
|
-
kind: 'stream';
|
|
53
|
-
stream: ReadableStream<Uint8Array>;
|
|
54
|
-
});
|
|
55
30
|
type UploadContext = {
|
|
56
31
|
transport: Transport;
|
|
57
32
|
operations: RuntimeOperations;
|
|
@@ -81,12 +56,12 @@ export async function uploadRuntimeFile(
|
|
|
81
56
|
processingTimeoutMs = defaults.processingTimeoutMs ??
|
|
82
57
|
DEFAULT_PROCESSING_TIMEOUT_MS,
|
|
83
58
|
} = input;
|
|
84
|
-
const prepared =
|
|
59
|
+
const prepared = prepareUploadSource(source);
|
|
85
60
|
const totalBytes = prepared.sizeBytes;
|
|
86
61
|
assertNonNegative(processingTimeoutMs, 'processingTimeoutMs');
|
|
87
62
|
|
|
88
63
|
throwIfAborted(signal);
|
|
89
|
-
|
|
64
|
+
reportUploadProgress(onProgress, {
|
|
90
65
|
transferredBytes: 0,
|
|
91
66
|
totalBytes,
|
|
92
67
|
phase: 'preparing',
|
|
@@ -123,101 +98,51 @@ export async function uploadRuntimeFile(
|
|
|
123
98
|
temporary,
|
|
124
99
|
path,
|
|
125
100
|
extension,
|
|
126
|
-
metadata:
|
|
101
|
+
metadata: normalizeUploadMetadata(metadata),
|
|
127
102
|
replaceTarget,
|
|
128
103
|
multipart: partNumbers ? { partNumbers } : undefined,
|
|
129
104
|
signedReadUrl,
|
|
130
105
|
signal,
|
|
131
106
|
});
|
|
132
|
-
const
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
)
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
? multipart.concurrency
|
|
167
|
-
: defaults.multipartConcurrency,
|
|
168
|
-
defaults.multipartConcurrency ?? DEFAULT_MULTIPART_CONCURRENCY,
|
|
169
|
-
'multipart.concurrency',
|
|
170
|
-
);
|
|
171
|
-
const transferOptions = {
|
|
172
|
-
uploadId,
|
|
173
|
-
parts: requested.upload.parts,
|
|
174
|
-
partSizeBytes: multipartPlan.partSizeBytes,
|
|
175
|
-
signal,
|
|
176
|
-
onProgress,
|
|
177
|
-
};
|
|
178
|
-
const completedParts =
|
|
179
|
-
prepared.kind === 'stream'
|
|
180
|
-
? await uploadStreamParts(transport, {
|
|
181
|
-
...transferOptions,
|
|
182
|
-
stream: prepared.stream,
|
|
183
|
-
totalBytes,
|
|
184
|
-
})
|
|
185
|
-
: await uploadParts(transport, {
|
|
186
|
-
...transferOptions,
|
|
187
|
-
body: prepared.body,
|
|
188
|
-
concurrency,
|
|
189
|
-
});
|
|
190
|
-
await operations.uploads.completeMultipart({
|
|
191
|
-
project,
|
|
192
|
-
uploadId,
|
|
193
|
-
parts: completedParts,
|
|
194
|
-
signal,
|
|
195
|
-
});
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
reportProgress(onProgress, {
|
|
199
|
-
transferredBytes: totalBytes,
|
|
200
|
-
totalBytes,
|
|
201
|
-
phase: 'processing',
|
|
202
|
-
});
|
|
203
|
-
|
|
204
|
-
const completed = await waitForUpload(context, {
|
|
205
|
-
project,
|
|
206
|
-
uploadId,
|
|
207
|
-
signal,
|
|
208
|
-
timeoutMs: processingTimeoutMs,
|
|
209
|
-
});
|
|
107
|
+
const completed = await executeUploadLifecycle({
|
|
108
|
+
transport,
|
|
109
|
+
requested,
|
|
110
|
+
prepared,
|
|
111
|
+
multipartPlan,
|
|
112
|
+
multipartConcurrency:
|
|
113
|
+
typeof multipart === 'object'
|
|
114
|
+
? multipart.concurrency
|
|
115
|
+
: defaults.multipartConcurrency,
|
|
116
|
+
defaultMultipartConcurrency: defaults.multipartConcurrency,
|
|
117
|
+
processingTimeoutMs,
|
|
118
|
+
signal,
|
|
119
|
+
onProgress,
|
|
120
|
+
operations: {
|
|
121
|
+
completeMultipart: ({ uploadId, parts, signal: requestSignal }) =>
|
|
122
|
+
operations.uploads.completeMultipart({
|
|
123
|
+
project,
|
|
124
|
+
uploadId,
|
|
125
|
+
parts,
|
|
126
|
+
signal: requestSignal,
|
|
127
|
+
}),
|
|
128
|
+
get: ({ uploadId, signal: requestSignal }) =>
|
|
129
|
+
context.transport.executeWithResponse(
|
|
130
|
+
createGetUploadRequest({
|
|
131
|
+
project,
|
|
132
|
+
uploadId,
|
|
133
|
+
signal: requestSignal,
|
|
134
|
+
}),
|
|
135
|
+
),
|
|
136
|
+
cancel: ({ uploadId }) =>
|
|
137
|
+
operations.uploads.cancel({ project, uploadId }),
|
|
138
|
+
},
|
|
139
|
+
cleanupPolicy: 'preserve-original',
|
|
140
|
+
});
|
|
210
141
|
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
} catch (error) {
|
|
216
|
-
if (!(error instanceof EdgeStoreUploadProcessingTimeoutError)) {
|
|
217
|
-
await cancelUpload(operations, project, uploadId);
|
|
218
|
-
}
|
|
219
|
-
throw error;
|
|
220
|
-
}
|
|
142
|
+
return {
|
|
143
|
+
...completed,
|
|
144
|
+
signedReadUrl: requested.signedReadUrl,
|
|
145
|
+
};
|
|
221
146
|
}
|
|
222
147
|
|
|
223
148
|
export async function uploadRuntimeFileFromUrl(
|
|
@@ -303,156 +228,6 @@ async function cancelResponseBody(
|
|
|
303
228
|
await body.cancel().catch(() => undefined);
|
|
304
229
|
}
|
|
305
230
|
|
|
306
|
-
async function waitForUpload(
|
|
307
|
-
context: UploadContext,
|
|
308
|
-
options: {
|
|
309
|
-
project: string;
|
|
310
|
-
uploadId: string;
|
|
311
|
-
signal?: AbortSignal;
|
|
312
|
-
timeoutMs: number;
|
|
313
|
-
},
|
|
314
|
-
): Promise<CompletedUpload> {
|
|
315
|
-
const deadline = Date.now() + options.timeoutMs;
|
|
316
|
-
const timeoutError = () =>
|
|
317
|
-
new EdgeStoreUploadProcessingTimeoutError(
|
|
318
|
-
'Timed out while EdgeStore was processing the upload.',
|
|
319
|
-
options.uploadId,
|
|
320
|
-
);
|
|
321
|
-
|
|
322
|
-
while (true) {
|
|
323
|
-
const { data, response } = await retryOperation(
|
|
324
|
-
(signal) =>
|
|
325
|
-
context.transport.executeWithResponse(
|
|
326
|
-
createGetUploadRequest({
|
|
327
|
-
project: options.project,
|
|
328
|
-
uploadId: options.uploadId,
|
|
329
|
-
signal,
|
|
330
|
-
}),
|
|
331
|
-
),
|
|
332
|
-
{
|
|
333
|
-
signal: options.signal,
|
|
334
|
-
deadline,
|
|
335
|
-
timeoutError,
|
|
336
|
-
},
|
|
337
|
-
);
|
|
338
|
-
|
|
339
|
-
if (data.upload.status === 'completed' && 'file' in data) return data;
|
|
340
|
-
if (data.upload.status === 'canceled') {
|
|
341
|
-
throw new EdgeStoreUploadCanceledError(
|
|
342
|
-
'The EdgeStore upload was canceled.',
|
|
343
|
-
options.uploadId,
|
|
344
|
-
);
|
|
345
|
-
}
|
|
346
|
-
|
|
347
|
-
const delayMs = getRetryAfterMs(response) ?? 1000;
|
|
348
|
-
if (Date.now() + delayMs > deadline) {
|
|
349
|
-
throw timeoutError();
|
|
350
|
-
}
|
|
351
|
-
await sleep(delayMs, options.signal);
|
|
352
|
-
}
|
|
353
|
-
}
|
|
354
|
-
|
|
355
|
-
async function cancelUpload(
|
|
356
|
-
operations: RuntimeOperations,
|
|
357
|
-
project: string,
|
|
358
|
-
uploadId: string,
|
|
359
|
-
) {
|
|
360
|
-
try {
|
|
361
|
-
await operations.uploads.cancel({ project, uploadId });
|
|
362
|
-
} catch {
|
|
363
|
-
// Preserve the original upload failure.
|
|
364
|
-
}
|
|
365
|
-
}
|
|
366
|
-
|
|
367
|
-
function normalizeMetadata(
|
|
368
|
-
metadata?: Record<string, UploadMetadataValue>,
|
|
369
|
-
): Record<string, string> | undefined {
|
|
370
|
-
if (!metadata) return undefined;
|
|
371
|
-
const entries = Object.entries(metadata).flatMap(([key, value]) =>
|
|
372
|
-
value === null || value === undefined ? [] : [[key, String(value)]],
|
|
373
|
-
);
|
|
374
|
-
return entries.length ? Object.fromEntries(entries) : undefined;
|
|
375
|
-
}
|
|
376
|
-
|
|
377
|
-
function prepareSource(source: UploadSource): PreparedUploadSource {
|
|
378
|
-
if (typeof source === 'string') {
|
|
379
|
-
const body = new Blob([source], { type: 'text/plain' });
|
|
380
|
-
return {
|
|
381
|
-
kind: 'body',
|
|
382
|
-
body,
|
|
383
|
-
sizeBytes: body.size,
|
|
384
|
-
mimeType: body.type,
|
|
385
|
-
};
|
|
386
|
-
}
|
|
387
|
-
if (isStreamSource(source)) {
|
|
388
|
-
if (!Number.isSafeInteger(source.sizeBytes) || source.sizeBytes < 0) {
|
|
389
|
-
throw new RangeError('source.sizeBytes must be a non-negative integer.');
|
|
390
|
-
}
|
|
391
|
-
return {
|
|
392
|
-
kind: 'stream',
|
|
393
|
-
stream: source.stream,
|
|
394
|
-
sizeBytes: source.sizeBytes,
|
|
395
|
-
};
|
|
396
|
-
}
|
|
397
|
-
if (source instanceof Blob) {
|
|
398
|
-
return {
|
|
399
|
-
kind: 'body',
|
|
400
|
-
body: source,
|
|
401
|
-
sizeBytes: source.size,
|
|
402
|
-
fileName:
|
|
403
|
-
'name' in source && typeof source.name === 'string'
|
|
404
|
-
? source.name
|
|
405
|
-
: undefined,
|
|
406
|
-
mimeType: source.type || undefined,
|
|
407
|
-
};
|
|
408
|
-
}
|
|
409
|
-
if (source instanceof ArrayBuffer) {
|
|
410
|
-
const body = new Blob([source]);
|
|
411
|
-
return { kind: 'body', body, sizeBytes: body.size };
|
|
412
|
-
}
|
|
413
|
-
const body = new Blob([
|
|
414
|
-
Uint8Array.from(
|
|
415
|
-
new Uint8Array(source.buffer, source.byteOffset, source.byteLength),
|
|
416
|
-
),
|
|
417
|
-
]);
|
|
418
|
-
return { kind: 'body', body, sizeBytes: body.size };
|
|
419
|
-
}
|
|
420
|
-
|
|
421
|
-
function isStreamSource(source: UploadSource): source is UploadStreamSource {
|
|
422
|
-
const stream =
|
|
423
|
-
typeof source === 'object' && source !== null && 'stream' in source
|
|
424
|
-
? Reflect.get(source, 'stream')
|
|
425
|
-
: undefined;
|
|
426
|
-
return (
|
|
427
|
-
typeof stream === 'object' &&
|
|
428
|
-
stream !== null &&
|
|
429
|
-
'getReader' in stream &&
|
|
430
|
-
typeof Reflect.get(stream, 'getReader') === 'function'
|
|
431
|
-
);
|
|
432
|
-
}
|
|
433
|
-
|
|
434
|
-
function reportProgress(
|
|
435
|
-
onProgress: RuntimeUploadInput['onProgress'],
|
|
436
|
-
progress: {
|
|
437
|
-
transferredBytes: number;
|
|
438
|
-
totalBytes: number;
|
|
439
|
-
phase: 'preparing' | 'uploading' | 'processing';
|
|
440
|
-
},
|
|
441
|
-
) {
|
|
442
|
-
const { transferredBytes, totalBytes, phase } = progress;
|
|
443
|
-
onProgress?.({
|
|
444
|
-
transferredBytes,
|
|
445
|
-
totalBytes,
|
|
446
|
-
percentage:
|
|
447
|
-
totalBytes === 0
|
|
448
|
-
? phase === 'preparing'
|
|
449
|
-
? 0
|
|
450
|
-
: 100
|
|
451
|
-
: Math.round((transferredBytes / totalBytes) * 10_000) / 100,
|
|
452
|
-
phase,
|
|
453
|
-
});
|
|
454
|
-
}
|
|
455
|
-
|
|
456
231
|
function getFileNameFromUrl(url: string): string | undefined {
|
|
457
232
|
const name = new URL(url).pathname.split('/').filter(Boolean).at(-1);
|
|
458
233
|
return name ? decodeURIComponent(name) : undefined;
|
package/src/version.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export const EDGE_STORE_PACKAGE_NAME = '@edgestore/sdk';
|
|
2
|
-
export const EDGE_STORE_PACKAGE_VERSION = '1.0.0-next.
|
|
2
|
+
export const EDGE_STORE_PACKAGE_VERSION = '1.0.0-next.2';
|