1 | import { __asyncDelegator, __asyncGenerator, __asyncValues, __await } from "tslib";
|
2 | import { getDefaultProxySettings, isNode, isTokenCredential, URLBuilder, } from "@azure/core-http";
|
3 | import { SpanStatusCode } from "@azure/core-tracing";
|
4 | import { AnonymousCredential } from "./credentials/AnonymousCredential";
|
5 | import { StorageSharedKeyCredential } from "./credentials/StorageSharedKeyCredential";
|
6 | import { Container } from "./generated/src/operations";
|
7 | import { newPipeline, isPipelineLike } from "./Pipeline";
|
8 | import { StorageClient } from "./StorageClient";
|
9 | import { convertTracingToRequestOptionsBase, createSpan } from "./utils/tracing";
|
10 | import { appendToURLPath, appendToURLQuery, BlobNameToString, ConvertInternalResponseOfListBlobFlat, ConvertInternalResponseOfListBlobHierarchy, extractConnectionStringParts, isIpEndpointStyle, parseObjectReplicationRecord, ProcessBlobItems, ProcessBlobPrefixes, toTags, truncatedISO8061Date, } from "./utils/utils.common";
|
11 | import { generateBlobSASQueryParameters } from "./sas/BlobSASSignatureValues";
|
12 | import { BlobLeaseClient } from "./BlobLeaseClient";
|
13 | import { AppendBlobClient, BlobClient, BlockBlobClient, PageBlobClient, } from "./Clients";
|
14 | import { BlobBatchClient } from "./BlobBatchClient";
|
15 | /**
|
16 | * A ContainerClient represents a URL to the Azure Storage container allowing you to manipulate its blobs.
|
17 | */
|
18 | export class ContainerClient extends StorageClient {
|
19 | constructor(urlOrConnectionString, credentialOrPipelineOrContainerName,
|
20 | // Legacy, no fix for eslint error without breaking. Disable it for this interface.
|
21 | /* eslint-disable-next-line @azure/azure-sdk/ts-naming-options*/
|
22 | options) {
|
23 | let pipeline;
|
24 | let url;
|
25 | options = options || {};
|
26 | if (isPipelineLike(credentialOrPipelineOrContainerName)) {
|
27 | // (url: string, pipeline: Pipeline)
|
28 | url = urlOrConnectionString;
|
29 | pipeline = credentialOrPipelineOrContainerName;
|
30 | }
|
31 | else if ((isNode && credentialOrPipelineOrContainerName instanceof StorageSharedKeyCredential) ||
|
32 | credentialOrPipelineOrContainerName instanceof AnonymousCredential ||
|
33 | isTokenCredential(credentialOrPipelineOrContainerName)) {
|
34 | // (url: string, credential?: StorageSharedKeyCredential | AnonymousCredential | TokenCredential, options?: StoragePipelineOptions)
|
35 | url = urlOrConnectionString;
|
36 | pipeline = newPipeline(credentialOrPipelineOrContainerName, options);
|
37 | }
|
38 | else if (!credentialOrPipelineOrContainerName &&
|
39 | typeof credentialOrPipelineOrContainerName !== "string") {
|
40 | // (url: string, credential?: StorageSharedKeyCredential | AnonymousCredential | TokenCredential, options?: StoragePipelineOptions)
|
41 | // The second parameter is undefined. Use anonymous credential.
|
42 | url = urlOrConnectionString;
|
43 | pipeline = newPipeline(new AnonymousCredential(), options);
|
44 | }
|
45 | else if (credentialOrPipelineOrContainerName &&
|
46 | typeof credentialOrPipelineOrContainerName === "string") {
|
47 | // (connectionString: string, containerName: string, blobName: string, options?: StoragePipelineOptions)
|
48 | const containerName = credentialOrPipelineOrContainerName;
|
49 | const extractedCreds = extractConnectionStringParts(urlOrConnectionString);
|
50 | if (extractedCreds.kind === "AccountConnString") {
|
51 | if (isNode) {
|
52 | const sharedKeyCredential = new StorageSharedKeyCredential(extractedCreds.accountName, extractedCreds.accountKey);
|
53 | url = appendToURLPath(extractedCreds.url, encodeURIComponent(containerName));
|
54 | if (!options.proxyOptions) {
|
55 | options.proxyOptions = getDefaultProxySettings(extractedCreds.proxyUri);
|
56 | }
|
57 | pipeline = newPipeline(sharedKeyCredential, options);
|
58 | }
|
59 | else {
|
60 | throw new Error("Account connection string is only supported in Node.js environment");
|
61 | }
|
62 | }
|
63 | else if (extractedCreds.kind === "SASConnString") {
|
64 | url =
|
65 | appendToURLPath(extractedCreds.url, encodeURIComponent(containerName)) +
|
66 | "?" +
|
67 | extractedCreds.accountSas;
|
68 | pipeline = newPipeline(new AnonymousCredential(), options);
|
69 | }
|
70 | else {
|
71 | throw new Error("Connection string must be either an Account connection string or a SAS connection string");
|
72 | }
|
73 | }
|
74 | else {
|
75 | throw new Error("Expecting non-empty strings for containerName parameter");
|
76 | }
|
77 | super(url, pipeline);
|
78 | this._containerName = this.getContainerNameFromUrl();
|
79 | this.containerContext = new Container(this.storageClientContext);
|
80 | }
|
81 | /**
|
82 | * The name of the container.
|
83 | */
|
84 | get containerName() {
|
85 | return this._containerName;
|
86 | }
|
87 | /**
|
88 | * Creates a new container under the specified account. If the container with
|
89 | * the same name already exists, the operation fails.
|
90 | * @see https://docs.microsoft.com/en-us/rest/api/storageservices/create-container
|
91 | *
|
92 | * @param options - Options to Container Create operation.
|
93 | *
|
94 | *
|
95 | * Example usage:
|
96 | *
|
97 | * ```js
|
98 | * const containerClient = blobServiceClient.getContainerClient("<container name>");
|
99 | * const createContainerResponse = await containerClient.create();
|
100 | * console.log("Container was created successfully", createContainerResponse.requestId);
|
101 | * ```
|
102 | */
|
103 | async create(options = {}) {
|
104 | const { span, updatedOptions } = createSpan("ContainerClient-create", options);
|
105 | try {
|
106 | // Spread operator in destructuring assignments,
|
107 | // this will filter out unwanted properties from the response object into result object
|
108 | return await this.containerContext.create(Object.assign(Object.assign({}, options), convertTracingToRequestOptionsBase(updatedOptions)));
|
109 | }
|
110 | catch (e) {
|
111 | span.setStatus({
|
112 | code: SpanStatusCode.ERROR,
|
113 | message: e.message,
|
114 | });
|
115 | throw e;
|
116 | }
|
117 | finally {
|
118 | span.end();
|
119 | }
|
120 | }
|
121 | /**
|
122 | * Creates a new container under the specified account. If the container with
|
123 | * the same name already exists, it is not changed.
|
124 | * @see https://docs.microsoft.com/en-us/rest/api/storageservices/create-container
|
125 | *
|
126 | * @param options -
|
127 | */
|
128 | async createIfNotExists(options = {}) {
|
129 | var _a, _b;
|
130 | const { span, updatedOptions } = createSpan("ContainerClient-createIfNotExists", options);
|
131 | try {
|
132 | const res = await this.create(updatedOptions);
|
133 | return Object.assign(Object.assign({ succeeded: true }, res), { _response: res._response });
|
134 | }
|
135 | catch (e) {
|
136 | if (((_a = e.details) === null || _a === void 0 ? void 0 : _a.errorCode) === "ContainerAlreadyExists") {
|
137 | span.setStatus({
|
138 | code: SpanStatusCode.ERROR,
|
139 | message: "Expected exception when creating a container only if it does not already exist.",
|
140 | });
|
141 | return Object.assign(Object.assign({ succeeded: false }, (_b = e.response) === null || _b === void 0 ? void 0 : _b.parsedHeaders), { _response: e.response });
|
142 | }
|
143 | span.setStatus({
|
144 | code: SpanStatusCode.ERROR,
|
145 | message: e.message,
|
146 | });
|
147 | throw e;
|
148 | }
|
149 | finally {
|
150 | span.end();
|
151 | }
|
152 | }
|
153 | /**
|
154 | * Returns true if the Azure container resource represented by this client exists; false otherwise.
|
155 | *
|
156 | * NOTE: use this function with care since an existing container might be deleted by other clients or
|
157 | * applications. Vice versa new containers with the same name might be added by other clients or
|
158 | * applications after this function completes.
|
159 | *
|
160 | * @param options -
|
161 | */
|
162 | async exists(options = {}) {
|
163 | const { span, updatedOptions } = createSpan("ContainerClient-exists", options);
|
164 | try {
|
165 | await this.getProperties({
|
166 | abortSignal: options.abortSignal,
|
167 | tracingOptions: updatedOptions.tracingOptions,
|
168 | });
|
169 | return true;
|
170 | }
|
171 | catch (e) {
|
172 | if (e.statusCode === 404) {
|
173 | span.setStatus({
|
174 | code: SpanStatusCode.ERROR,
|
175 | message: "Expected exception when checking container existence",
|
176 | });
|
177 | return false;
|
178 | }
|
179 | span.setStatus({
|
180 | code: SpanStatusCode.ERROR,
|
181 | message: e.message,
|
182 | });
|
183 | throw e;
|
184 | }
|
185 | finally {
|
186 | span.end();
|
187 | }
|
188 | }
|
189 | /**
|
190 | * Creates a {@link BlobClient}
|
191 | *
|
192 | * @param blobName - A blob name
|
193 | * @returns A new BlobClient object for the given blob name.
|
194 | */
|
195 | getBlobClient(blobName) {
|
196 | return new BlobClient(appendToURLPath(this.url, encodeURIComponent(blobName)), this.pipeline);
|
197 | }
|
198 | /**
|
199 | * Creates an {@link AppendBlobClient}
|
200 | *
|
201 | * @param blobName - An append blob name
|
202 | */
|
203 | getAppendBlobClient(blobName) {
|
204 | return new AppendBlobClient(appendToURLPath(this.url, encodeURIComponent(blobName)), this.pipeline);
|
205 | }
|
206 | /**
|
207 | * Creates a {@link BlockBlobClient}
|
208 | *
|
209 | * @param blobName - A block blob name
|
210 | *
|
211 | *
|
212 | * Example usage:
|
213 | *
|
214 | * ```js
|
215 | * const content = "Hello world!";
|
216 | *
|
217 | * const blockBlobClient = containerClient.getBlockBlobClient("<blob name>");
|
218 | * const uploadBlobResponse = await blockBlobClient.upload(content, content.length);
|
219 | * ```
|
220 | */
|
221 | getBlockBlobClient(blobName) {
|
222 | return new BlockBlobClient(appendToURLPath(this.url, encodeURIComponent(blobName)), this.pipeline);
|
223 | }
|
224 | /**
|
225 | * Creates a {@link PageBlobClient}
|
226 | *
|
227 | * @param blobName - A page blob name
|
228 | */
|
229 | getPageBlobClient(blobName) {
|
230 | return new PageBlobClient(appendToURLPath(this.url, encodeURIComponent(blobName)), this.pipeline);
|
231 | }
|
232 | /**
|
233 | * Returns all user-defined metadata and system properties for the specified
|
234 | * container. The data returned does not include the container's list of blobs.
|
235 | * @see https://docs.microsoft.com/en-us/rest/api/storageservices/get-container-properties
|
236 | *
|
237 | * WARNING: The `metadata` object returned in the response will have its keys in lowercase, even if
|
238 | * they originally contained uppercase characters. This differs from the metadata keys returned by
|
239 | * the `listContainers` method of {@link BlobServiceClient} using the `includeMetadata` option, which
|
240 | * will retain their original casing.
|
241 | *
|
242 | * @param options - Options to Container Get Properties operation.
|
243 | */
|
244 | async getProperties(options = {}) {
|
245 | if (!options.conditions) {
|
246 | options.conditions = {};
|
247 | }
|
248 | const { span, updatedOptions } = createSpan("ContainerClient-getProperties", options);
|
249 | try {
|
250 | return await this.containerContext.getProperties(Object.assign(Object.assign({ abortSignal: options.abortSignal }, options.conditions), convertTracingToRequestOptionsBase(updatedOptions)));
|
251 | }
|
252 | catch (e) {
|
253 | span.setStatus({
|
254 | code: SpanStatusCode.ERROR,
|
255 | message: e.message,
|
256 | });
|
257 | throw e;
|
258 | }
|
259 | finally {
|
260 | span.end();
|
261 | }
|
262 | }
|
263 | /**
|
264 | * Marks the specified container for deletion. The container and any blobs
|
265 | * contained within it are later deleted during garbage collection.
|
266 | * @see https://docs.microsoft.com/en-us/rest/api/storageservices/delete-container
|
267 | *
|
268 | * @param options - Options to Container Delete operation.
|
269 | */
|
270 | async delete(options = {}) {
|
271 | if (!options.conditions) {
|
272 | options.conditions = {};
|
273 | }
|
274 | const { span, updatedOptions } = createSpan("ContainerClient-delete", options);
|
275 | try {
|
276 | return await this.containerContext.delete(Object.assign({ abortSignal: options.abortSignal, leaseAccessConditions: options.conditions, modifiedAccessConditions: options.conditions }, convertTracingToRequestOptionsBase(updatedOptions)));
|
277 | }
|
278 | catch (e) {
|
279 | span.setStatus({
|
280 | code: SpanStatusCode.ERROR,
|
281 | message: e.message,
|
282 | });
|
283 | throw e;
|
284 | }
|
285 | finally {
|
286 | span.end();
|
287 | }
|
288 | }
|
289 | /**
|
290 | * Marks the specified container for deletion if it exists. The container and any blobs
|
291 | * contained within it are later deleted during garbage collection.
|
292 | * @see https://docs.microsoft.com/en-us/rest/api/storageservices/delete-container
|
293 | *
|
294 | * @param options - Options to Container Delete operation.
|
295 | */
|
296 | async deleteIfExists(options = {}) {
|
297 | var _a, _b;
|
298 | const { span, updatedOptions } = createSpan("ContainerClient-deleteIfExists", options);
|
299 | try {
|
300 | const res = await this.delete(updatedOptions);
|
301 | return Object.assign(Object.assign({ succeeded: true }, res), { _response: res._response });
|
302 | }
|
303 | catch (e) {
|
304 | if (((_a = e.details) === null || _a === void 0 ? void 0 : _a.errorCode) === "ContainerNotFound") {
|
305 | span.setStatus({
|
306 | code: SpanStatusCode.ERROR,
|
307 | message: "Expected exception when deleting a container only if it exists.",
|
308 | });
|
309 | return Object.assign(Object.assign({ succeeded: false }, (_b = e.response) === null || _b === void 0 ? void 0 : _b.parsedHeaders), { _response: e.response });
|
310 | }
|
311 | span.setStatus({
|
312 | code: SpanStatusCode.ERROR,
|
313 | message: e.message,
|
314 | });
|
315 | throw e;
|
316 | }
|
317 | finally {
|
318 | span.end();
|
319 | }
|
320 | }
|
321 | /**
|
322 | * Sets one or more user-defined name-value pairs for the specified container.
|
323 | *
|
324 | * If no option provided, or no metadata defined in the parameter, the container
|
325 | * metadata will be removed.
|
326 | *
|
327 | * @see https://docs.microsoft.com/en-us/rest/api/storageservices/set-container-metadata
|
328 | *
|
329 | * @param metadata - Replace existing metadata with this value.
|
330 | * If no value provided the existing metadata will be removed.
|
331 | * @param options - Options to Container Set Metadata operation.
|
332 | */
|
333 | async setMetadata(metadata, options = {}) {
|
334 | if (!options.conditions) {
|
335 | options.conditions = {};
|
336 | }
|
337 | if (options.conditions.ifUnmodifiedSince) {
|
338 | throw new RangeError("the IfUnmodifiedSince must have their default values because they are ignored by the blob service");
|
339 | }
|
340 | const { span, updatedOptions } = createSpan("ContainerClient-setMetadata", options);
|
341 | try {
|
342 | return await this.containerContext.setMetadata(Object.assign({ abortSignal: options.abortSignal, leaseAccessConditions: options.conditions, metadata, modifiedAccessConditions: options.conditions }, convertTracingToRequestOptionsBase(updatedOptions)));
|
343 | }
|
344 | catch (e) {
|
345 | span.setStatus({
|
346 | code: SpanStatusCode.ERROR,
|
347 | message: e.message,
|
348 | });
|
349 | throw e;
|
350 | }
|
351 | finally {
|
352 | span.end();
|
353 | }
|
354 | }
|
355 | /**
|
356 | * Gets the permissions for the specified container. The permissions indicate
|
357 | * whether container data may be accessed publicly.
|
358 | *
|
359 | * WARNING: JavaScript Date will potentially lose precision when parsing startsOn and expiresOn strings.
|
360 | * For example, new Date("2018-12-31T03:44:23.8827891Z").toISOString() will get "2018-12-31T03:44:23.882Z".
|
361 | *
|
362 | * @see https://docs.microsoft.com/en-us/rest/api/storageservices/get-container-acl
|
363 | *
|
364 | * @param options - Options to Container Get Access Policy operation.
|
365 | */
|
366 | async getAccessPolicy(options = {}) {
|
367 | if (!options.conditions) {
|
368 | options.conditions = {};
|
369 | }
|
370 | const { span, updatedOptions } = createSpan("ContainerClient-getAccessPolicy", options);
|
371 | try {
|
372 | const response = await this.containerContext.getAccessPolicy(Object.assign({ abortSignal: options.abortSignal, leaseAccessConditions: options.conditions }, convertTracingToRequestOptionsBase(updatedOptions)));
|
373 | const res = {
|
374 | _response: response._response,
|
375 | blobPublicAccess: response.blobPublicAccess,
|
376 | date: response.date,
|
377 | etag: response.etag,
|
378 | errorCode: response.errorCode,
|
379 | lastModified: response.lastModified,
|
380 | requestId: response.requestId,
|
381 | clientRequestId: response.clientRequestId,
|
382 | signedIdentifiers: [],
|
383 | version: response.version,
|
384 | };
|
385 | for (const identifier of response) {
|
386 | let accessPolicy = undefined;
|
387 | if (identifier.accessPolicy) {
|
388 | accessPolicy = {
|
389 | permissions: identifier.accessPolicy.permissions,
|
390 | };
|
391 | if (identifier.accessPolicy.expiresOn) {
|
392 | accessPolicy.expiresOn = new Date(identifier.accessPolicy.expiresOn);
|
393 | }
|
394 | if (identifier.accessPolicy.startsOn) {
|
395 | accessPolicy.startsOn = new Date(identifier.accessPolicy.startsOn);
|
396 | }
|
397 | }
|
398 | res.signedIdentifiers.push({
|
399 | accessPolicy,
|
400 | id: identifier.id,
|
401 | });
|
402 | }
|
403 | return res;
|
404 | }
|
405 | catch (e) {
|
406 | span.setStatus({
|
407 | code: SpanStatusCode.ERROR,
|
408 | message: e.message,
|
409 | });
|
410 | throw e;
|
411 | }
|
412 | finally {
|
413 | span.end();
|
414 | }
|
415 | }
|
416 | /**
|
417 | * Sets the permissions for the specified container. The permissions indicate
|
418 | * whether blobs in a container may be accessed publicly.
|
419 | *
|
420 | * When you set permissions for a container, the existing permissions are replaced.
|
421 | * If no access or containerAcl provided, the existing container ACL will be
|
422 | * removed.
|
423 | *
|
424 | * When you establish a stored access policy on a container, it may take up to 30 seconds to take effect.
|
425 | * During this interval, a shared access signature that is associated with the stored access policy will
|
426 | * fail with status code 403 (Forbidden), until the access policy becomes active.
|
427 | * @see https://docs.microsoft.com/en-us/rest/api/storageservices/set-container-acl
|
428 | *
|
429 | * @param access - The level of public access to data in the container.
|
430 | * @param containerAcl - Array of elements each having a unique Id and details of the access policy.
|
431 | * @param options - Options to Container Set Access Policy operation.
|
432 | */
|
433 | async setAccessPolicy(access, containerAcl, options = {}) {
|
434 | options.conditions = options.conditions || {};
|
435 | const { span, updatedOptions } = createSpan("ContainerClient-setAccessPolicy", options);
|
436 | try {
|
437 | const acl = [];
|
438 | for (const identifier of containerAcl || []) {
|
439 | acl.push({
|
440 | accessPolicy: {
|
441 | expiresOn: identifier.accessPolicy.expiresOn
|
442 | ? truncatedISO8061Date(identifier.accessPolicy.expiresOn)
|
443 | : "",
|
444 | permissions: identifier.accessPolicy.permissions,
|
445 | startsOn: identifier.accessPolicy.startsOn
|
446 | ? truncatedISO8061Date(identifier.accessPolicy.startsOn)
|
447 | : "",
|
448 | },
|
449 | id: identifier.id,
|
450 | });
|
451 | }
|
452 | return await this.containerContext.setAccessPolicy(Object.assign({ abortSignal: options.abortSignal, access, containerAcl: acl, leaseAccessConditions: options.conditions, modifiedAccessConditions: options.conditions }, convertTracingToRequestOptionsBase(updatedOptions)));
|
453 | }
|
454 | catch (e) {
|
455 | span.setStatus({
|
456 | code: SpanStatusCode.ERROR,
|
457 | message: e.message,
|
458 | });
|
459 | throw e;
|
460 | }
|
461 | finally {
|
462 | span.end();
|
463 | }
|
464 | }
|
465 | /**
|
466 | * Get a {@link BlobLeaseClient} that manages leases on the container.
|
467 | *
|
468 | * @param proposeLeaseId - Initial proposed lease Id.
|
469 | * @returns A new BlobLeaseClient object for managing leases on the container.
|
470 | */
|
471 | getBlobLeaseClient(proposeLeaseId) {
|
472 | return new BlobLeaseClient(this, proposeLeaseId);
|
473 | }
|
474 | /**
|
475 | * Creates a new block blob, or updates the content of an existing block blob.
|
476 | *
|
477 | * Updating an existing block blob overwrites any existing metadata on the blob.
|
478 | * Partial updates are not supported; the content of the existing blob is
|
479 | * overwritten with the new content. To perform a partial update of a block blob's,
|
480 | * use {@link BlockBlobClient.stageBlock} and {@link BlockBlobClient.commitBlockList}.
|
481 | *
|
482 | * This is a non-parallel uploading method, please use {@link BlockBlobClient.uploadFile},
|
483 | * {@link BlockBlobClient.uploadStream} or {@link BlockBlobClient.uploadBrowserData} for better
|
484 | * performance with concurrency uploading.
|
485 | *
|
486 | * @see https://docs.microsoft.com/rest/api/storageservices/put-blob
|
487 | *
|
488 | * @param blobName - Name of the block blob to create or update.
|
489 | * @param body - Blob, string, ArrayBuffer, ArrayBufferView or a function
|
490 | * which returns a new Readable stream whose offset is from data source beginning.
|
491 | * @param contentLength - Length of body in bytes. Use Buffer.byteLength() to calculate body length for a
|
492 | * string including non non-Base64/Hex-encoded characters.
|
493 | * @param options - Options to configure the Block Blob Upload operation.
|
494 | * @returns Block Blob upload response data and the corresponding BlockBlobClient instance.
|
495 | */
|
496 | async uploadBlockBlob(blobName, body, contentLength, options = {}) {
|
497 | const { span, updatedOptions } = createSpan("ContainerClient-uploadBlockBlob", options);
|
498 | try {
|
499 | const blockBlobClient = this.getBlockBlobClient(blobName);
|
500 | const response = await blockBlobClient.upload(body, contentLength, updatedOptions);
|
501 | return {
|
502 | blockBlobClient,
|
503 | response,
|
504 | };
|
505 | }
|
506 | catch (e) {
|
507 | span.setStatus({
|
508 | code: SpanStatusCode.ERROR,
|
509 | message: e.message,
|
510 | });
|
511 | throw e;
|
512 | }
|
513 | finally {
|
514 | span.end();
|
515 | }
|
516 | }
|
517 | /**
|
518 | * Marks the specified blob or snapshot for deletion. The blob is later deleted
|
519 | * during garbage collection. Note that in order to delete a blob, you must delete
|
520 | * all of its snapshots. You can delete both at the same time with the Delete
|
521 | * Blob operation.
|
522 | * @see https://docs.microsoft.com/en-us/rest/api/storageservices/delete-blob
|
523 | *
|
524 | * @param blobName -
|
525 | * @param options - Options to Blob Delete operation.
|
526 | * @returns Block blob deletion response data.
|
527 | */
|
528 | async deleteBlob(blobName, options = {}) {
|
529 | const { span, updatedOptions } = createSpan("ContainerClient-deleteBlob", options);
|
530 | try {
|
531 | let blobClient = this.getBlobClient(blobName);
|
532 | if (options.versionId) {
|
533 | blobClient = blobClient.withVersion(options.versionId);
|
534 | }
|
535 | return await blobClient.delete(updatedOptions);
|
536 | }
|
537 | catch (e) {
|
538 | span.setStatus({
|
539 | code: SpanStatusCode.ERROR,
|
540 | message: e.message,
|
541 | });
|
542 | throw e;
|
543 | }
|
544 | finally {
|
545 | span.end();
|
546 | }
|
547 | }
|
548 | /**
|
549 | * listBlobFlatSegment returns a single segment of blobs starting from the
|
550 | * specified Marker. Use an empty Marker to start enumeration from the beginning.
|
551 | * After getting a segment, process it, and then call listBlobsFlatSegment again
|
552 | * (passing the the previously-returned Marker) to get the next segment.
|
553 | * @see https://docs.microsoft.com/rest/api/storageservices/list-blobs
|
554 | *
|
555 | * @param marker - A string value that identifies the portion of the list to be returned with the next list operation.
|
556 | * @param options - Options to Container List Blob Flat Segment operation.
|
557 | */
|
558 | async listBlobFlatSegment(marker, options = {}) {
|
559 | const { span, updatedOptions } = createSpan("ContainerClient-listBlobFlatSegment", options);
|
560 | try {
|
561 | const response = await this.containerContext.listBlobFlatSegment(Object.assign(Object.assign({ marker }, options), convertTracingToRequestOptionsBase(updatedOptions)));
|
562 | response.segment.blobItems = [];
|
563 | if (response.segment["Blob"] !== undefined) {
|
564 | response.segment.blobItems = ProcessBlobItems(response.segment["Blob"]);
|
565 | }
|
566 | const wrappedResponse = Object.assign(Object.assign({}, response), { _response: Object.assign(Object.assign({}, response._response), { parsedBody: ConvertInternalResponseOfListBlobFlat(response._response.parsedBody) }), segment: Object.assign(Object.assign({}, response.segment), { blobItems: response.segment.blobItems.map((blobItemInteral) => {
|
567 | const blobItem = Object.assign(Object.assign({}, blobItemInteral), { name: BlobNameToString(blobItemInteral.name), tags: toTags(blobItemInteral.blobTags), objectReplicationSourceProperties: parseObjectReplicationRecord(blobItemInteral.objectReplicationMetadata) });
|
568 | return blobItem;
|
569 | }) }) });
|
570 | return wrappedResponse;
|
571 | }
|
572 | catch (e) {
|
573 | span.setStatus({
|
574 | code: SpanStatusCode.ERROR,
|
575 | message: e.message,
|
576 | });
|
577 | throw e;
|
578 | }
|
579 | finally {
|
580 | span.end();
|
581 | }
|
582 | }
|
583 | /**
|
584 | * listBlobHierarchySegment returns a single segment of blobs starting from
|
585 | * the specified Marker. Use an empty Marker to start enumeration from the
|
586 | * beginning. After getting a segment, process it, and then call listBlobsHierarchicalSegment
|
587 | * again (passing the the previously-returned Marker) to get the next segment.
|
588 | * @see https://docs.microsoft.com/rest/api/storageservices/list-blobs
|
589 | *
|
590 | * @param delimiter - The character or string used to define the virtual hierarchy
|
591 | * @param marker - A string value that identifies the portion of the list to be returned with the next list operation.
|
592 | * @param options - Options to Container List Blob Hierarchy Segment operation.
|
593 | */
|
594 | async listBlobHierarchySegment(delimiter, marker, options = {}) {
|
595 | var _a;
|
596 | const { span, updatedOptions } = createSpan("ContainerClient-listBlobHierarchySegment", options);
|
597 | try {
|
598 | const response = await this.containerContext.listBlobHierarchySegment(delimiter, Object.assign(Object.assign({ marker }, options), convertTracingToRequestOptionsBase(updatedOptions)));
|
599 | response.segment.blobItems = [];
|
600 | if (response.segment["Blob"] !== undefined) {
|
601 | response.segment.blobItems = ProcessBlobItems(response.segment["Blob"]);
|
602 | }
|
603 | response.segment.blobPrefixes = [];
|
604 | if (response.segment["BlobPrefix"] !== undefined) {
|
605 | response.segment.blobPrefixes = ProcessBlobPrefixes(response.segment["BlobPrefix"]);
|
606 | }
|
607 | const wrappedResponse = Object.assign(Object.assign({}, response), { _response: Object.assign(Object.assign({}, response._response), { parsedBody: ConvertInternalResponseOfListBlobHierarchy(response._response.parsedBody) }), segment: Object.assign(Object.assign({}, response.segment), { blobItems: response.segment.blobItems.map((blobItemInteral) => {
|
608 | const blobItem = Object.assign(Object.assign({}, blobItemInteral), { name: BlobNameToString(blobItemInteral.name), tags: toTags(blobItemInteral.blobTags), objectReplicationSourceProperties: parseObjectReplicationRecord(blobItemInteral.objectReplicationMetadata) });
|
609 | return blobItem;
|
610 | }), blobPrefixes: (_a = response.segment.blobPrefixes) === null || _a === void 0 ? void 0 : _a.map((blobPrefixInternal) => {
|
611 | const blobPrefix = {
|
612 | name: BlobNameToString(blobPrefixInternal.name),
|
613 | };
|
614 | return blobPrefix;
|
615 | }) }) });
|
616 | return wrappedResponse;
|
617 | }
|
618 | catch (e) {
|
619 | span.setStatus({
|
620 | code: SpanStatusCode.ERROR,
|
621 | message: e.message,
|
622 | });
|
623 | throw e;
|
624 | }
|
625 | finally {
|
626 | span.end();
|
627 | }
|
628 | }
|
629 | /**
|
630 | * Returns an AsyncIterableIterator for ContainerListBlobFlatSegmentResponse
|
631 | *
|
632 | * @param marker - A string value that identifies the portion of
|
633 | * the list of blobs to be returned with the next listing operation. The
|
634 | * operation returns the ContinuationToken value within the response body if the
|
635 | * listing operation did not return all blobs remaining to be listed
|
636 | * with the current page. The ContinuationToken value can be used as the value for
|
637 | * the marker parameter in a subsequent call to request the next page of list
|
638 | * items. The marker value is opaque to the client.
|
639 | * @param options - Options to list blobs operation.
|
640 | */
|
641 | listSegments(marker, options = {}) {
|
642 | return __asyncGenerator(this, arguments, function* listSegments_1() {
|
643 | let listBlobsFlatSegmentResponse;
|
644 | if (!!marker || marker === undefined) {
|
645 | do {
|
646 | listBlobsFlatSegmentResponse = yield __await(this.listBlobFlatSegment(marker, options));
|
647 | marker = listBlobsFlatSegmentResponse.continuationToken;
|
648 | yield yield __await(yield __await(listBlobsFlatSegmentResponse));
|
649 | } while (marker);
|
650 | }
|
651 | });
|
652 | }
|
653 | /**
|
654 | * Returns an AsyncIterableIterator of {@link BlobItem} objects
|
655 | *
|
656 | * @param options - Options to list blobs operation.
|
657 | */
|
658 | listItems(options = {}) {
|
659 | return __asyncGenerator(this, arguments, function* listItems_1() {
|
660 | var e_1, _a;
|
661 | let marker;
|
662 | try {
|
663 | for (var _b = __asyncValues(this.listSegments(marker, options)), _c; _c = yield __await(_b.next()), !_c.done;) {
|
664 | const listBlobsFlatSegmentResponse = _c.value;
|
665 | yield __await(yield* __asyncDelegator(__asyncValues(listBlobsFlatSegmentResponse.segment.blobItems)));
|
666 | }
|
667 | }
|
668 | catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
669 | finally {
|
670 | try {
|
671 | if (_c && !_c.done && (_a = _b.return)) yield __await(_a.call(_b));
|
672 | }
|
673 | finally { if (e_1) throw e_1.error; }
|
674 | }
|
675 | });
|
676 | }
|
677 | /**
|
678 | * Returns an async iterable iterator to list all the blobs
|
679 | * under the specified account.
|
680 | *
|
681 | * .byPage() returns an async iterable iterator to list the blobs in pages.
|
682 | *
|
683 | * Example using `for await` syntax:
|
684 | *
|
685 | * ```js
|
686 | * // Get the containerClient before you run these snippets,
|
687 | * // Can be obtained from `blobServiceClient.getContainerClient("<your-container-name>");`
|
688 | * let i = 1;
|
689 | * for await (const blob of containerClient.listBlobsFlat()) {
|
690 | * console.log(`Blob ${i++}: ${blob.name}`);
|
691 | * }
|
692 | * ```
|
693 | *
|
694 | * Example using `iter.next()`:
|
695 | *
|
696 | * ```js
|
697 | * let i = 1;
|
698 | * let iter = containerClient.listBlobsFlat();
|
699 | * let blobItem = await iter.next();
|
700 | * while (!blobItem.done) {
|
701 | * console.log(`Blob ${i++}: ${blobItem.value.name}`);
|
702 | * blobItem = await iter.next();
|
703 | * }
|
704 | * ```
|
705 | *
|
706 | * Example using `byPage()`:
|
707 | *
|
708 | * ```js
|
709 | * // passing optional maxPageSize in the page settings
|
710 | * let i = 1;
|
711 | * for await (const response of containerClient.listBlobsFlat().byPage({ maxPageSize: 20 })) {
|
712 | * for (const blob of response.segment.blobItems) {
|
713 | * console.log(`Blob ${i++}: ${blob.name}`);
|
714 | * }
|
715 | * }
|
716 | * ```
|
717 | *
|
718 | * Example using paging with a marker:
|
719 | *
|
720 | * ```js
|
721 | * let i = 1;
|
722 | * let iterator = containerClient.listBlobsFlat().byPage({ maxPageSize: 2 });
|
723 | * let response = (await iterator.next()).value;
|
724 | *
|
725 | * // Prints 2 blob names
|
726 | * for (const blob of response.segment.blobItems) {
|
727 | * console.log(`Blob ${i++}: ${blob.name}`);
|
728 | * }
|
729 | *
|
730 | * // Gets next marker
|
731 | * let marker = response.continuationToken;
|
732 | *
|
733 | * // Passing next marker as continuationToken
|
734 | *
|
735 | * iterator = containerClient.listBlobsFlat().byPage({ continuationToken: marker, maxPageSize: 10 });
|
736 | * response = (await iterator.next()).value;
|
737 | *
|
738 | * // Prints 10 blob names
|
739 | * for (const blob of response.segment.blobItems) {
|
740 | * console.log(`Blob ${i++}: ${blob.name}`);
|
741 | * }
|
742 | * ```
|
743 | *
|
744 | * @param options - Options to list blobs.
|
745 | * @returns An asyncIterableIterator that supports paging.
|
746 | */
|
747 | listBlobsFlat(options = {}) {
|
748 | const include = [];
|
749 | if (options.includeCopy) {
|
750 | include.push("copy");
|
751 | }
|
752 | if (options.includeDeleted) {
|
753 | include.push("deleted");
|
754 | }
|
755 | if (options.includeMetadata) {
|
756 | include.push("metadata");
|
757 | }
|
758 | if (options.includeSnapshots) {
|
759 | include.push("snapshots");
|
760 | }
|
761 | if (options.includeVersions) {
|
762 | include.push("versions");
|
763 | }
|
764 | if (options.includeUncommitedBlobs) {
|
765 | include.push("uncommittedblobs");
|
766 | }
|
767 | if (options.includeTags) {
|
768 | include.push("tags");
|
769 | }
|
770 | if (options.includeDeletedWithVersions) {
|
771 | include.push("deletedwithversions");
|
772 | }
|
773 | if (options.includeImmutabilityPolicy) {
|
774 | include.push("immutabilitypolicy");
|
775 | }
|
776 | if (options.includeLegalHold) {
|
777 | include.push("legalhold");
|
778 | }
|
779 | if (options.prefix === "") {
|
780 | options.prefix = undefined;
|
781 | }
|
782 | const updatedOptions = Object.assign(Object.assign({}, options), (include.length > 0 ? { include: include } : {}));
|
783 | // AsyncIterableIterator to iterate over blobs
|
784 | const iter = this.listItems(updatedOptions);
|
785 | return {
|
786 | /**
|
787 | * The next method, part of the iteration protocol
|
788 | */
|
789 | next() {
|
790 | return iter.next();
|
791 | },
|
792 | /**
|
793 | * The connection to the async iterator, part of the iteration protocol
|
794 | */
|
795 | [Symbol.asyncIterator]() {
|
796 | return this;
|
797 | },
|
798 | /**
|
799 | * Return an AsyncIterableIterator that works a page at a time
|
800 | */
|
801 | byPage: (settings = {}) => {
|
802 | return this.listSegments(settings.continuationToken, Object.assign({ maxPageSize: settings.maxPageSize }, updatedOptions));
|
803 | },
|
804 | };
|
805 | }
|
806 | /**
|
807 | * Returns an AsyncIterableIterator for ContainerListBlobHierarchySegmentResponse
|
808 | *
|
809 | * @param delimiter - The character or string used to define the virtual hierarchy
|
810 | * @param marker - A string value that identifies the portion of
|
811 | * the list of blobs to be returned with the next listing operation. The
|
812 | * operation returns the ContinuationToken value within the response body if the
|
813 | * listing operation did not return all blobs remaining to be listed
|
814 | * with the current page. The ContinuationToken value can be used as the value for
|
815 | * the marker parameter in a subsequent call to request the next page of list
|
816 | * items. The marker value is opaque to the client.
|
817 | * @param options - Options to list blobs operation.
|
818 | */
|
819 | listHierarchySegments(delimiter, marker, options = {}) {
|
820 | return __asyncGenerator(this, arguments, function* listHierarchySegments_1() {
|
821 | let listBlobsHierarchySegmentResponse;
|
822 | if (!!marker || marker === undefined) {
|
823 | do {
|
824 | listBlobsHierarchySegmentResponse = yield __await(this.listBlobHierarchySegment(delimiter, marker, options));
|
825 | marker = listBlobsHierarchySegmentResponse.continuationToken;
|
826 | yield yield __await(yield __await(listBlobsHierarchySegmentResponse));
|
827 | } while (marker);
|
828 | }
|
829 | });
|
830 | }
|
831 | /**
|
832 | * Returns an AsyncIterableIterator for {@link BlobPrefix} and {@link BlobItem} objects.
|
833 | *
|
834 | * @param delimiter - The character or string used to define the virtual hierarchy
|
835 | * @param options - Options to list blobs operation.
|
836 | */
|
837 | listItemsByHierarchy(delimiter, options = {}) {
|
838 | return __asyncGenerator(this, arguments, function* listItemsByHierarchy_1() {
|
839 | var e_2, _a;
|
840 | let marker;
|
841 | try {
|
842 | for (var _b = __asyncValues(this.listHierarchySegments(delimiter, marker, options)), _c; _c = yield __await(_b.next()), !_c.done;) {
|
843 | const listBlobsHierarchySegmentResponse = _c.value;
|
844 | const segment = listBlobsHierarchySegmentResponse.segment;
|
845 | if (segment.blobPrefixes) {
|
846 | for (const prefix of segment.blobPrefixes) {
|
847 | yield yield __await(Object.assign({ kind: "prefix" }, prefix));
|
848 | }
|
849 | }
|
850 | for (const blob of segment.blobItems) {
|
851 | yield yield __await(Object.assign({ kind: "blob" }, blob));
|
852 | }
|
853 | }
|
854 | }
|
855 | catch (e_2_1) { e_2 = { error: e_2_1 }; }
|
856 | finally {
|
857 | try {
|
858 | if (_c && !_c.done && (_a = _b.return)) yield __await(_a.call(_b));
|
859 | }
|
860 | finally { if (e_2) throw e_2.error; }
|
861 | }
|
862 | });
|
863 | }
|
864 | /**
|
865 | * Returns an async iterable iterator to list all the blobs by hierarchy.
|
866 | * under the specified account.
|
867 | *
|
868 | * .byPage() returns an async iterable iterator to list the blobs by hierarchy in pages.
|
869 | *
|
870 | * Example using `for await` syntax:
|
871 | *
|
872 | * ```js
|
873 | * for await (const item of containerClient.listBlobsByHierarchy("/")) {
|
874 | * if (item.kind === "prefix") {
|
875 | * console.log(`\tBlobPrefix: ${item.name}`);
|
876 | * } else {
|
877 | * console.log(`\tBlobItem: name - ${item.name}`);
|
878 | * }
|
879 | * }
|
880 | * ```
|
881 | *
|
882 | * Example using `iter.next()`:
|
883 | *
|
884 | * ```js
|
885 | * let iter = containerClient.listBlobsByHierarchy("/", { prefix: "prefix1/" });
|
886 | * let entity = await iter.next();
|
887 | * while (!entity.done) {
|
888 | * let item = entity.value;
|
889 | * if (item.kind === "prefix") {
|
890 | * console.log(`\tBlobPrefix: ${item.name}`);
|
891 | * } else {
|
892 | * console.log(`\tBlobItem: name - ${item.name}`);
|
893 | * }
|
894 | * entity = await iter.next();
|
895 | * }
|
896 | * ```
|
897 | *
|
898 | * Example using `byPage()`:
|
899 | *
|
900 | * ```js
|
901 | * console.log("Listing blobs by hierarchy by page");
|
902 | * for await (const response of containerClient.listBlobsByHierarchy("/").byPage()) {
|
903 | * const segment = response.segment;
|
904 | * if (segment.blobPrefixes) {
|
905 | * for (const prefix of segment.blobPrefixes) {
|
906 | * console.log(`\tBlobPrefix: ${prefix.name}`);
|
907 | * }
|
908 | * }
|
909 | * for (const blob of response.segment.blobItems) {
|
910 | * console.log(`\tBlobItem: name - ${blob.name}`);
|
911 | * }
|
912 | * }
|
913 | * ```
|
914 | *
|
915 | * Example using paging with a max page size:
|
916 | *
|
917 | * ```js
|
918 | * console.log("Listing blobs by hierarchy by page, specifying a prefix and a max page size");
|
919 | *
|
920 | * let i = 1;
|
921 | * for await (const response of containerClient
|
922 | * .listBlobsByHierarchy("/", { prefix: "prefix2/sub1/" })
|
923 | * .byPage({ maxPageSize: 2 })) {
|
924 | * console.log(`Page ${i++}`);
|
925 | * const segment = response.segment;
|
926 | *
|
927 | * if (segment.blobPrefixes) {
|
928 | * for (const prefix of segment.blobPrefixes) {
|
929 | * console.log(`\tBlobPrefix: ${prefix.name}`);
|
930 | * }
|
931 | * }
|
932 | *
|
933 | * for (const blob of response.segment.blobItems) {
|
934 | * console.log(`\tBlobItem: name - ${blob.name}`);
|
935 | * }
|
936 | * }
|
937 | * ```
|
938 | *
|
939 | * @param delimiter - The character or string used to define the virtual hierarchy
|
940 | * @param options - Options to list blobs operation.
|
941 | */
|
942 | listBlobsByHierarchy(delimiter, options = {}) {
|
943 | if (delimiter === "") {
|
944 | throw new RangeError("delimiter should contain one or more characters");
|
945 | }
|
946 | const include = [];
|
947 | if (options.includeCopy) {
|
948 | include.push("copy");
|
949 | }
|
950 | if (options.includeDeleted) {
|
951 | include.push("deleted");
|
952 | }
|
953 | if (options.includeMetadata) {
|
954 | include.push("metadata");
|
955 | }
|
956 | if (options.includeSnapshots) {
|
957 | include.push("snapshots");
|
958 | }
|
959 | if (options.includeVersions) {
|
960 | include.push("versions");
|
961 | }
|
962 | if (options.includeUncommitedBlobs) {
|
963 | include.push("uncommittedblobs");
|
964 | }
|
965 | if (options.includeTags) {
|
966 | include.push("tags");
|
967 | }
|
968 | if (options.includeDeletedWithVersions) {
|
969 | include.push("deletedwithversions");
|
970 | }
|
971 | if (options.includeImmutabilityPolicy) {
|
972 | include.push("immutabilitypolicy");
|
973 | }
|
974 | if (options.includeLegalHold) {
|
975 | include.push("legalhold");
|
976 | }
|
977 | if (options.prefix === "") {
|
978 | options.prefix = undefined;
|
979 | }
|
980 | const updatedOptions = Object.assign(Object.assign({}, options), (include.length > 0 ? { include: include } : {}));
|
981 | // AsyncIterableIterator to iterate over blob prefixes and blobs
|
982 | const iter = this.listItemsByHierarchy(delimiter, updatedOptions);
|
983 | return {
|
984 | /**
|
985 | * The next method, part of the iteration protocol
|
986 | */
|
987 | async next() {
|
988 | return iter.next();
|
989 | },
|
990 | /**
|
991 | * The connection to the async iterator, part of the iteration protocol
|
992 | */
|
993 | [Symbol.asyncIterator]() {
|
994 | return this;
|
995 | },
|
996 | /**
|
997 | * Return an AsyncIterableIterator that works a page at a time
|
998 | */
|
999 | byPage: (settings = {}) => {
|
1000 | return this.listHierarchySegments(delimiter, settings.continuationToken, Object.assign({ maxPageSize: settings.maxPageSize }, updatedOptions));
|
1001 | },
|
1002 | };
|
1003 | }
|
1004 | /**
|
1005 | * The Filter Blobs operation enables callers to list blobs in the container whose tags
|
1006 | * match a given search expression.
|
1007 | *
|
1008 | * @param tagFilterSqlExpression - The where parameter enables the caller to query blobs whose tags match a given expression.
|
1009 | * The given expression must evaluate to true for a blob to be returned in the results.
|
1010 | * The[OData - ABNF] filter syntax rule defines the formal grammar for the value of the where query parameter;
|
1011 | * however, only a subset of the OData filter syntax is supported in the Blob service.
|
1012 | * @param marker - A string value that identifies the portion of
|
1013 | * the list of blobs to be returned with the next listing operation. The
|
1014 | * operation returns the continuationToken value within the response body if the
|
1015 | * listing operation did not return all blobs remaining to be listed
|
1016 | * with the current page. The continuationToken value can be used as the value for
|
1017 | * the marker parameter in a subsequent call to request the next page of list
|
1018 | * items. The marker value is opaque to the client.
|
1019 | * @param options - Options to find blobs by tags.
|
1020 | */
|
1021 | async findBlobsByTagsSegment(tagFilterSqlExpression, marker, options = {}) {
|
1022 | const { span, updatedOptions } = createSpan("ContainerClient-findBlobsByTagsSegment", options);
|
1023 | try {
|
1024 | const response = await this.containerContext.filterBlobs(Object.assign({ abortSignal: options.abortSignal, where: tagFilterSqlExpression, marker, maxPageSize: options.maxPageSize }, convertTracingToRequestOptionsBase(updatedOptions)));
|
1025 | const wrappedResponse = Object.assign(Object.assign({}, response), { _response: response._response, blobs: response.blobs.map((blob) => {
|
1026 | var _a;
|
1027 | let tagValue = "";
|
1028 | if (((_a = blob.tags) === null || _a === void 0 ? void 0 : _a.blobTagSet.length) === 1) {
|
1029 | tagValue = blob.tags.blobTagSet[0].value;
|
1030 | }
|
1031 | return Object.assign(Object.assign({}, blob), { tags: toTags(blob.tags), tagValue });
|
1032 | }) });
|
1033 | return wrappedResponse;
|
1034 | }
|
1035 | catch (e) {
|
1036 | span.setStatus({
|
1037 | code: SpanStatusCode.ERROR,
|
1038 | message: e.message,
|
1039 | });
|
1040 | throw e;
|
1041 | }
|
1042 | finally {
|
1043 | span.end();
|
1044 | }
|
1045 | }
|
1046 | /**
|
1047 | * Returns an AsyncIterableIterator for ContainerFindBlobsByTagsSegmentResponse.
|
1048 | *
|
1049 | * @param tagFilterSqlExpression - The where parameter enables the caller to query blobs whose tags match a given expression.
|
1050 | * The given expression must evaluate to true for a blob to be returned in the results.
|
1051 | * The[OData - ABNF] filter syntax rule defines the formal grammar for the value of the where query parameter;
|
1052 | * however, only a subset of the OData filter syntax is supported in the Blob service.
|
1053 | * @param marker - A string value that identifies the portion of
|
1054 | * the list of blobs to be returned with the next listing operation. The
|
1055 | * operation returns the continuationToken value within the response body if the
|
1056 | * listing operation did not return all blobs remaining to be listed
|
1057 | * with the current page. The continuationToken value can be used as the value for
|
1058 | * the marker parameter in a subsequent call to request the next page of list
|
1059 | * items. The marker value is opaque to the client.
|
1060 | * @param options - Options to find blobs by tags.
|
1061 | */
|
1062 | findBlobsByTagsSegments(tagFilterSqlExpression, marker, options = {}) {
|
1063 | return __asyncGenerator(this, arguments, function* findBlobsByTagsSegments_1() {
|
1064 | let response;
|
1065 | if (!!marker || marker === undefined) {
|
1066 | do {
|
1067 | response = yield __await(this.findBlobsByTagsSegment(tagFilterSqlExpression, marker, options));
|
1068 | response.blobs = response.blobs || [];
|
1069 | marker = response.continuationToken;
|
1070 | yield yield __await(response);
|
1071 | } while (marker);
|
1072 | }
|
1073 | });
|
1074 | }
|
1075 | /**
|
1076 | * Returns an AsyncIterableIterator for blobs.
|
1077 | *
|
1078 | * @param tagFilterSqlExpression - The where parameter enables the caller to query blobs whose tags match a given expression.
|
1079 | * The given expression must evaluate to true for a blob to be returned in the results.
|
1080 | * The[OData - ABNF] filter syntax rule defines the formal grammar for the value of the where query parameter;
|
1081 | * however, only a subset of the OData filter syntax is supported in the Blob service.
|
1082 | * @param options - Options to findBlobsByTagsItems.
|
1083 | */
|
1084 | findBlobsByTagsItems(tagFilterSqlExpression, options = {}) {
|
1085 | return __asyncGenerator(this, arguments, function* findBlobsByTagsItems_1() {
|
1086 | var e_3, _a;
|
1087 | let marker;
|
1088 | try {
|
1089 | for (var _b = __asyncValues(this.findBlobsByTagsSegments(tagFilterSqlExpression, marker, options)), _c; _c = yield __await(_b.next()), !_c.done;) {
|
1090 | const segment = _c.value;
|
1091 | yield __await(yield* __asyncDelegator(__asyncValues(segment.blobs)));
|
1092 | }
|
1093 | }
|
1094 | catch (e_3_1) { e_3 = { error: e_3_1 }; }
|
1095 | finally {
|
1096 | try {
|
1097 | if (_c && !_c.done && (_a = _b.return)) yield __await(_a.call(_b));
|
1098 | }
|
1099 | finally { if (e_3) throw e_3.error; }
|
1100 | }
|
1101 | });
|
1102 | }
|
1103 | /**
|
1104 | * Returns an async iterable iterator to find all blobs with specified tag
|
1105 | * under the specified container.
|
1106 | *
|
1107 | * .byPage() returns an async iterable iterator to list the blobs in pages.
|
1108 | *
|
1109 | * Example using `for await` syntax:
|
1110 | *
|
1111 | * ```js
|
1112 | * let i = 1;
|
1113 | * for await (const blob of containerClient.findBlobsByTags("tagkey='tagvalue'")) {
|
1114 | * console.log(`Blob ${i++}: ${blob.name}`);
|
1115 | * }
|
1116 | * ```
|
1117 | *
|
1118 | * Example using `iter.next()`:
|
1119 | *
|
1120 | * ```js
|
1121 | * let i = 1;
|
1122 | * const iter = containerClient.findBlobsByTags("tagkey='tagvalue'");
|
1123 | * let blobItem = await iter.next();
|
1124 | * while (!blobItem.done) {
|
1125 | * console.log(`Blob ${i++}: ${blobItem.value.name}`);
|
1126 | * blobItem = await iter.next();
|
1127 | * }
|
1128 | * ```
|
1129 | *
|
1130 | * Example using `byPage()`:
|
1131 | *
|
1132 | * ```js
|
1133 | * // passing optional maxPageSize in the page settings
|
1134 | * let i = 1;
|
1135 | * for await (const response of containerClient.findBlobsByTags("tagkey='tagvalue'").byPage({ maxPageSize: 20 })) {
|
1136 | * if (response.blobs) {
|
1137 | * for (const blob of response.blobs) {
|
1138 | * console.log(`Blob ${i++}: ${blob.name}`);
|
1139 | * }
|
1140 | * }
|
1141 | * }
|
1142 | * ```
|
1143 | *
|
1144 | * Example using paging with a marker:
|
1145 | *
|
1146 | * ```js
|
1147 | * let i = 1;
|
1148 | * let iterator = containerClient.findBlobsByTags("tagkey='tagvalue'").byPage({ maxPageSize: 2 });
|
1149 | * let response = (await iterator.next()).value;
|
1150 | *
|
1151 | * // Prints 2 blob names
|
1152 | * if (response.blobs) {
|
1153 | * for (const blob of response.blobs) {
|
1154 | * console.log(`Blob ${i++}: ${blob.name}`);
|
1155 | * }
|
1156 | * }
|
1157 | *
|
1158 | * // Gets next marker
|
1159 | * let marker = response.continuationToken;
|
1160 | * // Passing next marker as continuationToken
|
1161 | * iterator = containerClient
|
1162 | * .findBlobsByTags("tagkey='tagvalue'")
|
1163 | * .byPage({ continuationToken: marker, maxPageSize: 10 });
|
1164 | * response = (await iterator.next()).value;
|
1165 | *
|
1166 | * // Prints blob names
|
1167 | * if (response.blobs) {
|
1168 | * for (const blob of response.blobs) {
|
1169 | * console.log(`Blob ${i++}: ${blob.name}`);
|
1170 | * }
|
1171 | * }
|
1172 | * ```
|
1173 | *
|
1174 | * @param tagFilterSqlExpression - The where parameter enables the caller to query blobs whose tags match a given expression.
|
1175 | * The given expression must evaluate to true for a blob to be returned in the results.
|
1176 | * The[OData - ABNF] filter syntax rule defines the formal grammar for the value of the where query parameter;
|
1177 | * however, only a subset of the OData filter syntax is supported in the Blob service.
|
1178 | * @param options - Options to find blobs by tags.
|
1179 | */
|
1180 | findBlobsByTags(tagFilterSqlExpression, options = {}) {
|
1181 | // AsyncIterableIterator to iterate over blobs
|
1182 | const listSegmentOptions = Object.assign({}, options);
|
1183 | const iter = this.findBlobsByTagsItems(tagFilterSqlExpression, listSegmentOptions);
|
1184 | return {
|
1185 | /**
|
1186 | * The next method, part of the iteration protocol
|
1187 | */
|
1188 | next() {
|
1189 | return iter.next();
|
1190 | },
|
1191 | /**
|
1192 | * The connection to the async iterator, part of the iteration protocol
|
1193 | */
|
1194 | [Symbol.asyncIterator]() {
|
1195 | return this;
|
1196 | },
|
1197 | /**
|
1198 | * Return an AsyncIterableIterator that works a page at a time
|
1199 | */
|
1200 | byPage: (settings = {}) => {
|
1201 | return this.findBlobsByTagsSegments(tagFilterSqlExpression, settings.continuationToken, Object.assign({ maxPageSize: settings.maxPageSize }, listSegmentOptions));
|
1202 | },
|
1203 | };
|
1204 | }
|
1205 | getContainerNameFromUrl() {
|
1206 | let containerName;
|
1207 | try {
|
1208 | // URL may look like the following
|
1209 | // "https://myaccount.blob.core.windows.net/mycontainer?sasString";
|
1210 | // "https://myaccount.blob.core.windows.net/mycontainer";
|
1211 | // IPv4/IPv6 address hosts, Endpoints - `http://127.0.0.1:10000/devstoreaccount1/containername`
|
1212 | // http://localhost:10001/devstoreaccount1/containername
|
1213 | const parsedUrl = URLBuilder.parse(this.url);
|
1214 | if (parsedUrl.getHost().split(".")[1] === "blob") {
|
1215 | // "https://myaccount.blob.core.windows.net/containername".
|
1216 | // "https://customdomain.com/containername".
|
1217 | // .getPath() -> /containername
|
1218 | containerName = parsedUrl.getPath().split("/")[1];
|
1219 | }
|
1220 | else if (isIpEndpointStyle(parsedUrl)) {
|
1221 | // IPv4/IPv6 address hosts... Example - http://192.0.0.10:10001/devstoreaccount1/containername
|
1222 | // Single word domain without a [dot] in the endpoint... Example - http://localhost:10001/devstoreaccount1/containername
|
1223 | // .getPath() -> /devstoreaccount1/containername
|
1224 | containerName = parsedUrl.getPath().split("/")[2];
|
1225 | }
|
1226 | else {
|
1227 | // "https://customdomain.com/containername".
|
1228 | // .getPath() -> /containername
|
1229 | containerName = parsedUrl.getPath().split("/")[1];
|
1230 | }
|
1231 | // decode the encoded containerName - to get all the special characters that might be present in it
|
1232 | containerName = decodeURIComponent(containerName);
|
1233 | if (!containerName) {
|
1234 | throw new Error("Provided containerName is invalid.");
|
1235 | }
|
1236 | return containerName;
|
1237 | }
|
1238 | catch (error) {
|
1239 | throw new Error("Unable to extract containerName with provided information.");
|
1240 | }
|
1241 | }
|
1242 | /**
|
1243 | * Only available for ContainerClient constructed with a shared key credential.
|
1244 | *
|
1245 | * Generates a Blob Container Service Shared Access Signature (SAS) URI based on the client properties
|
1246 | * and parameters passed in. The SAS is signed by the shared key credential of the client.
|
1247 | *
|
1248 | * @see https://docs.microsoft.com/en-us/rest/api/storageservices/constructing-a-service-sas
|
1249 | *
|
1250 | * @param options - Optional parameters.
|
1251 | * @returns The SAS URI consisting of the URI to the resource represented by this client, followed by the generated SAS token.
|
1252 | */
|
1253 | generateSasUrl(options) {
|
1254 | return new Promise((resolve) => {
|
1255 | if (!(this.credential instanceof StorageSharedKeyCredential)) {
|
1256 | throw new RangeError("Can only generate the SAS when the client is initialized with a shared key credential");
|
1257 | }
|
1258 | const sas = generateBlobSASQueryParameters(Object.assign({ containerName: this._containerName }, options), this.credential).toString();
|
1259 | resolve(appendToURLQuery(this.url, sas));
|
1260 | });
|
1261 | }
|
1262 | /**
|
1263 | * Creates a BlobBatchClient object to conduct batch operations.
|
1264 | *
|
1265 | * @see https://docs.microsoft.com/en-us/rest/api/storageservices/blob-batch
|
1266 | *
|
1267 | * @returns A new BlobBatchClient object for this container.
|
1268 | */
|
1269 | getBlobBatchClient() {
|
1270 | return new BlobBatchClient(this.url, this.pipeline);
|
1271 | }
|
1272 | }
|
1273 | //# sourceMappingURL=ContainerClient.js.map |
\ | No newline at end of file |