UNPKG

57.4 kBJavaScriptView Raw
1import { __asyncDelegator, __asyncGenerator, __asyncValues, __await } from "tslib";
2import { getDefaultProxySettings, isNode, isTokenCredential, URLBuilder, } from "@azure/core-http";
3import { SpanStatusCode } from "@azure/core-tracing";
4import { AnonymousCredential } from "./credentials/AnonymousCredential";
5import { StorageSharedKeyCredential } from "./credentials/StorageSharedKeyCredential";
6import { Container } from "./generated/src/operations";
7import { newPipeline, isPipelineLike } from "./Pipeline";
8import { StorageClient } from "./StorageClient";
9import { convertTracingToRequestOptionsBase, createSpan } from "./utils/tracing";
10import { appendToURLPath, appendToURLQuery, BlobNameToString, ConvertInternalResponseOfListBlobFlat, ConvertInternalResponseOfListBlobHierarchy, extractConnectionStringParts, isIpEndpointStyle, parseObjectReplicationRecord, ProcessBlobItems, ProcessBlobPrefixes, toTags, truncatedISO8061Date, } from "./utils/utils.common";
11import { generateBlobSASQueryParameters } from "./sas/BlobSASSignatureValues";
12import { BlobLeaseClient } from "./BlobLeaseClient";
13import { AppendBlobClient, BlobClient, BlockBlobClient, PageBlobClient, } from "./Clients";
14import { BlobBatchClient } from "./BlobBatchClient";
15/**
16 * A ContainerClient represents a URL to the Azure Storage container allowing you to manipulate its blobs.
17 */
18export 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