@azure/storage-file-share
Version:
Microsoft Azure Storage SDK for JavaScript - File
1,012 lines • 134 kB
JavaScript
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
import { __asyncGenerator, __asyncValues, __await } from "tslib";
import { isTokenCredential } from "@azure/core-auth";
import { isNode } from "@azure/core-util";
import { isPipelineLike, newPipeline } from "./Pipeline";
import { DEFAULT_MAX_DOWNLOAD_RETRY_REQUESTS, DEFAULT_HIGH_LEVEL_CONCURRENCY, FILE_MAX_SIZE_BYTES, FILE_RANGE_MAX_SIZE_BYTES, URLConstants, } from "./utils/constants";
import { appendToURLPath, setURLParameter, truncatedISO8061Date, extractConnectionStringParts, getShareNameAndPathFromUrl, appendToURLQuery, httpAuthorizationToString, setURLPath, setURLQueries, EscapePath, ConvertInternalResponseOfListFiles, ConvertInternalResponseOfListHandles, assertResponse, removeEmptyString, asSharePermission, parseOctalFileMode, toOctalFileMode, } from "./utils/utils.common";
import { Credential } from "../../storage-blob/src/credentials/Credential";
import { StorageSharedKeyCredential } from "../../storage-blob/src/credentials/StorageSharedKeyCredential";
import { AnonymousCredential } from "../../storage-blob/src/credentials/AnonymousCredential";
import { tracingClient } from "./utils/tracing";
import { StorageClient } from "./StorageClient";
import { FileDownloadResponse } from "./FileDownloadResponse";
import { rangeToString } from "./Range";
import { fileAttributesToString, fileCreationTimeToString, fileLastWriteTimeToString, validateAndSetDefaultsForFileAndDirectoryCreateCommonOptions, validateAndSetDefaultsForFileAndDirectorySetPropertiesCommonOptions, toShareProtocolsString, toShareProtocols, fileChangeTimeToString, } from "./models";
import { Batch } from "./utils/Batch";
import { BufferScheduler } from "./utils/BufferScheduler";
import { fsStat, fsCreateReadStream, readStreamToLocalFile, streamToBuffer, } from "./utils/utils.node";
import { randomUUID } from "@azure/core-util";
import { generateFileSASQueryParameters, generateFileSASQueryParametersInternal, } from "./FileSASSignatureValues";
/**
* A ShareClient represents a URL to the Azure Storage share allowing you to manipulate its directories and files.
*/
export class ShareClient extends StorageClient {
/**
* The name of the share
*/
get name() {
return this._name;
}
constructor(urlOrConnectionString, credentialOrPipelineOrShareName,
// Legacy, no way to fix the eslint error without breaking. Disable the rule for this line.
options) {
let pipeline;
let url;
if (isPipelineLike(credentialOrPipelineOrShareName)) {
// (url: string, pipeline: Pipeline)
url = urlOrConnectionString;
pipeline = credentialOrPipelineOrShareName;
}
else if (credentialOrPipelineOrShareName instanceof Credential ||
isTokenCredential(credentialOrPipelineOrShareName)) {
// (url: string, credential?: Credential, options?: ShareClientOptions)
url = urlOrConnectionString;
pipeline = newPipeline(credentialOrPipelineOrShareName, options);
}
else if (!credentialOrPipelineOrShareName &&
typeof credentialOrPipelineOrShareName !== "string") {
// (url: string, credential?: Credential, options?: ShareClientOptions)
// The second parameter is undefined. Use anonymous credential.
url = urlOrConnectionString;
pipeline = newPipeline(new AnonymousCredential(), options);
}
else if (credentialOrPipelineOrShareName &&
typeof credentialOrPipelineOrShareName === "string") {
// (connectionString: string, name: string, options?: ShareClientOptions)
const extractedCreds = extractConnectionStringParts(urlOrConnectionString);
const name = credentialOrPipelineOrShareName;
if (extractedCreds.kind === "AccountConnString") {
if (isNode) {
const sharedKeyCredential = new StorageSharedKeyCredential(extractedCreds.accountName, extractedCreds.accountKey);
url = appendToURLPath(extractedCreds.url, name);
pipeline = newPipeline(sharedKeyCredential, options);
}
else {
throw new Error("Account connection string is only supported in Node.js environment");
}
}
else if (extractedCreds.kind === "SASConnString") {
url = appendToURLPath(extractedCreds.url, name) + "?" + extractedCreds.accountSas;
pipeline = newPipeline(new AnonymousCredential(), options);
}
else {
throw new Error("Connection string must be either an Account connection string or a SAS connection string");
}
}
else {
throw new Error("Expecting non-empty strings for name parameter");
}
super(url, pipeline);
this._name = getShareNameAndPathFromUrl(this.url).shareName;
this.shareClientConfig = options;
this.context = this.storageClientContext.share;
}
/**
* Creates a new ShareClient object identical to the source but with the specified snapshot timestamp.
* Provide "" will remove the snapshot and return a URL to the base share.
*
* @param snapshot - The snapshot timestamp.
* @returns A new ShareClient object identical to the source but with the specified snapshot timestamp
*/
withSnapshot(snapshot) {
return new ShareClient(setURLParameter(this.url, URLConstants.Parameters.SHARE_SNAPSHOT, snapshot.length === 0 ? undefined : snapshot), this.pipeline, this.shareClientConfig);
}
/**
* Creates a new share under the specified account. If the share with
* the same name already exists, the operation fails.
* @see https://learn.microsoft.com/en-us/rest/api/storageservices/create-share
*
* @param options - Options to Share Create operation.
* @returns Response data for the Share Create operation.
*/
async create(options = {}) {
return tracingClient.withSpan("ShareClient-create", options, async (updatedOptions) => {
return assertResponse(await this.context.create(Object.assign(Object.assign(Object.assign({}, updatedOptions), this.shareClientConfig), { enabledProtocols: toShareProtocolsString(updatedOptions.protocols) })));
});
}
/**
* Creates a new share under the specified account. If the share with
* the same name already exists, it is not changed.
* @see https://learn.microsoft.com/en-us/rest/api/storageservices/create-share
*
* @param options -
*/
async createIfNotExists(options = {}) {
return tracingClient.withSpan("ShareClient-createIfNotExists", options, async (updatedOptions) => {
var _a, _b;
try {
const res = await this.create(updatedOptions);
return Object.assign({ succeeded: true }, res);
}
catch (e) {
if (((_a = e.details) === null || _a === void 0 ? void 0 : _a.errorCode) === "ShareAlreadyExists") {
return Object.assign(Object.assign({ succeeded: false }, (_b = e.response) === null || _b === void 0 ? void 0 : _b.parsedHeaders), { _response: e.response });
}
throw e;
}
});
}
/**
* Creates a {@link ShareDirectoryClient} object.
*
* @param directoryName - A directory name
* @returns The ShareDirectoryClient object for the given directory name.
*/
// Legacy, no way to fix the eslint error without breaking. Disable the rule for this line.
/* eslint-disable-next-line @azure/azure-sdk/ts-naming-subclients */
getDirectoryClient(directoryName) {
return new ShareDirectoryClient(appendToURLPath(this.url, EscapePath(directoryName)), this.pipeline, this.shareClientConfig);
}
/**
* Gets the directory client for the root directory of this share.
* Note that the root directory always exists and cannot be deleted.
*
* @readonly A new ShareDirectoryClient object for the root directory.
*/
// Legacy, no way to fix the eslint error without breaking. Disable the rule for this line.
/* eslint-disable-next-line @azure/azure-sdk/ts-naming-subclients */
get rootDirectoryClient() {
return this.getDirectoryClient("");
}
/**
* Creates a new subdirectory under this share.
* @see https://learn.microsoft.com/en-us/rest/api/storageservices/create-directory
*
* @param directoryName -
* @param options - Options to Directory Create operation.
* @returns Directory creation response data and the corresponding directory client.
*/
async createDirectory(directoryName, options = {}) {
return tracingClient.withSpan("ShareClient-createDirectory", options, async (updatedOptions) => {
const directoryClient = this.getDirectoryClient(directoryName);
const directoryCreateResponse = await directoryClient.create(updatedOptions);
return {
directoryClient,
directoryCreateResponse,
};
});
}
/**
* Removes the specified empty sub directory under this share.
* Note that the directory must be empty before it can be deleted.
* @see https://learn.microsoft.com/en-us/rest/api/storageservices/delete-directory
*
* @param directoryName -
* @param options - Options to Directory Delete operation.
* @returns Directory deletion response data.
*/
async deleteDirectory(directoryName, options = {}) {
return tracingClient.withSpan("ShareClient-deleteDirectory", options, async (updatedOptions) => {
const directoryClient = this.getDirectoryClient(directoryName);
return directoryClient.delete(updatedOptions);
});
}
/**
* Creates a new file or replaces a file under the root directory of this share.
* Note it only initializes the file with no content.
* @see https://learn.microsoft.com/en-us/rest/api/storageservices/create-file
*
* @param fileName -
* @param size - Specifies the maximum size in bytes for the file, up to 4 TB.
* @param options - Options to File Create operation.
* @returns File creation response data and the corresponding file client.
*/
async createFile(fileName, size, options = {}) {
return tracingClient.withSpan("ShareClient-createFile", options, async (updatedOptions) => {
const directoryClient = this.rootDirectoryClient;
const fileClient = directoryClient.getFileClient(fileName);
const fileCreateResponse = await fileClient.create(size, updatedOptions);
return {
fileClient,
fileCreateResponse,
};
});
}
/**
* Removes a file under the root directory of this share from the storage account.
* When a file is successfully deleted, it is immediately removed from the storage
* account's index and is no longer accessible to clients. The file's data is later
* removed from the service during garbage collection.
*
* Delete File will fail with status code 409 (Conflict) and error code `SharingViolation`
* if the file is open on an SMB client.
*
* Delete File is not supported on a share snapshot, which is a read-only copy of
* a share. An attempt to perform this operation on a share snapshot will fail with 400
* (`InvalidQueryParameterValue`)
*
* @see https://learn.microsoft.com/en-us/rest/api/storageservices/delete-file2
*
* @param directoryName -
* @param fileName -
* @param options - Options to File Delete operation.
* @returns Promise<FileDeleteResponse> File Delete response data.
*/
async deleteFile(fileName, options = {}) {
return tracingClient.withSpan("ShareClient-deleteFile", options, async (updatedOptions) => {
const directoryClient = this.rootDirectoryClient;
const fileClient = directoryClient.getFileClient(fileName);
return fileClient.delete(updatedOptions);
});
}
/**
* Returns true if the Azrue share resource represented by this client exists; false otherwise.
*
* NOTE: use this function with care since an existing share might be deleted by other clients or
* applications. Vice versa new shares might be added by other clients or applications after this
* function completes.
*
* @param options - options to Exists operation.
*/
async exists(options = {}) {
return tracingClient.withSpan("ShareClient-exists", options, async (updatedOptions) => {
try {
await this.getProperties(updatedOptions);
return true;
}
catch (e) {
if (e.statusCode === 404) {
return false;
}
throw e;
}
});
}
/**
* Returns all user-defined metadata and system properties for the specified
* share.
* @see https://learn.microsoft.com/en-us/rest/api/storageservices/get-share-properties
*
* WARNING: The `metadata` object returned in the response will have its keys in lowercase, even if
* they originally contained uppercase characters. This differs from the metadata keys returned by
* the `listShares` method of {@link ShareServiceClient} using the `includeMetadata` option, which
* will retain their original casing.
*
* @returns Response data for the Share Get Properties operation.
*/
async getProperties(options = {}) {
return tracingClient.withSpan("ShareClient-getProperties", options, async (updatedOptions) => {
const res = assertResponse(await this.context.getProperties(updatedOptions));
return Object.assign(Object.assign(Object.assign({}, res), this.shareClientConfig), { protocols: toShareProtocols(res.enabledProtocols) });
});
}
/**
* Marks the specified share for deletion. The share and any directories or files
* contained within it are later deleted during garbage collection.
* @see https://learn.microsoft.com/en-us/rest/api/storageservices/delete-share
*
* @param options - Options to Share Delete operation.
* @returns Response data for the Share Delete operation.
*/
async delete(options = {}) {
return tracingClient.withSpan("ShareClient-delete", options, async (updatedOptions) => {
return assertResponse(await this.context.delete(Object.assign(Object.assign({}, updatedOptions), this.shareClientConfig)));
});
}
/**
* Marks the specified share for deletion if it exists. The share and any directories or files
* contained within it are later deleted during garbage collection.
* @see https://learn.microsoft.com/en-us/rest/api/storageservices/delete-share
*
* @param options -
*/
async deleteIfExists(options = {}) {
return tracingClient.withSpan("ShareClient-deleteIfExists", options, async (updatedOptions) => {
var _a, _b;
try {
const res = await this.delete(updatedOptions);
return Object.assign({ succeeded: true }, res);
}
catch (e) {
if (((_a = e.details) === null || _a === void 0 ? void 0 : _a.errorCode) === "ShareNotFound") {
return Object.assign(Object.assign({ succeeded: false }, (_b = e.response) === null || _b === void 0 ? void 0 : _b.parsedHeaders), { _response: e.response });
}
throw e;
}
});
}
/**
* Sets one or more user-defined name-value pairs for the specified share.
*
* If no option provided, or no metadata defined in the option parameter, the share
* metadata will be removed.
* @see https://learn.microsoft.com/en-us/rest/api/storageservices/set-share-metadata
*
* @param metadata - If no metadata provided, all existing directory metadata will be removed.
* @param option - Options to Share Set Metadata operation.
* @returns Response data for the Share Set Metadata operation.
*/
async setMetadata(metadata, options = {}) {
return tracingClient.withSpan("ShareClient-setMetadata", options, async (updatedOptions) => {
return assertResponse(await this.context.setMetadata(Object.assign(Object.assign(Object.assign({}, updatedOptions), this.shareClientConfig), { metadata })));
});
}
/**
* Gets the permissions for the specified share. The permissions indicate
* whether share data may be accessed publicly.
*
* WARNING: JavaScript Date will potential lost precision when parsing start and expiry string.
* For example, new Date("2018-12-31T03:44:23.8827891Z").toISOString() will get "2018-12-31T03:44:23.882Z".
*
* @see https://learn.microsoft.com/en-us/rest/api/storageservices/get-share-acl
*
* @param option - Options to Share Get Access Policy operation.
* @returns Response data for the Share Get Access Policy operation.
*/
async getAccessPolicy(options = {}) {
return tracingClient.withSpan("ShareClient-getAccessPolicy", options, async (updatedOptions) => {
const response = assertResponse(await this.context.getAccessPolicy(Object.assign(Object.assign({}, updatedOptions), this.shareClientConfig)));
const res = {
_response: response._response,
date: response.date,
etag: response.etag,
lastModified: response.lastModified,
requestId: response.requestId,
signedIdentifiers: [],
version: response.version,
};
for (const identifier of response) {
let accessPolicy = undefined;
if (identifier.accessPolicy) {
accessPolicy = {
permissions: identifier.accessPolicy.permissions,
};
if (identifier.accessPolicy.expiresOn) {
accessPolicy.expiresOn = new Date(identifier.accessPolicy.expiresOn);
}
if (identifier.accessPolicy.startsOn) {
accessPolicy.startsOn = new Date(identifier.accessPolicy.startsOn);
}
}
res.signedIdentifiers.push({
accessPolicy,
id: identifier.id,
});
}
return res;
});
}
/**
* Sets the permissions for the specified share. The permissions indicate
* whether directories or files in a share may be accessed publicly.
*
* When you set permissions for a share, the existing permissions are replaced.
* If no shareAcl provided, the existing share ACL will be
* removed.
*
* When you establish a stored access policy on a share, it may take up to 30 seconds to take effect.
* During this interval, a shared access signature that is associated with the stored access policy will
* fail with status code 403 (Forbidden), until the access policy becomes active.
* @see https://learn.microsoft.com/en-us/rest/api/storageservices/set-share-acl
*
* @param shareAcl - Array of signed identifiers, each having a unique Id and details of access policy.
* @param option - Options to Share Set Access Policy operation.
* @returns Response data for the Share Set Access Policy operation.
*/
async setAccessPolicy(shareAcl, options = {}) {
return tracingClient.withSpan("ShareClient-setAccessPolicy", options, async (updatedOptions) => {
var _a, _b, _c;
const acl = [];
for (const identifier of shareAcl || []) {
acl.push({
accessPolicy: {
expiresOn: ((_a = identifier.accessPolicy) === null || _a === void 0 ? void 0 : _a.expiresOn)
? truncatedISO8061Date(identifier.accessPolicy.expiresOn)
: undefined,
permissions: (_b = identifier.accessPolicy) === null || _b === void 0 ? void 0 : _b.permissions,
startsOn: ((_c = identifier.accessPolicy) === null || _c === void 0 ? void 0 : _c.startsOn)
? truncatedISO8061Date(identifier.accessPolicy.startsOn)
: undefined,
},
id: identifier.id,
});
}
return assertResponse(await this.context.setAccessPolicy(Object.assign(Object.assign(Object.assign({}, updatedOptions), this.shareClientConfig), { shareAcl: acl })));
});
}
/**
* Creates a read-only snapshot of a share.
*
* @param options - Options to Share Create Snapshot operation.
* @returns Response data for the Share Create Snapshot operation.
*/
async createSnapshot(options = {}) {
return tracingClient.withSpan("ShareClient-createSnapshot", options, async (updatedOptions) => {
return assertResponse(await this.context.createSnapshot(Object.assign(Object.assign({}, updatedOptions), this.shareClientConfig)));
});
}
/**
* Sets quota for the specified share.
*
* @deprecated Use {@link ShareClient.setProperties} instead.
*
* @param quotaInGB - Specifies the maximum size of the share in gigabytes
* @param option - Options to Share Set Quota operation.
* @returns Response data for the Share Get Quota operation.
*/
async setQuota(quotaInGB, options = {}) {
return tracingClient.withSpan("ShareClient-setQuota", options, async (updatedOptions) => {
return assertResponse(await this.context.setProperties(Object.assign(Object.assign(Object.assign({}, updatedOptions), this.shareClientConfig), { quota: quotaInGB })));
});
}
/**
* Sets properties of the share.
*
* @param option - Options to Share Set Properties operation.
* @returns Response data for the Share Set Properties operation.
*/
async setProperties(options = {}) {
return tracingClient.withSpan("ShareClient-setProperties", options, async (updatedOptions) => {
return assertResponse(await this.context.setProperties(Object.assign(Object.assign(Object.assign({}, options), this.shareClientConfig), { quota: options.quotaInGB, tracingOptions: updatedOptions.tracingOptions })));
});
}
/**
* Retrieves statistics related to the share.
*
* @param option - Options to Share Get Statistics operation.
* @returns Response data for the Share Get Statistics operation.
*/
async getStatistics(options = {}) {
return tracingClient.withSpan("ShareClient-getStatistics", options, async (updatedOptions) => {
const response = assertResponse(await this.context.getStatistics(Object.assign(Object.assign({}, updatedOptions), this.shareClientConfig)));
const GBBytes = 1024 * 1024 * 1024;
return Object.assign(Object.assign({}, response), { shareUsage: Math.ceil(response.shareUsageBytes / GBBytes) });
});
}
/**
* Creates a file permission (a security descriptor) at the share level.
* The created security descriptor can be used for the files/directories in the share.
* @see https://learn.microsoft.com/en-us/rest/api/storageservices/create-permission
*
* @param options - Options to Share Create Permission operation.
* @param filePermission - File permission described in the SDDL
*/
async createPermission(filePermission, options = {}) {
return tracingClient.withSpan("ShareClient-createPermission", options, async (updatedOptions) => {
return assertResponse(await this.context.createPermission(asSharePermission(filePermission), Object.assign(Object.assign({}, updatedOptions), this.shareClientConfig)));
});
}
/**
* Gets the Security Descriptor Definition Language (SDDL) for a given file permission key
* which indicates a security descriptor.
* @see https://learn.microsoft.com/en-us/rest/api/storageservices/get-permission
*
* @param options - Options to Share Create Permission operation.
* @param filePermissionKey - File permission key which indicates the security descriptor of the permission.
*/
async getPermission(filePermissionKey, options = {}) {
return tracingClient.withSpan("ShareClient-getPermission", options, async (updatedOptions) => {
return assertResponse(await this.context.getPermission(filePermissionKey, Object.assign(Object.assign({}, updatedOptions), this.shareClientConfig)));
});
}
/**
* Get a {@link ShareLeaseClient} that manages leases on the file.
*
* @param proposeLeaseId - Initial proposed lease Id.
* @returns A new ShareLeaseClient object for managing leases on the file.
*/
getShareLeaseClient(proposeLeaseId) {
return new ShareLeaseClient(this, proposeLeaseId);
}
/**
* Only available for ShareClient constructed with a shared key credential.
*
* Generates a Service Shared Access Signature (SAS) URI based on the client properties
* and parameters passed in. The SAS is signed by the shared key credential of the client.
*
* @see https://learn.microsoft.com/en-us/rest/api/storageservices/constructing-a-service-sas
*
* @param options - Optional parameters.
* @returns The SAS URI consisting of the URI to the resource represented by this client, followed by the generated SAS token.
*/
generateSasUrl(options) {
if (!(this.credential instanceof StorageSharedKeyCredential)) {
throw RangeError("Can only generate the SAS when the client is initialized with a shared key credential");
}
const sas = generateFileSASQueryParameters(Object.assign({ shareName: this.name }, options), this.credential).toString();
return appendToURLQuery(this.url, sas);
}
/**
* Only available for ShareClient constructed with a shared key credential.
*
* Generates string to sign for a Service Shared Access Signature (SAS) URI based on the client properties
* and parameters passed in. The SAS is signed by the shared key credential of the client.
*
* @see https://learn.microsoft.com/en-us/rest/api/storageservices/constructing-a-service-sas
*
* @param options - Optional parameters.
* @returns The SAS URI consisting of the URI to the resource represented by this client, followed by the generated SAS token.
*/
/* eslint-disable-next-line @azure/azure-sdk/ts-naming-options*/
generateSasStringToSign(options) {
if (!(this.credential instanceof StorageSharedKeyCredential)) {
throw RangeError("Can only generate the SAS when the client is initialized with a shared key credential");
}
return generateFileSASQueryParametersInternal(Object.assign({ shareName: this.name }, options), this.credential).stringToSign;
}
}
/**
* A ShareDirectoryClient represents a URL to the Azure Storage directory allowing you to manipulate its files and directories.
*/
export class ShareDirectoryClient extends StorageClient {
/**
* The share name corresponding to this directory client
*/
get shareName() {
return this._shareName;
}
/**
* The full path of the directory
*/
get path() {
return this._path;
}
/**
* The name of the directory
*/
get name() {
return this._name;
}
constructor(url, credentialOrPipeline,
// Legacy, no way to fix the eslint error without breaking. Disable the rule for this line.
/* eslint-disable-next-line @azure/azure-sdk/ts-naming-options */
options = {}) {
let pipeline;
if (isPipelineLike(credentialOrPipeline)) {
pipeline = credentialOrPipeline;
}
else if (credentialOrPipeline instanceof Credential ||
isTokenCredential(credentialOrPipeline)) {
pipeline = newPipeline(credentialOrPipeline, options);
}
else {
// The second parameter is undefined. Use anonymous credential.
pipeline = newPipeline(new AnonymousCredential(), options);
}
super(url, pipeline);
({
baseName: this._name,
shareName: this._shareName,
path: this._path,
} = getShareNameAndPathFromUrl(this.url));
this.shareClientConfig = options;
this.context = this.storageClientContext.directory;
}
/**
* Creates a new directory under the specified share or parent directory.
* @see https://learn.microsoft.com/en-us/rest/api/storageservices/create-directory
*
* @param options - Options to Directory Create operation.
* @returns Response data for the Directory operation.
*/
async create(options = {}) {
if (!options.fileAttributes) {
options = validateAndSetDefaultsForFileAndDirectoryCreateCommonOptions(options);
}
return tracingClient.withSpan("ShareDirectoryClient-create", options, async (updatedOptions) => {
var _a, _b, _c;
const rawResponse = await this.context.create(Object.assign(Object.assign(Object.assign({}, updatedOptions), { fileChangeOn: fileChangeTimeToString(updatedOptions.changeTime), fileCreatedOn: fileCreationTimeToString(updatedOptions.creationTime), fileLastWriteOn: fileLastWriteTimeToString(updatedOptions.lastWriteTime), fileAttributes: updatedOptions.fileAttributes
? fileAttributesToString(updatedOptions.fileAttributes)
: undefined, owner: (_a = updatedOptions.posixProperties) === null || _a === void 0 ? void 0 : _a.owner, group: (_b = updatedOptions.posixProperties) === null || _b === void 0 ? void 0 : _b.group, fileMode: toOctalFileMode((_c = updatedOptions.posixProperties) === null || _c === void 0 ? void 0 : _c.fileMode) }), this.shareClientConfig));
const wrappedRes = Object.assign(Object.assign({}, rawResponse), { _response: rawResponse._response, posixProperties: {
fileMode: parseOctalFileMode(rawResponse.fileMode),
fileType: rawResponse.nfsFileType,
owner: rawResponse.owner,
group: rawResponse.group,
} });
return assertResponse(wrappedRes);
});
}
/**
* Creates a new directory under the specified share or parent directory if it does not already exists.
* If the directory already exists, it is not modified.
* @see https://learn.microsoft.com/en-us/rest/api/storageservices/create-directory
*
* @param options -
*/
async createIfNotExists(options = {}) {
return tracingClient.withSpan("ShareDirectoryClient-createIfNotExists", options, async (updatedOptions) => {
var _a, _b;
try {
const res = await this.create(updatedOptions);
return Object.assign({ succeeded: true }, res);
}
catch (e) {
if (((_a = e.details) === null || _a === void 0 ? void 0 : _a.errorCode) === "ResourceAlreadyExists") {
return Object.assign(Object.assign({ succeeded: false }, (_b = e.response) === null || _b === void 0 ? void 0 : _b.parsedHeaders), { _response: e.response });
}
throw e;
}
});
}
/**
* Sets properties on the directory.
* @see https://learn.microsoft.com/en-us/rest/api/storageservices/set-directory-properties
*
* @param DirectoryProperties - Directory properties. If no values are provided,
* existing values will be preserved.
*/
async setProperties(properties = {}) {
properties = validateAndSetDefaultsForFileAndDirectorySetPropertiesCommonOptions(properties);
return tracingClient.withSpan("ShareDirectoryClient-setProperties", properties, async (updatedOptions) => {
var _a, _b, _c;
const rawResponse = await this.context.setProperties(Object.assign(Object.assign(Object.assign({}, updatedOptions), { fileChangeOn: fileChangeTimeToString(updatedOptions.changeTime), fileCreatedOn: fileCreationTimeToString(updatedOptions.creationTime), fileLastWriteOn: fileLastWriteTimeToString(updatedOptions.lastWriteTime), fileAttributes: updatedOptions.fileAttributes
? fileAttributesToString(updatedOptions.fileAttributes)
: undefined, owner: (_a = updatedOptions.posixProperties) === null || _a === void 0 ? void 0 : _a.owner, group: (_b = updatedOptions.posixProperties) === null || _b === void 0 ? void 0 : _b.group, fileMode: toOctalFileMode((_c = updatedOptions.posixProperties) === null || _c === void 0 ? void 0 : _c.fileMode) }), this.shareClientConfig));
return assertResponse(Object.assign(Object.assign({}, rawResponse), { _response: rawResponse._response, posixProperties: {
fileMode: parseOctalFileMode(rawResponse.fileMode),
owner: rawResponse.owner,
group: rawResponse.group,
} }));
});
}
/**
* Creates a ShareDirectoryClient object for a sub directory.
*
* @param subDirectoryName - A subdirectory name
* @returns The ShareDirectoryClient object for the given subdirectory name.
*
* Example usage:
*
* ```js
* const directoryClient = shareClient.getDirectoryClient("<directory name>");
* await directoryClient.create();
* console.log("Created directory successfully");
* ```
*/
getDirectoryClient(subDirectoryName) {
return new ShareDirectoryClient(appendToURLPath(this.url, EscapePath(subDirectoryName)), this.pipeline, this.shareClientConfig);
}
/**
* Creates a new subdirectory under this directory.
* @see https://learn.microsoft.com/en-us/rest/api/storageservices/create-directory
*
* @param directoryName -
* @param options - Options to Directory Create operation.
* @returns Directory create response data and the corresponding DirectoryClient instance.
*/
async createSubdirectory(directoryName, options = {}) {
return tracingClient.withSpan("ShareDirectoryClient-createSubdirectory", options, async (updatedOptions) => {
const directoryClient = this.getDirectoryClient(directoryName);
const directoryCreateResponse = await directoryClient.create(updatedOptions);
return {
directoryClient,
directoryCreateResponse,
};
});
}
/**
* Removes the specified empty sub directory under this directory.
* Note that the directory must be empty before it can be deleted.
* @see https://learn.microsoft.com/en-us/rest/api/storageservices/delete-directory
*
* @param directoryName -
* @param options - Options to Directory Delete operation.
* @returns Directory deletion response data.
*/
async deleteSubdirectory(directoryName, options = {}) {
return tracingClient.withSpan("ShareDirectoryClient-deleteSubdirectory", options, async (updatedOptions) => {
const directoryClient = this.getDirectoryClient(directoryName);
return directoryClient.delete(updatedOptions);
});
}
/**
* Creates a new file or replaces a file under this directory. Note it only initializes the file with no content.
* @see https://learn.microsoft.com/en-us/rest/api/storageservices/create-file
*
* @param fileName -
* @param size - Specifies the maximum size in bytes for the file, up to 4 TB.
* @param options - Options to File Create operation.
* @returns File creation response data and the corresponding file client.
*/
async createFile(fileName, size, options = {}) {
return tracingClient.withSpan("ShareDirectoryClient-createFile", options, async (updatedOptions) => {
const fileClient = this.getFileClient(fileName);
const fileCreateResponse = await fileClient.create(size, updatedOptions);
return {
fileClient,
fileCreateResponse,
};
});
}
/**
* Removes the specified file under this directory from the storage account.
* When a file is successfully deleted, it is immediately removed from the storage
* account's index and is no longer accessible to clients. The file's data is later
* removed from the service during garbage collection.
*
* Delete File will fail with status code 409 (Conflict) and error code SharingViolation
* if the file is open on an SMB client.
*
* Delete File is not supported on a share snapshot, which is a read-only copy of
* a share. An attempt to perform this operation on a share snapshot will fail with 400 (InvalidQueryParameterValue)
*
* @see https://learn.microsoft.com/en-us/rest/api/storageservices/delete-file2
*
* @param fileName - Name of the file to delete
* @param options - Options to File Delete operation.
* @returns File deletion response data.
*/
async deleteFile(fileName, options = {}) {
return tracingClient.withSpan("ShareDirectoryClient-deleteFile", options, async (updatedOptions) => {
const fileClient = this.getFileClient(fileName);
return fileClient.delete(updatedOptions);
});
}
/**
* Creates a {@link ShareFileClient} object.
*
* @param fileName - A file name.
* @returns A new ShareFileClient object for the given file name.
*
* Example usage:
*
* ```js
* const content = "Hello world!"
*
* const fileClient = directoryClient.getFileClient("<file name>");
*
* await fileClient.create(content.length);
* console.log("Created file successfully!");
*
* await fileClient.uploadRange(content, 0, content.length);
* console.log("Updated file successfully!")
* ```
*/
// Legacy, no way to fix the eslint error without breaking. Disable the rule for this line.
/* eslint-disable-next-line @azure/azure-sdk/ts-naming-subclients */
getFileClient(fileName) {
return new ShareFileClient(appendToURLPath(this.url, EscapePath(fileName)), this.pipeline, this.shareClientConfig);
}
/**
* Returns true if the specified directory exists; false otherwise.
*
* NOTE: use this function with care since an existing directory might be deleted by other clients or
* applications. Vice versa new directories might be added by other clients or applications after this
* function completes.
*
* @param options - options to Exists operation.
*/
async exists(options = {}) {
return tracingClient.withSpan("ShareDirectoryClient-exists", options, async (updatedOptions) => {
try {
await this.getProperties(Object.assign(Object.assign({}, updatedOptions), this.shareClientConfig));
return true;
}
catch (e) {
if (e.statusCode === 404) {
return false;
}
throw e;
}
});
}
/**
* Returns all system properties for the specified directory, and can also be used to check the
* existence of a directory. The data returned does not include the files in the directory or any
* subdirectories.
* @see https://learn.microsoft.com/en-us/rest/api/storageservices/get-directory-properties
*
* @param options - Options to Directory Get Properties operation.
* @returns Response data for the Directory Get Properties operation.
*/
async getProperties(options = {}) {
return tracingClient.withSpan("ShareDirectoryClient-getProperties", options, async (updatedOptions) => {
const rawResponse = await this.context.getProperties(Object.assign(Object.assign({}, updatedOptions), this.shareClientConfig));
return assertResponse(Object.assign(Object.assign({}, rawResponse), { _response: rawResponse._response, posixProperties: {
fileMode: parseOctalFileMode(rawResponse.fileMode),
owner: rawResponse.owner,
group: rawResponse.group,
fileType: rawResponse.nfsFileType,
} }));
});
}
/**
* Removes the specified empty directory. Note that the directory must be empty before it can be
* deleted.
* @see https://learn.microsoft.com/en-us/rest/api/storageservices/delete-directory
*
* @param options - Options to Directory Delete operation.
* @returns Response data for the Directory Delete operation.
*/
async delete(options = {}) {
return tracingClient.withSpan("ShareDirectoryClient-delete", options, async (updatedOptions) => {
return assertResponse(await this.context.delete(Object.assign(Object.assign({}, updatedOptions), this.shareClientConfig)));
});
}
/**
* Removes the specified empty directory if it exists. Note that the directory must be empty before it can be
* deleted.
* @see https://learn.microsoft.com/en-us/rest/api/storageservices/delete-directory
*
* @param options -
*/
async deleteIfExists(options = {}) {
return tracingClient.withSpan("ShareDirectoryClient-deleteIfExists", options, async (updatedOptions) => {
var _a, _b, _c;
try {
const res = await this.delete(updatedOptions);
return Object.assign({ succeeded: true }, res);
}
catch (e) {
if (((_a = e.details) === null || _a === void 0 ? void 0 : _a.errorCode) === "ResourceNotFound" ||
((_b = e.details) === null || _b === void 0 ? void 0 : _b.errorCode) === "ParentNotFound") {
return Object.assign(Object.assign({ succeeded: false }, (_c = e.response) === null || _c === void 0 ? void 0 : _c.parsedHeaders), { _response: e.response });
}
throw e;
}
});
}
/**
* Updates user defined metadata for the specified directory.
* @see https://learn.microsoft.com/en-us/rest/api/storageservices/set-directory-metadata
*
* @param metadata - If no metadata provided, all existing directory metadata will be removed
* @param options - Options to Directory Set Metadata operation.
* @returns Response data for the Directory Set Metadata operation.
*/
async setMetadata(metadata, options = {}) {
return tracingClient.withSpan("ShareDirectoryClient-setMetadata", options, async (updatedOptions) => {
return assertResponse(await this.context.setMetadata(Object.assign(Object.assign(Object.assign({}, updatedOptions), { metadata }), this.shareClientConfig)));
});
}
/**
* Returns an AsyncIterableIterator for {@link DirectoryListFilesAndDirectoriesSegmentResponse} objects
*
* @param marker - A string value that identifies the portion of
* the list of files and directories to be returned with the next listing operation. The
* operation returns the ContinuationToken value within the response body if the
* listing operation did not return all files and directories remaining to be listed
* with the current page. The ContinuationToken value can be used as the value for
* the marker parameter in a subsequent call to request the next page of list
* items. The marker value is opaque to the client.
* @param options - Options to list files and directories operation.
*/
iterateFilesAndDirectoriesSegments(marker_1) {
return __asyncGenerator(this, arguments, function* iterateFilesAndDirectoriesSegments_1(marker, options = {}) {
if (options.prefix === "") {
options.prefix = undefined;
}
let listFilesAndDirectoriesResponse;
do {
listFilesAndDirectoriesResponse = yield __await(this.listFilesAndDirectoriesSegment(marker, options));
marker = listFilesAndDirectoriesResponse.continuationToken;
yield yield __await(yield __await(listFilesAndDirectoriesResponse));
} while (marker);
});
}
/**
* Returns an AsyncIterableIterator for file and directory items
*
* @param options - Options to list files and directories operation.
*/
listFilesAndDirectoriesItems() {
return __asyncGenerator(this, arguments, function* listFilesAndDirectoriesItems_1(options = {}) {
var _a, e_1, _b, _c;
if (options.prefix === "") {
options.prefix = undefined;
}
let marker;
try {
for (var _d = true, _e = __asyncValues(this.iterateFilesAndDirectoriesSegments(marker, options)), _f; _f = yield __await(_e.next()), _a = _f.done, !_a; _d = true) {
_c = _f.value;
_d = false;
const listFilesAndDirectoriesResponse = _c;
for (const file of listFilesAndDirectoriesResponse.segment.fileItems) {
yield yield __await(Object.assign({ kind: "file" }, file));
}
for (const directory of listFilesAndDirectoriesResponse.segment.directoryItems) {
yield yield __await(Object.assign({ kind: "directory" }, directory));
}
}
}
catch (e_1_1) { e_1 = { error: e_1_1 }; }
finally {
try {
if (!_d && !_a && (_b = _e.return)) yield __await(_b.call(_e));
}
finally { if (e_1) throw e_1.error; }
}
});
}
/**
* Returns an async iterable iterator to list all the files and directories
* under the specified account.
*
* .byPage() returns an async iterable iterator to list the files and directories in pages.
*
* Example using `for await` syntax:
*
* ```js
* let i = 1;
* for await (const entity of directoryClient.listFilesAndDirectories()) {
* if (entity.kind === "directory") {
* console.log(`${i++} - directory\t: ${entity.name}`);
* } else {
* console.log(`${i++} - file\t: ${entity.name}`);
* }
* }
* ```
*
* Example using `iter.next()`:
*
* ```js
* let i = 1;
* let iter = directoryClient.listFilesAndDirectories();
* let entity = await iter.next();
* while (!entity.done) {
* if (entity.value.kind === "directory") {
* console.log(`${i++} - directory\t: ${entity.value.name}`);
* } else {
* console.log(`${i++} - file\t: ${entity.value.name}`);
* }
* entity = await iter.next();
* }
* ```
*
* Example using `byPage()`:
*
* ```js
* // passing optional maxPageSize in the page settings
* let i = 1;
* for await (const response of directoryClient
* .listFilesAndDirectories()
* .byPage({ maxPageSize: 20 })) {
* for (const fileItem of response.segment.fileItems) {
* console.log(`${i++} - file\t: ${fileItem.name}`);
* }
* for (const dirItem of response.segment.directoryItems) {
* console.log(`${i++} - directory\t: ${dirItem.name}`);
* }
* }
* ```
*
* Example using paging with a marker:
*
* ```js
* let i = 1;
* let iterator = directoryClient.listFilesAndDirectories().byPage({ maxPageSize: 3 });
* let response = (await iterator.next()).value;
*
* // Prints 3 file and directory names
* for (const fileItem of response.segment.fileItems) {
* console.log(`${i++} - file\t: ${fileItem.name}`);
* }
*
* for (const dirItem of response.segment.directoryItems) {
* console.log(`${i++} - directory\t: ${dirItem.name}`);
* }
*
* // Gets next marker
* let dirMarker = response.continuationToken;
*
* // Passing next marker as continuationToken
* iterator = directoryClient
* .listFilesAndDirectories()
* .byPage({ continuationToken: dirMarker, maxPageSize: 4 });
* response = (await iterator.next()).value;
*
* // Prints 10 file and directory names
* for (const fileItem of response.segment.fileItems) {
* console.log(`${i++} - file\t: ${fileItem.name}`);
* }
*
* for (const dirItem of response.segment.directoryItems) {
* console.log(`${i++} - directory\t: ${dirItem.name}`);
* }
* ```
*
* @param options - Options to list files and directories operation.
* @returns An asyncIterableIterator that supports paging.
*/
listFilesAndDirectories(options = {}) {
const include = [];
if (options.includeTimestamps) {
include.push("Timestamps");
}
if (options.includeEtag) {
include.push("Etag");
}
if (options.in