diff --git a/common/scripts/prep-samples.js b/common/scripts/prep-samples.js index 77813256b68e..6598ef84a5b5 100644 --- a/common/scripts/prep-samples.js +++ b/common/scripts/prep-samples.js @@ -33,22 +33,22 @@ const fs = return { readdir: promisify(baseFS.readdir), readFile: promisify(baseFS.readFile), - stat: promisify(baseFS.stat), writeFile: promisify(baseFS.writeFile) }; })(); /** - * Breadth-first search for files ending in .ts, starting from `tsDir` + * Breadth-first search for files matching a given predicate * - * @param {string} tsDir The root of the sample tree to search + * @param {string} dir The root of the sample tree to search + * @param {(fs.Entry) => boolean} matches Predicate that decides whether or not a file entry is included * @returns */ -async function* findAllTsFiles(tsDir) { - const initialFiles = await fs.readdir(tsDir, { withFileTypes: true }); +async function* findMatchingFiles(dir, matches) { + const initialFiles = await fs.readdir(dir, { withFileTypes: true }); // BFS Queue and queue index - const q = initialFiles.map(f => [f, tsDir]); + const q = initialFiles.map(f => [f, dir]); while (q.length) { // [fs.Dirent, string] (file and dirName part of the full path) @@ -61,11 +61,7 @@ async function* findAllTsFiles(tsDir) { for (const child of children) { q.push([child, fullPath]); } - } else if ( - entry.isFile() && - entry.name.endsWith(".ts") && - !entry.name.endsWith(".d.ts") - ) { + } else if (matches(entry)) { yield fullPath; } else if ( entry.isBlockDevice() || @@ -87,21 +83,26 @@ async function* findAllTsFiles(tsDir) { } /** - * Replaces package imports with relative imports for CI + * Replaces package require/import statements with relative paths for CI * - * @param {string} file the name of the file to open and process - * @param {string} baseDir The base directory of the package + * @param {string} fileName the name of the file to open and process + * @param {string} baseDir the base directory of the package * @param {string} pkgName name of the package to use when looking for package-local imports */ async function enableLocalRun(fileName, baseDir, pkgName) { const fileContents = await fs.readFile(fileName, { encoding: "utf-8" }); - const importRegex = new RegExp( - `import\\s+(.*)\\s+from\\s+"${pkgName}";?\\s?`, - "s" - ); + const isTs = fileName.endsWith(".ts"); + const importRegex = isTs + ? new RegExp(`import\\s+(.*)\\s+from\\s+"${pkgName}";?\\s?`, "s") + : new RegExp(`const\\s+(.*)\\s*=\\s*require\\("${pkgName}"\\);?\\s?`, "s"); if (!importRegex.exec(fileContents)) { - throw new Error(`Sample ${fileName} did not contain an import statement!`); + // With the newer methods of using helper files and batch running, this + // should be a warning + console.warn( + `[prep-samples] skipping ${fileName} because it did not contain a matching import/require` + ); + return; } const relativeDir = path.dirname(fileName.replace(baseDir, "")); @@ -112,12 +113,27 @@ async function enableLocalRun(fileName, baseDir, pkgName) { const depth = relativeDir.length - relativeDir.split(path.sep).join("").length; - const relativeImportPath = new Array(depth).fill("..").join("/") + "/src"; - const updatedContents = fileContents.replace( + let relativePath = new Array(depth).fill("..").join("/"); + + if (isTs) { + // TypeScript imports should use src directly + relativePath += "/src"; + } + + const importRenamedContents = fileContents.replace( importRegex, - `import $1 from "${relativeImportPath}";` + isTs + ? `import $1 from "${relativePath}";` + : `const $1 = require("${relativePath}");` ); + // Remove trailing call to main() + const updatedContents = importRenamedContents.replace( + new RegExp("main\\(\\)\\.catch.*", "s"), + "" + ); + + console.log("[prep-samples] Updating imports in", fileName); return fs.writeFile(fileName, updatedContents, { encoding: "utf-8" }); } @@ -132,16 +148,28 @@ async function main() { baseDir = process.cwd(); } - const tsDir = path.join(baseDir, "samples", "typescript"); const package = require(path.join(baseDir, "package.json")); - console.log( "[prep-samples] Preparing samples for package:", `${package.name}@${package.version}` ); - for await (const fileName of findAllTsFiles(tsDir)) { - console.log("[prep-samples] Updating imports in", fileName); + const tsDir = path.join(baseDir, "samples", "typescript", "src"); + for await (const fileName of findMatchingFiles( + tsDir, + entry => + entry.isFile() && + entry.name.endsWith(".ts") && + !entry.name.endsWith(".d.ts") + )) { + await enableLocalRun(fileName, baseDir, package.name); + } + + const jsDir = path.join(baseDir, "samples", "javascript"); + for await (const fileName of findMatchingFiles( + jsDir, + entry => entry.isFile() && entry.name.endsWith(".js") + )) { await enableLocalRun(fileName, baseDir, package.name); } } diff --git a/common/scripts/run-samples.js b/common/scripts/run-samples.js new file mode 100644 index 000000000000..aeabbbc7b552 --- /dev/null +++ b/common/scripts/run-samples.js @@ -0,0 +1,115 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +/** + * run-samples.js + * + * Runs all JavaScript files in a directory, using the calling convention for + * our sample code. + */ + +const baseFS = require("fs"); +const path = require("path"); + +const IGNORE = ["node_modules"]; + +// Node >= 10 provide fs.promises, but since we're still building Node 8 for now +// we need to use util.promisify if fs.promises doesn't exist +const fs = + baseFS.promises || + (() => { + const promisify = require("util").promisify; + return { + readdir: promisify(baseFS.readdir) + }; + })(); + +/** + * Breadth-first search for files matching a given predicate + * + * @param {string} tsDir The root of the sample tree to search + * @param {(fs.Entry) => boolean} matches Predicate that decides whether or not a file entry is included + * @returns + */ +async function* findMatchingFiles(tsDir, matches) { + const initialFiles = await fs.readdir(tsDir, { withFileTypes: true }); + + // BFS Queue and queue index + const q = initialFiles.map(f => [f, tsDir]); + + while (q.length) { + // [fs.Dirent, string] (file and dirName part of the full path) + const [entry, dirName] = q.shift(); + const fullPath = path.join(dirName, entry.name); + + if (IGNORE.includes(entry.name)) { + console.log("[run-samples] Ignoring", fullPath); + continue; + } + + if (entry.isDirectory()) { + // Enqueue children of this directory to the bfs + const children = await fs.readdir(fullPath, { withFileTypes: true }); + for (const child of children) { + q.push([child, fullPath]); + } + } else if (matches(entry)) { + yield fullPath; + } + } + + // The full trace of files visited by the iterator is returned and can be accessed using `iter.value` + // once it is `done`, in case it is ever needed for debugging + return q; +} + +async function main() { + // Accept a base directory + const args = process.argv.slice(2); + + let sampleDir; + if (args.length) { + sampleDir = path.resolve(args[0]); + } else { + sampleDir = process.cwd(); + } + + // Patch the environment for the sample helper + process.env.BATCH_RUN_SAMPLES = "true"; + + console.log("[run-samples] Running all samples in:", sampleDir); + + let errors = []; + + for await (const fileName of findMatchingFiles( + sampleDir, + entry => entry.isFile() && entry.name.endsWith(".js") + )) { + console.log("[run-samples] Running", fileName); + const { main: sampleMain } = require(fileName); + try { + await sampleMain(); + } catch (err) { + const truncatedError = err + .toString() + .split("\n")[0] + .slice(0, 100); + errors.push([path.basename(fileName), truncatedError]); + console.warn("[run-samples] Error in", fileName, ":", err); + console.warn("[run-samples] Continuing ..."); + } + } + + if (errors.length > 0) { + console.error("[run-samples] Errors occurred in the following files:"); + for (const [fileName, error] of errors) { + console.error(" -", fileName, "(", error, ")"); + } + process.exit(1); + } +} + +main().catch(err => { + console.error("[run-samples] Error:", err); + process.exit(1); +}); diff --git a/sdk/storage/storage-blob/execute-samples.js b/sdk/storage/storage-blob/execute-samples.js deleted file mode 100644 index aa77c71f12be..000000000000 --- a/sdk/storage/storage-blob/execute-samples.js +++ /dev/null @@ -1,80 +0,0 @@ -const execa = require("execa"); -const fs = require("fs"); -require("dotenv").config({ path: "../.env" }); - -// Samples can be skipped by mentioning them in the skipSamples Array. -// Suppose skipSamples = ["some-entry", "sample-2"], -// some-entry.ts, sample-2.ts, some-entry.js and sample-2.js will be skipped. -const skipSamples = ["proxyAuth"]; - -const bDel = `!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!`; -const del = `${bDel}------------------------------${bDel}`; - -// Colours - green, yellow, red and blue - for console logs. -const { g, y, r, b } = [["r", 1], ["g", 2], ["b", 4], ["y", 3]].reduce( - (cols, col) => ({ - ...cols, - [col[0]]: (f) => `\x1b[3${col[1]}m${f}\x1b[0m` - }), - {} -); - -// Executes `cmd` in `cwd`(directory). -async function exec(cmd, cwd) { - let command = execa(cmd, { - cwd, - shell: true - }); - command.stderr.pipe(process.stderr); - command.stdout.pipe(process.stdout); - return command; -} - -async function runSamples(language) { - let cmd; - // Tries to execute all the samples in the `directory`. - const directory = `./samples/${language}`; - - if (language === "typescript") { - cmd = "ts-node"; - } else { - cmd = "node"; - await exec(`npm run build:js-samples`, directory); - } - - console.log(`Running ${language} samples...`); - - const files = fs.readdirSync(directory); - - for (var i = 0; i < files.length; i++) { - if (!skipSamples.includes(files[i].split(".")[0])) { - try { - console.log(`\n\n${b(del)}\n${del}`); - console.log(`${bDel}\t${files[i]} \t `); - console.log(`${del}\n${b(del)} \n`); - - console.log(`${g("Running")} ${y(files[i])} ${g("...")}`); - // Executing a sample - Example: (`ts-node samplefilename.ts`, `./samples/typescript`). - await exec(`${cmd} ${files[i]}`, directory); - console.log(`${g(files[i] + " is done..!")}`); - } catch (error) { - console.log(error.message); - console.log(`${r(del)}\n${del}`); - console.log(`${bDel}\t${files[i]} Sample - FAILED\t `); - console.log(`${del}\n${r(del)}`); - } - } - } -} - -(async () => { - try { - await runSamples("typescript"); - await runSamples("javascript"); - process.exit(0); - } catch (error) { - console.log("Samples failed!"); - console.log(error); - process.exit(1); - } -})(); diff --git a/sdk/storage/storage-blob/package.json b/sdk/storage/storage-blob/package.json index dba760e7faee..4174f2143994 100644 --- a/sdk/storage/storage-blob/package.json +++ b/sdk/storage/storage-blob/package.json @@ -24,14 +24,17 @@ "build:autorest": "autorest ./swagger/README.md --typescript --package-version=12.0.1 --use=@microsoft.azure/autorest.typescript@5.0.1", "build:es6": "tsc -p tsconfig.json", "build:nodebrowser": "rollup -c 2>&1", - "build:js-samples": "npm run clean && npm run build:es6 && cross-env ONLY_NODE=true rollup -c 2>&1", - "build:ts-samples": "npm run clean && cd samples && tsc -p . ", + "build:samples": "npm run clean && npm run build:es6 && cross-env ONLY_NODE=true rollup -c 2>&1 && npm run build:prep-samples", + "build:prep-samples": "node ../../../common/scripts/prep-samples.js && cd samples && tsc", "build:test": "npm run build:es6 && rollup -c rollup.test.config.js 2>&1", "build": "npm run build:es6 && npm run build:nodebrowser && api-extractor run --local", "check-format": "prettier --list-different --config ../../.prettierrc.json \"src/**/*.ts\" \"test/**/*.ts\" \"*.{js,json}\"", "clean": "rimraf dist dist-esm dist-test typings temp browser/*.js* browser/*.zip statistics.html coverage coverage-browser .nyc_output *.tgz *.log test*.xml TEST*.xml", + "clean:samples": "rimraf samples/javascript/node_modules samples/typescript/node_modules samples/typescript/dist samples/typescript/package-lock.json samples/javascript/package-lock.json", "extract-api": "tsc -p . && api-extractor run --local", - "execute:samples": "node execute-samples.js", + "execute:js-samples": "node ../../../common/scripts/run-samples.js samples/javascript/", + "execute:ts-samples": "node ../../../common/scripts/run-samples.js samples/typescript/dist/samples/typescript/src/", + "execute:samples": "npm run build:samples && npm run execute:js-samples && npm run execute:ts-samples", "format": "prettier --write --config ../../.prettierrc.json \"src/**/*.ts\" \"test/**/*.ts\" \"*.{js,json}\"", "integration-test:browser": "karma start --single-run", "integration-test:node": "nyc mocha --require source-map-support/register --reporter mocha-multi --reporter-options spec=-,mocha-junit-reporter=- --full-trace -t 120000 --retries 2 dist-test/index.node.js", diff --git a/sdk/storage/storage-blob/samples/javascript/README.md b/sdk/storage/storage-blob/samples/javascript/README.md new file mode 100644 index 000000000000..2a1e2c0c0705 --- /dev/null +++ b/sdk/storage/storage-blob/samples/javascript/README.md @@ -0,0 +1,85 @@ +--- +page_type: sample +languages: + - javascript +products: + - azure + - azure-storage +urlFragment: storage-blob-javascript +--- + +# Azure Storage Blob client library samples for JavaScript + +These sample programs show how to use the JavaScript client libraries for Azure Storage Blobs in some common scenarios. + +| **File Name** | **Description** | +| --------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- | +| [basic.js][basic] | authenticate with the service using an account name & key (or anonymously with a SAS URL); create and delete containers; create, list, and download a blob | +| [withConnString.js][withconnstring] | connect to and authenticate with the service using a connection string | +| [sharedKeyCred.js][sharedkeycred] | authenticate with the service using an account name and a shared key | +| [anonymousCred.js][anonymouscred] | authenticate with the service anonymously using a SAS URL | +| [azureAdAuth.js][azureadauth] | authenticate with the service using Azure Active Directory | +| [proxyAuth.js][proxyauth] | connect to the service using a proxy and authenticate with an account name & key | +| [iterators-blobs.js][iterators-blobs] | different methods for iterating over blobs in a container, showing options for paging, resuming paging, etc. | +| [iterators-containers.js][iterators-containers] | different methods for iterating over containers in an account, showing options for paging, resuming paging, etc. | +| [iterators-blobs-hierarchy.js][iterators-blobs-hierarchy] | iterating over blobs by hierarchy, using separators in the blob names, showing options for paging, resuming paging, etc. | +| [customPipeline.js][custompipeline] | use custom HTTP pipeline options when connecting to the service | +| [customizedClientHeaders.js][customizedclientheaders] | use a custom request policy to add metadata to requests, in this case through the custom x-ms-client-request-id header | +| [errorsAndResponses.js][errorsandresponses] | demonstrate various errors and responses | +| [readingSnapshot.js][readingsnapshot] | create a blob snapshot and read from that snapshot | +| [advanced.js][advanced] | use custom logging and pipeline options, then shows some example advanced options when creating containers, listing and downloading blobs, etc. | + +## Prerequisites + +The sample are compatible with Node.js >= 8.0.0, except for the samples that use the async `for await` syntax, which require Node.js >= 10.0.0. + +You need [an Azure subscription][freesub] and [an Azure Storage account][azstorage] to run these sample programs. Samples retrieve credentials to access the storage account from environment variables. Alternatively, edit the source code to include the appropriate credentials. See each individual sample for details on which environment variables/credentials it requires to function. + +Adapting the samples to run in the browser requires some additional consideration. For details, please see the [package README][package]. + +## Setup + +To run the samples using the published version of the package: + +1. Install the dependencies using `npm`: + +```bash +npm install +``` + +2. Edit the file `sample.env`, adding the correct credentials to access the Azure service and run the samples. Then rename the file from `sample.env` to just `.env`. The sample programs will read this file automatically. + +3. Run whichever samples you like (note that some samples may require additional setup, see the table above): + +```bash +node basic.js +``` + +Alternatively, run a single sample with the correct environment variables set (step 3 is not required if you do this), for example (cross-platform): + +```bash +npx cross-env ACCOUNT_NAME="" ACCOUNT_KEY="" node basic.js +``` + +## Next Steps + +Take a look at our [API Documentation][apiref] for more information about the APIs that are available in the clients. + +[advanced]: https://github.com/Azure/azure-sdk-for-js/tree/master/sdk/storage/storage-blob/samples/javascript/advanced.js +[anonymouscred]: https://github.com/Azure/azure-sdk-for-js/tree/master/sdk/storage/storage-blob/samples/javascript/anonymousCred.js +[azureadauth]: https://github.com/Azure/azure-sdk-for-js/tree/master/sdk/storage/storage-blob/samples/javascript/azureAdAuth.js +[basic]: https://github.com/Azure/azure-sdk-for-js/tree/master/sdk/storage/storage-blob/samples/javascript/basic.js +[customizedclientheaders]: https://github.com/Azure/azure-sdk-for-js/tree/master/sdk/storage/storage-blob/samples/javascript/customizedClientHeaders.js +[custompipeline]: https://github.com/Azure/azure-sdk-for-js/tree/master/sdk/storage/storage-blob/samples/javascript/customPipeline.js +[errorsandresponses]: https://github.com/Azure/azure-sdk-for-js/tree/master/sdk/storage/storage-blob/samples/javascript/errorsAndResponses.js +[iterators-blobs-hierarchy]: https://github.com/Azure/azure-sdk-for-js/tree/master/sdk/storage/storage-blob/samples/javascript/iterators-blobs-hierarchy.js +[iterators-blobs]: https://github.com/Azure/azure-sdk-for-js/tree/master/sdk/storage/storage-blob/samples/javascript/iterators-blobs.js +[iterators-containers]: https://github.com/Azure/azure-sdk-for-js/tree/master/sdk/storage/storage-blob/samples/javascript/iterators-containers.js +[proxyauth]: https://github.com/Azure/azure-sdk-for-js/tree/master/sdk/storage/storage-blob/samples/javascript/proxyAuth.js +[readingsnapshot]: https://github.com/Azure/azure-sdk-for-js/tree/master/sdk/storage/storage-blob/samples/javascript/readingSnapshot.js +[sharedkeycred]: https://github.com/Azure/azure-sdk-for-js/tree/master/sdk/storage/storage-blob/samples/javascript/sharedKeyCred.js +[withconnstring]: https://github.com/Azure/azure-sdk-for-js/tree/master/sdk/storage/storage-blob/samples/javascript/withConnString.js +[apiref]: https://docs.microsoft.com/javascript/api/@azure/storage-blob +[azstorage]: https://docs.microsoft.com/azure/storage/common/storage-account-overview +[freesub]: https://azure.microsoft.com/free/ +[package]: https://github.com/Azure/azure-sdk-for-js/tree/master/sdk/storage/storage-blob/README.md diff --git a/sdk/storage/storage-blob/samples/javascript/advanced.js b/sdk/storage/storage-blob/samples/javascript/advanced.js index 475f09a1e9a9..8c17271098ee 100644 --- a/sdk/storage/storage-blob/samples/javascript/advanced.js +++ b/sdk/storage/storage-blob/samples/javascript/advanced.js @@ -1,10 +1,13 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + /* Setup: Enter your storage account name, SAS and a path pointing to local file in main() */ const fs = require("fs"); const { AbortController } = require("@azure/abort-controller"); -const { AnonymousCredential, BlobServiceClient, newPipeline } = require("../.."); // Change to "@azure/storage-blob" in your package +const { AnonymousCredential, BlobServiceClient, newPipeline } = require("@azure/storage-blob"); // Enabling logging may help uncover useful information about failures. // In order to see a log of HTTP requests and responses, set the `AZURE_LOG_LEVEL` environment variable to `info`. @@ -17,7 +20,7 @@ async function main() { // Fill in following settings before running this sample const account = process.env.ACCOUNT_NAME || ""; const accountSas = process.env.ACCOUNT_SAS || ""; - const localFilePath = "../README.md"; + const localFilePath = "README.md"; const pipeline = newPipeline(new AnonymousCredential(), { // httpClient: MyHTTPClient, // A customized HTTP client implementing IHttpClient interface @@ -127,11 +130,8 @@ async function main() { console.log("deleted container"); } -// An async method returns a Promise object, which is compatible with then().catch() coding style. -main() - .then(() => { - console.log("Successfully executed sample."); - }) - .catch((err) => { - console.log(err.message); - }); +module.exports = { main }; + +main().catch((err) => { + console.error("Error running sample:", err.message); +}); diff --git a/sdk/storage/storage-blob/samples/javascript/anonymousCred.js b/sdk/storage/storage-blob/samples/javascript/anonymousCred.js index 0b1b53d15464..8b5f1657fe82 100644 --- a/sdk/storage/storage-blob/samples/javascript/anonymousCred.js +++ b/sdk/storage/storage-blob/samples/javascript/anonymousCred.js @@ -1,8 +1,11 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + /* Setup: Enter your storage account name and SAS in main() */ -const { BlobServiceClient, AnonymousCredential } = require("../.."); // Change to "@azure/storage-blob" in your package +const { BlobServiceClient, AnonymousCredential } = require("@azure/storage-blob"); async function main() { // Enter your storage account name and SAS @@ -37,11 +40,8 @@ async function main() { console.log("deleted container"); } -// An async method returns a Promise object, which is compatible with then().catch() coding style. -main() - .then(() => { - console.log("Successfully executed sample."); - }) - .catch((err) => { - console.log(err.message); - }); +module.exports = { main }; + +main().catch((err) => { + console.error("Error running sample:", err.message); +}); diff --git a/sdk/storage/storage-blob/samples/javascript/azureAdAuth.js b/sdk/storage/storage-blob/samples/javascript/azureAdAuth.js index 2f2d81db6808..fb43688cabe2 100644 --- a/sdk/storage/storage-blob/samples/javascript/azureAdAuth.js +++ b/sdk/storage/storage-blob/samples/javascript/azureAdAuth.js @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + /* ONLY AVAILABLE IN NODE.JS RUNTIME @@ -18,13 +21,25 @@ - Make sure you have AZURE_TENANT_ID, AZURE_CLIENT_ID, AZURE_CLIENT_SECRET as environment variables to successfully execute the sample(Can leverage process.env). */ -const { BlobServiceClient } = require("../.."); // Change to "@azure/storage-blob" in your package +const { BlobServiceClient } = require("@azure/storage-blob"); const { DefaultAzureCredential } = require("@azure/identity"); async function main() { // Enter your storage account name const account = process.env.ACCOUNT_NAME || ""; + // Azure AD Credential information is required to run this sample: + if ( + !process.env.AZURE_TENANT_ID || + !process.env.AZURE_CLIENT_ID || + !process.env.AZURE_CLIENT_SECRET + ) { + console.warn( + "Azure AD authentication information not provided, but it is required to run this sample. Exiting." + ); + return; + } + // ONLY AVAILABLE IN NODE.JS RUNTIME // DefaultAzureCredential will first look for Azure Active Directory (AAD) // client secret credentials in the following environment variables: @@ -51,11 +66,8 @@ async function main() { console.log(`Created container ${containerName} successfully`, createContainerResponse.requestId); } -// An async method returns a Promise object, which is compatible with then().catch() coding style. -main() - .then(() => { - console.log("Successfully executed the sample."); - }) - .catch((err) => { - console.log(err.message); - }); +module.exports = { main }; + +main().catch((err) => { + console.error("Error running sample:", err.message); +}); diff --git a/sdk/storage/storage-blob/samples/javascript/basic.js b/sdk/storage/storage-blob/samples/javascript/basic.js index 5ac24138fafb..b48c474bb516 100644 --- a/sdk/storage/storage-blob/samples/javascript/basic.js +++ b/sdk/storage/storage-blob/samples/javascript/basic.js @@ -1,8 +1,11 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + /* Setup: Enter your storage account name and shared key in main() */ -const { BlobServiceClient, StorageSharedKeyCredential } = require("../.."); // Change to "@azure/storage-blob" in your package +const { BlobServiceClient, StorageSharedKeyCredential } = require("@azure/storage-blob"); async function main() { // Enter your storage account name and shared key @@ -94,11 +97,8 @@ async function streamToString(readableStream) { }); } -// An async method returns a Promise object, which is compatible with then().catch() coding style. -main() - .then(() => { - console.log("Successfully executed sample."); - }) - .catch((err) => { - console.log(err.message); - }); +module.exports = { main }; + +main().catch((err) => { + console.error("Error running sample:", err.message); +}); diff --git a/sdk/storage/storage-blob/samples/javascript/customPipeline.js b/sdk/storage/storage-blob/samples/javascript/customPipeline.js index 86788560fb50..4823d0ae2046 100644 --- a/sdk/storage/storage-blob/samples/javascript/customPipeline.js +++ b/sdk/storage/storage-blob/samples/javascript/customPipeline.js @@ -1,8 +1,15 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + /* Setup: Enter your storage account name and shared key in main() */ -const { BlobServiceClient, StorageSharedKeyCredential, newPipeline } = require("../.."); // Change to "@azure/storage-blob" in your package +const { + BlobServiceClient, + StorageSharedKeyCredential, + newPipeline +} = require("@azure/storage-blob"); async function main() { // Enter your storage account name and shared key @@ -44,11 +51,8 @@ async function main() { console.log("deleted container"); } -// An async method returns a Promise object, which is compatible with then().catch() coding style. -main() - .then(() => { - console.log("Successfully executed sample."); - }) - .catch((err) => { - console.log(err.message); - }); +module.exports = { main }; + +main().catch((err) => { + console.error("Error running sample:", err.message); +}); diff --git a/sdk/storage/storage-blob/samples/javascript/customizedClientHeaders.js b/sdk/storage/storage-blob/samples/javascript/customizedClientHeaders.js index b0185af6682f..a05233749bcd 100644 --- a/sdk/storage/storage-blob/samples/javascript/customizedClientHeaders.js +++ b/sdk/storage/storage-blob/samples/javascript/customizedClientHeaders.js @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + /* You can create your own policy and inject it into the default pipeline, or create your own Pipeline. A request policy is a filter triggered before and after a HTTP request. With a filter, we can tweak HTTP requests and responses. @@ -9,7 +12,12 @@ Setup: Enter your storage account name and shared key in main() */ -const { newPipeline, AnonymousCredential, BlobServiceClient, BaseRequestPolicy } = require("../.."); // Change to "@azure/storage-blob" in your package +const { + newPipeline, + AnonymousCredential, + BlobServiceClient, + BaseRequestPolicy +} = require("@azure/storage-blob"); // Create a policy factory with create() method provided class RequestIDPolicyFactory { @@ -64,17 +72,19 @@ async function main() { `https://${account}.blob.core.windows.net${accountSas}`, pipeline ); - const response = (await blobServiceClient - .listContainers() - .byPage() - .next()).value; + const response = ( + await blobServiceClient + .listContainers() + .byPage() + .next() + ).value; // Check customized client request ID console.log(response._response.request.headers.get("x-ms-client-request-id")); } -main() - .then(() => { - console.log("Successfully executed sample"); - }) - .catch(console.error); +module.exports = { main }; + +main().catch((err) => { + console.error("Error running sample:", err.message); +}); diff --git a/sdk/storage/storage-blob/samples/javascript/errorsAndResponses.js b/sdk/storage/storage-blob/samples/javascript/errorsAndResponses.js index f21c3be43482..b40e9b2495f9 100644 --- a/sdk/storage/storage-blob/samples/javascript/errorsAndResponses.js +++ b/sdk/storage/storage-blob/samples/javascript/errorsAndResponses.js @@ -1,8 +1,11 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + /* Setup: Enter connection string of your storage account name in main() */ -const { BlobServiceClient } = require("../.."); // Change to "@azure/storage-blob" in your package +const { BlobServiceClient } = require("@azure/storage-blob"); async function main() { // Create Blob Service Client from Account connection string or SAS connection string @@ -145,11 +148,8 @@ async function streamToString(readableStream) { }); } -// An async method returns a Promise object, which is compatible with then().catch() coding style. -main() - .then(() => { - console.log("\n\nSuccessfully executed sample."); - }) - .catch((err) => { - console.log(err.message); - }); +module.exports = { main }; + +main().catch((err) => { + console.error("Error running sample:", err.message); +}); diff --git a/sdk/storage/storage-blob/samples/javascript/iterators-blobs-hierarchy.js b/sdk/storage/storage-blob/samples/javascript/iterators-blobs-hierarchy.js index 1f87715de689..414c5137bea8 100644 --- a/sdk/storage/storage-blob/samples/javascript/iterators-blobs-hierarchy.js +++ b/sdk/storage/storage-blob/samples/javascript/iterators-blobs-hierarchy.js @@ -1,8 +1,11 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + /* Setup: Enter your storage account name and shared key in main() */ -const { BlobServiceClient, StorageSharedKeyCredential } = require("../.."); // Change to "@azure/storage-blob" in your package +const { BlobServiceClient, StorageSharedKeyCredential } = require("@azure/storage-blob"); async function main() { // Enter your storage account name and shared key @@ -131,11 +134,8 @@ async function main() { console.log("deleted container"); } -// An async method returns a Promise object, which is compatible with then().catch() coding style. -main() - .then(() => { - console.log("Successfully executed the sample."); - }) - .catch((err) => { - console.log(err.message); - }); +module.exports = { main }; + +main().catch((err) => { + console.error("Error running sample:", err.message); +}); diff --git a/sdk/storage/storage-blob/samples/javascript/iterators-blobs.js b/sdk/storage/storage-blob/samples/javascript/iterators-blobs.js index f0de7a795926..a942de620acf 100644 --- a/sdk/storage/storage-blob/samples/javascript/iterators-blobs.js +++ b/sdk/storage/storage-blob/samples/javascript/iterators-blobs.js @@ -1,8 +1,11 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + /* Setup: Enter your storage account name and shared key in main() */ -const { BlobServiceClient, StorageSharedKeyCredential } = require("../.."); // Change to "@azure/storage-blob" in your package +const { BlobServiceClient, StorageSharedKeyCredential } = require("@azure/storage-blob"); async function main() { // Enter your storage account name and shared key @@ -122,11 +125,8 @@ async function main() { console.log("deleted container"); } -// An async method returns a Promise object, which is compatible with then().catch() coding style. -main() - .then(() => { - console.log("Successfully executed the sample."); - }) - .catch((err) => { - console.log(err.message); - }); +module.exports = { main }; + +main().catch((err) => { + console.error("Error running sample:", err.message); +}); diff --git a/sdk/storage/storage-blob/samples/javascript/iterators-containers.js b/sdk/storage/storage-blob/samples/javascript/iterators-containers.js index d8f86c089bf0..d2a207407c1d 100644 --- a/sdk/storage/storage-blob/samples/javascript/iterators-containers.js +++ b/sdk/storage/storage-blob/samples/javascript/iterators-containers.js @@ -1,8 +1,11 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + /* Setup: Enter your storage account name and shared key in main() */ -const { BlobServiceClient, StorageSharedKeyCredential } = require("../.."); // Change to "@azure/storage-blob" in your package +const { BlobServiceClient, StorageSharedKeyCredential } = require("@azure/storage-blob"); async function main() { // Enter your storage account name and shared key @@ -111,11 +114,8 @@ async function main() { } } -// An async method returns a Promise object, which is compatible with then().catch() coding style. -main() - .then(() => { - console.log("Successfully executed the sample."); - }) - .catch((err) => { - console.log(err.message); - }); +module.exports = { main }; + +main().catch((err) => { + console.error("Error running sample:", err.message); +}); diff --git a/sdk/storage/storage-blob/samples/javascript/package.json b/sdk/storage/storage-blob/samples/javascript/package.json new file mode 100644 index 000000000000..556fbb345f1b --- /dev/null +++ b/sdk/storage/storage-blob/samples/javascript/package.json @@ -0,0 +1,37 @@ +{ + "name": "azure-storage-blob-samples-js", + "private": true, + "version": "0.1.0", + "description": "Azure Storage Blob client library samples for TypeScript", + "engine": { + "node": ">=8.0.0" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/Azure/azure-sdk-for-js.git" + }, + "keywords": [ + "Azure", + "Storage", + "Blob", + "Node.js", + "JavaScript" + ], + "author": "Microsoft Corporation", + "license": "MIT", + "bugs": { + "url": "https://github.com/Azure/azure-sdk-for-js/issues" + }, + "homepage": "https://github.com/Azure/azure-sdk-for-js#readme", + "sideEffects": false, + "dependencies": { + "@azure/abort-controller": "latest", + "@azure/identity": "latest", + "@azure/storage-blob": "latest", + "dotenv": "^8.2.0" + }, + "devDependencies": { + "cross-env": "^6.0.3", + "rimraf": "^3.0.0" + } +} diff --git a/sdk/storage/storage-blob/samples/javascript/proxyAuth.js b/sdk/storage/storage-blob/samples/javascript/proxyAuth.js index 424af6251cdf..c20efe0ae404 100644 --- a/sdk/storage/storage-blob/samples/javascript/proxyAuth.js +++ b/sdk/storage/storage-blob/samples/javascript/proxyAuth.js @@ -1,8 +1,11 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + /* Setup: Enter your storage account name and shared key in main() */ -const { BlobServiceClient, StorageSharedKeyCredential } = require("../.."); // Change to "@azure/storage-blob" in your package +const { BlobServiceClient, StorageSharedKeyCredential } = require("@azure/storage-blob"); async function main() { // Enter your storage account name and shared key @@ -13,20 +16,27 @@ async function main() { // StorageSharedKeyCredential is only avaiable in Node.js runtime, not in browsers const sharedKeyCredential = new StorageSharedKeyCredential(account, accountKey); + // To use the manual proxyOptions below, remove this block + if (!process.env.HTTP_PROXY || !process.env.HTTPS_PROXY) { + console.warn("Proxy information not provided, but it is required to run this sample. Exiting."); + return; + } + const blobServiceClient = new BlobServiceClient( `https://${account}.blob.core.windows.net`, sharedKeyCredential, + // The library tries to load the proxy settings from the environment variables like HTTP_PROXY + // Alternatively, the service client accepts the following `proxyOptions` as part of its options: { - // proxy can either be a URL like "http://localhost:3128" - // or - // an option bag consisting {host, port, username, password } - proxyOptions: { + /* + proxyOptions : { + // To use these options, remove the section above that checks for HTTP_PROXY or HTTPS_PROXY host: "http://localhost", port: 3128, - username: "username", - password: "password" + username: "", + password: "" } - // if proxy is undefined, the library tries to load the proxy settings from the environment variables like HTTP_PROXY + */ } ); @@ -38,11 +48,8 @@ async function main() { console.log(`Created container ${containerName} successfully`, createContainerResponse.requestId); } -// An async method returns a Promise object, which is compatible with then().catch() coding style. -main() - .then(() => { - console.log("Successfully executed the sample."); - }) - .catch((err) => { - console.log(err.message); - }); +module.exports = { main }; + +main().catch((err) => { + console.error("Error running sample:", err.message); +}); diff --git a/sdk/storage/storage-blob/samples/javascript/readingSnapshot.js b/sdk/storage/storage-blob/samples/javascript/readingSnapshot.js index 20d4a2a03b71..22126e7a40f8 100644 --- a/sdk/storage/storage-blob/samples/javascript/readingSnapshot.js +++ b/sdk/storage/storage-blob/samples/javascript/readingSnapshot.js @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + /* If you use BlobClient.download() to download an append blob which is being actively appended, you may get a 412 HTTP error, just like this issue: https://github.com/Azure/azure-storage-js/issues/51 @@ -18,7 +21,7 @@ Setup: Enter your storage account name and shared key in main() */ -const { BlobServiceClient, StorageSharedKeyCredential } = require("../.."); // Change to "@azure/storage-blob" in your package +const { BlobServiceClient, StorageSharedKeyCredential } = require("@azure/storage-blob"); async function main() { // Enter your storage account name and shared key @@ -82,11 +85,8 @@ async function streamToString(readableStream) { }); } -// An async method returns a Promise object, which is compatible with then().catch() coding style. -main() - .then(() => { - console.log("Successfully executed sample."); - }) - .catch((err) => { - console.log(err.message); - }); +module.exports = { main }; + +main().catch((err) => { + console.error("Error running sample:", err.message); +}); diff --git a/sdk/storage/storage-blob/samples/javascript/sample.env b/sdk/storage/storage-blob/samples/javascript/sample.env new file mode 100644 index 000000000000..92a81cac6547 --- /dev/null +++ b/sdk/storage/storage-blob/samples/javascript/sample.env @@ -0,0 +1,20 @@ +# Used in most samples. Retrieve these values from a storage account in the Azure Portal. +ACCOUNT_NAME= +ACCOUNT_KEY= + +# Used for withConnString +STORAGE_CONNECTION_STRING= + +# Used for the advanced and anonymousCred tests. Create a SAS token for a storage account in the Azure Portal. +ACCOUNT_SAS= + +# Used to authenticate using Azure AD as a service principal for role-based authentication. +# +# See the documentation for `EnvironmentCredential` at the following link: +# https://docs.microsoft.com/javascript/api/@azure/identity/environmentcredential +AZURE_TENANT_ID= +AZURE_CLIENT_ID= +AZURE_CLIENT_SECRET= + +# To run the proxyAuth sample, set up an HTTP proxy and enter your information: +# HTTP_PROXY=http://localhost:3128 diff --git a/sdk/storage/storage-blob/samples/javascript/sharedKeyCred.js b/sdk/storage/storage-blob/samples/javascript/sharedKeyCred.js index e6f25bc36463..a9085cceb204 100644 --- a/sdk/storage/storage-blob/samples/javascript/sharedKeyCred.js +++ b/sdk/storage/storage-blob/samples/javascript/sharedKeyCred.js @@ -1,8 +1,11 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + /* Setup: Enter your storage account name and shared key in main() */ -const { BlobServiceClient, StorageSharedKeyCredential } = require("../.."); // Change to "@azure/storage-blob" in your package +const { BlobServiceClient, StorageSharedKeyCredential } = require("@azure/storage-blob"); async function main() { // Enter your storage account name and shared key @@ -37,11 +40,8 @@ async function main() { console.log("deleted container"); } -// An async method returns a Promise object, which is compatible with then().catch() coding style. -main() - .then(() => { - console.log("Successfully executed sample."); - }) - .catch((err) => { - console.log(err.message); - }); +module.exports = { main }; + +main().catch((err) => { + console.error("Error running sample:", err.message); +}); diff --git a/sdk/storage/storage-blob/samples/javascript/withConnString.js b/sdk/storage/storage-blob/samples/javascript/withConnString.js index 08ebb18c5fa2..5dc16dddd7be 100644 --- a/sdk/storage/storage-blob/samples/javascript/withConnString.js +++ b/sdk/storage/storage-blob/samples/javascript/withConnString.js @@ -1,8 +1,11 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + /* Setup: Enter your storage account name and shared key in main() */ -const { BlobServiceClient } = require("../.."); // Change to "@azure/storage-blob" in your package +const { BlobServiceClient } = require("@azure/storage-blob"); async function main() { // Create Blob Service Client from Account connection string or SAS connection string @@ -30,11 +33,8 @@ async function main() { console.log("deleted container"); } -// An async method returns a Promise object, which is compatible with then().catch() coding style. -main() - .then(() => { - console.log("Successfully executed sample."); - }) - .catch((err) => { - console.log(err.message); - }); +module.exports = { main }; + +main().catch((err) => { + console.error("Error running sample:", err.message); +}); diff --git a/sdk/storage/storage-blob/samples/tsconfig.json b/sdk/storage/storage-blob/samples/tsconfig.json index c01d1f002034..3a37abdb0902 100644 --- a/sdk/storage/storage-blob/samples/tsconfig.json +++ b/sdk/storage/storage-blob/samples/tsconfig.json @@ -1,13 +1,9 @@ { - "extends": "../tsconfig.json", - "compilerOptions": { - "module": "commonjs" - }, - "include": [ - "**/*.ts" - ], - "exclude": [ - "../node_modules", - "../typings/**", - ] -} \ No newline at end of file + "extends": "../tsconfig.json", + "compilerOptions": { + "module": "commonjs", + "outDir": "typescript/dist" + }, + "include": ["typescript/src/**.ts"], + "exclude": ["typescript/*.json", "**/node_modules/", "../node_modules", "../typings"] +} diff --git a/sdk/storage/storage-blob/samples/typescript/README.md b/sdk/storage/storage-blob/samples/typescript/README.md new file mode 100644 index 000000000000..d5856db9b7cb --- /dev/null +++ b/sdk/storage/storage-blob/samples/typescript/README.md @@ -0,0 +1,98 @@ +--- +page_type: sample +languages: + - typescript +products: + - azure + - azure-storage +urlFragment: storage-blob-typescript +--- + +# Azure Storage Blob client library samples for TypeScript + +These sample programs show how to use the TypeScript client libraries for Azure Storage Blobs in some common scenarios. + +| **File Name** | **Description** | +| --------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- | +| [basic.ts][basic] | authenticate with the service using an account name & key (or anonymously with a SAS URL); create and delete containers; create, list, and download a blob | +| [withConnString.ts][withconnstring] | connect to and authenticate with the service using a connection string | +| [sharedKeyCred.ts][sharedkeycred] | authenticate with the service using an account name and a shared key | +| [anonymousCred.ts][anonymouscred] | authenticate with the service anonymously using a SAS URL | +| [azureAdAuth.ts][azureadauth] | authenticate with the service using Azure Active Directory | +| [proxyAuth.ts][proxyauth] | connect to the service using a proxy and authenticate with an account name & key | +| [iterators-blobs.ts][iterators-blobs] | different methods for iterating over blobs in a container, showing options for paging, resuming paging, etc. | +| [iterators-containers.ts][iterators-containers] | different methods for iterating over containers in an account, showing options for paging, resuming paging, etc. | +| [iterators-blobs-hierarchy.ts][iterators-blobs-hierarchy] | iterating over blobs by hierarchy, using separators in the blob names, showing options for paging, resuming paging, etc. | +| [customPipeline.ts][custompipeline] | use custom HTTP pipeline options when connecting to the service | +| [customizedClientHeaders.ts][customizedclientheaders] | use a custom request policy to add metadata to requests, in this case through the custom x-ms-client-request-id header | +| [errorsAndResponses.ts][errorsandresponses] | demonstrate various errors and responses | +| [readingSnapshot.ts][readingsnapshot] | create a blob snapshot and read from that snapshot | +| [advanced.ts][advanced] | use custom logging and pipeline options, then shows some example advanced options when creating containers, listing and downloading blobs, etc. | + +## Prerequisites + +The samples are compatible with Node.js >= 8.0.0, except for the samples that use the async `for await` syntax, which require a Node.js >= 10.0.0. + +Before running the samples in Node, they must be compiled to JavaScript using the TypeScript compiler. For more information on TypeScript, see the [TypeScript documentation][typescript]. Install the TypeScript compiler using + +```bash +npm install -g typescript +``` + +You need [an Azure subscription][freesub] and [an Azure Storage account][azstorage] to run these sample programs. Samples retrieve credentials to access the storage account from environment variables. Alternatively, edit the source code to include the appropriate credentials. See each individual sample for details on which environment variables/credentials it requires to function. + +Adapting the samples to run in the browser requires some additional consideration. For details, please see the [package README][package]. + +## Setup + +To run the samples using the published version of the package: + +1. Install the dependencies using `npm`: + +```bash +npm install +``` + +2. Compile the samples + +```bash +npm run build +``` + +3. Edit the file `sample.env`, adding the correct credentials to access the Azure service and run the samples. Then rename the file from `sample.env` to just `.env`. The sample programs will read this file automatically. + +4. Run whichever samples you like (note that some samples may require additional setup, see the table above): + +```bash +node dist/basic.js +``` + +Alternatively, run a single sample with the correct environment variables set (step 3 is not required if you do this), for example (cross-platform): + +```bash +npx cross-env ACCOUNT_NAME="" ACCOUNT_KEY="" node dist/basic.js +``` + +## Next Steps + +Take a look at our [API Documentation][apiref] for more information about the APIs that are available in the clients. + +[advanced]: https://github.com/Azure/azure-sdk-for-js/tree/master/sdk/storage/storage-blob/samples/typescript/src/advanced.ts +[anonymouscred]: https://github.com/Azure/azure-sdk-for-js/tree/master/sdk/storage/storage-blob/samples/typescript/src/anonymousCred.ts +[azureadauth]: https://github.com/Azure/azure-sdk-for-js/tree/master/sdk/storage/storage-blob/samples/typescript/src/azureAdAuth.ts +[basic]: https://github.com/Azure/azure-sdk-for-js/tree/master/sdk/storage/storage-blob/samples/typescript/src/basic.ts +[customizedclientheaders]: https://github.com/Azure/azure-sdk-for-js/tree/master/sdk/storage/storage-blob/samples/typescript/src/customizedClientHeaders.ts +[custompipeline]: https://github.com/Azure/azure-sdk-for-js/tree/master/sdk/storage/storage-blob/samples/typescript/src/customPipeline.ts +[errorsandresponses]: https://github.com/Azure/azure-sdk-for-js/tree/master/sdk/storage/storage-blob/samples/typescript/src/errorsAndResponses.ts +[iterators-blobs-hierarchy]: https://github.com/Azure/azure-sdk-for-js/tree/master/sdk/storage/storage-blob/samples/typescript/src/iterators-blobs-hierarchy.ts +[iterators-blobs]: https://github.com/Azure/azure-sdk-for-js/tree/master/sdk/storage/storage-blob/samples/typescript/src/iterators-blobs.ts +[iterators-containers]: https://github.com/Azure/azure-sdk-for-js/tree/master/sdk/storage/storage-blob/samples/typescript/src/iterators-containers.ts +[proxyauth]: https://github.com/Azure/azure-sdk-for-js/tree/master/sdk/storage/storage-blob/samples/typescript/src/proxyAuth.ts +[readingsnapshot]: https://github.com/Azure/azure-sdk-for-js/tree/master/sdk/storage/storage-blob/samples/typescript/src/readingSnapshot.ts +[sharedkeycred]: https://github.com/Azure/azure-sdk-for-js/tree/master/sdk/storage/storage-blob/samples/typescript/src/sharedKeyCred.ts +[withconnstring]: https://github.com/Azure/azure-sdk-for-js/tree/master/sdk/storage/storage-blob/samples/typescript/src/withConnString.ts +[apiref]: https://docs.microsoft.com/javascript/api/@azure/storage-blob +[azstorage]: https://docs.microsoft.com/azure/storage/common/storage-account-overview +[freesub]: https://azure.microsoft.com/free/ +[package]: https://github.com/Azure/azure-sdk-for-js/tree/master/sdk/storage/storage-blob/README.md +[typescript]: https://www.typescriptlang.org/docs/home.html diff --git a/sdk/storage/storage-blob/samples/typescript/package.json b/sdk/storage/storage-blob/samples/typescript/package.json new file mode 100644 index 000000000000..11748303b62f --- /dev/null +++ b/sdk/storage/storage-blob/samples/typescript/package.json @@ -0,0 +1,44 @@ +{ + "name": "azure-storage-blob-samples-ts", + "private": true, + "version": "0.1.0", + "description": "Azure Storage Blob client library samples for TypeScript", + "engine": { + "node": ">=8.0.0" + }, + "scripts": { + "build": "tsc", + "prebuild": "rimraf dist/" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/Azure/azure-sdk-for-js.git" + }, + "keywords": [ + "Azure", + "Storage", + "Blob", + "Node.js", + "TypeScript" + ], + "author": "Microsoft Corporation", + "license": "MIT", + "bugs": { + "url": "https://github.com/Azure/azure-sdk-for-js/issues" + }, + "homepage": "https://github.com/Azure/azure-sdk-for-js#readme", + "sideEffects": false, + "dependencies": { + "@azure/abort-controller": "latest", + "@azure/identity": "latest", + "@azure/storage-blob": "latest", + "dotenv": "^8.2.0" + }, + "devDependencies": { + "@types/node": "^8.0.0", + "cross-env": "^6.0.3", + "rimraf": "^3.0.0", + "ts-node": "^8.3.0", + "typescript": "~3.6.4" + } +} diff --git a/sdk/storage/storage-blob/samples/typescript/sample.env b/sdk/storage/storage-blob/samples/typescript/sample.env new file mode 100644 index 000000000000..92a81cac6547 --- /dev/null +++ b/sdk/storage/storage-blob/samples/typescript/sample.env @@ -0,0 +1,20 @@ +# Used in most samples. Retrieve these values from a storage account in the Azure Portal. +ACCOUNT_NAME= +ACCOUNT_KEY= + +# Used for withConnString +STORAGE_CONNECTION_STRING= + +# Used for the advanced and anonymousCred tests. Create a SAS token for a storage account in the Azure Portal. +ACCOUNT_SAS= + +# Used to authenticate using Azure AD as a service principal for role-based authentication. +# +# See the documentation for `EnvironmentCredential` at the following link: +# https://docs.microsoft.com/javascript/api/@azure/identity/environmentcredential +AZURE_TENANT_ID= +AZURE_CLIENT_ID= +AZURE_CLIENT_SECRET= + +# To run the proxyAuth sample, set up an HTTP proxy and enter your information: +# HTTP_PROXY=http://localhost:3128 diff --git a/sdk/storage/storage-blob/samples/typescript/advanced.ts b/sdk/storage/storage-blob/samples/typescript/src/advanced.ts similarity index 92% rename from sdk/storage/storage-blob/samples/typescript/advanced.ts rename to sdk/storage/storage-blob/samples/typescript/src/advanced.ts index 2c0a12859f13..45749d72b489 100644 --- a/sdk/storage/storage-blob/samples/typescript/advanced.ts +++ b/sdk/storage/storage-blob/samples/typescript/src/advanced.ts @@ -1,10 +1,13 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + /* Setup: Enter your storage account name, SAS and a path pointing to local file in main() */ -import fs from "fs"; +import * as fs from "fs"; import { AbortController } from "@azure/abort-controller"; -import { AnonymousCredential, BlobServiceClient, newPipeline } from "../../src"; // Change to "@azure/storage-blob" in your package +import { AnonymousCredential, BlobServiceClient, newPipeline } from "@azure/storage-blob"; // Enabling logging may help uncover useful information about failures. // In order to see a log of HTTP requests and responses, set the `AZURE_LOG_LEVEL` environment variable to `info`. @@ -13,11 +16,11 @@ import { AnonymousCredential, BlobServiceClient, newPipeline } from "../../src"; import { setLogLevel } from "@azure/logger"; setLogLevel("info"); -async function main() { +export async function main() { // Fill in following settings before running this sample const account = process.env.ACCOUNT_NAME || ""; const accountSas = process.env.ACCOUNT_SAS || ""; - const localFilePath = "../README.md"; + const localFilePath = "README.md"; const pipeline = newPipeline(new AnonymousCredential(), { // httpClient: MyHTTPClient, // A customized HTTP client implementing IHttpClient interface @@ -127,11 +130,6 @@ async function main() { console.log("deleted container"); } -// An async method returns a Promise object, which is compatible with then().catch() coding style. -main() - .then(() => { - console.log("Successfully executed sample."); - }) - .catch((err) => { - console.log(err.message); - }); +main().catch((err) => { + console.error("Error running sample:", err.message); +}); diff --git a/sdk/storage/storage-blob/samples/typescript/anonymousCred.ts b/sdk/storage/storage-blob/samples/typescript/src/anonymousCred.ts similarity index 75% rename from sdk/storage/storage-blob/samples/typescript/anonymousCred.ts rename to sdk/storage/storage-blob/samples/typescript/src/anonymousCred.ts index f8919c17eafb..d743ed1ecc9b 100644 --- a/sdk/storage/storage-blob/samples/typescript/anonymousCred.ts +++ b/sdk/storage/storage-blob/samples/typescript/src/anonymousCred.ts @@ -1,10 +1,13 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + /* Setup: Enter your storage account name and SAS in main() */ -import { BlobServiceClient, AnonymousCredential } from "../../src"; // Change to "@azure/storage-blob" in your package +import { BlobServiceClient, AnonymousCredential } from "@azure/storage-blob"; -async function main() { +export async function main() { // Enter your storage account name and SAS const account = process.env.ACCOUNT_NAME || ""; const accountSas = process.env.ACCOUNT_SAS || ""; @@ -37,11 +40,6 @@ async function main() { console.log("deleted container"); } -// An async method returns a Promise object, which is compatible with then().catch() coding style. -main() - .then(() => { - console.log("Successfully executed sample."); - }) - .catch((err) => { - console.log(err.message); - }); +main().catch((err) => { + console.error("Error running sample:", err.message); +}); diff --git a/sdk/storage/storage-blob/samples/typescript/azureAdAuth.ts b/sdk/storage/storage-blob/samples/typescript/src/azureAdAuth.ts similarity index 83% rename from sdk/storage/storage-blob/samples/typescript/azureAdAuth.ts rename to sdk/storage/storage-blob/samples/typescript/src/azureAdAuth.ts index e159ae373d70..ae8cd0e9ae13 100644 --- a/sdk/storage/storage-blob/samples/typescript/azureAdAuth.ts +++ b/sdk/storage/storage-blob/samples/typescript/src/azureAdAuth.ts @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + /* ONLY AVAILABLE IN NODE.JS RUNTIME @@ -18,13 +21,25 @@ - Make sure you have AZURE_TENANT_ID, AZURE_CLIENT_ID, AZURE_CLIENT_SECRET as environment variables to successfully execute the sample(Can leverage process.env). */ -import { BlobServiceClient } from "../../src"; // Change to "@azure/storage-blob" in your package +import { BlobServiceClient } from "@azure/storage-blob"; import { DefaultAzureCredential } from "@azure/identity"; -async function main() { +export async function main() { // Enter your storage account name const account = process.env.ACCOUNT_NAME || ""; + // Azure AD Credential information is required to run this sample: + if ( + !process.env.AZURE_TENANT_ID || + !process.env.AZURE_CLIENT_ID || + !process.env.AZURE_CLIENT_SECRET + ) { + console.warn( + "Azure AD authentication information not provided, but it is required to run this sample. Exiting." + ); + return; + } + // ONLY AVAILABLE IN NODE.JS RUNTIME // DefaultAzureCredential will first look for Azure Active Directory (AAD) // client secret credentials in the following environment variables: @@ -51,11 +66,6 @@ async function main() { console.log(`Created container ${containerName} successfully`, createContainerResponse.requestId); } -// An async method returns a Promise object, which is compatible with then().catch() coding style. -main() - .then(() => { - console.log("Successfully executed the sample."); - }) - .catch((err) => { - console.log(err.message); - }); +main().catch((err) => { + console.error("Error running sample:", err.message); +}); diff --git a/sdk/storage/storage-blob/samples/typescript/basic.ts b/sdk/storage/storage-blob/samples/typescript/src/basic.ts similarity index 90% rename from sdk/storage/storage-blob/samples/typescript/basic.ts rename to sdk/storage/storage-blob/samples/typescript/src/basic.ts index 6ef1c2e7d155..f13e5e8789cb 100644 --- a/sdk/storage/storage-blob/samples/typescript/basic.ts +++ b/sdk/storage/storage-blob/samples/typescript/src/basic.ts @@ -1,10 +1,17 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + /* Setup: Enter your storage account name and shared key in main() */ -import { BlobServiceClient, StorageSharedKeyCredential, BlobDownloadResponseModel } from "../../src"; // Change to "@azure/storage-blob" in your package +import { + BlobServiceClient, + StorageSharedKeyCredential, + BlobDownloadResponseModel +} from "@azure/storage-blob"; -async function main() { +export async function main() { // Enter your storage account name and shared key const account = process.env.ACCOUNT_NAME || ""; const accountKey = process.env.ACCOUNT_KEY || ""; @@ -94,11 +101,6 @@ async function streamToString(readableStream: NodeJS.ReadableStream) { }); } -// An async method returns a Promise object, which is compatible with then().catch() coding style. -main() - .then(() => { - console.log("Successfully executed sample."); - }) - .catch((err) => { - console.log(err.message); - }); +main().catch((err) => { + console.error("Error running sample:", err.message); +}); diff --git a/sdk/storage/storage-blob/samples/typescript/customPipeline.ts b/sdk/storage/storage-blob/samples/typescript/src/customPipeline.ts similarity index 83% rename from sdk/storage/storage-blob/samples/typescript/customPipeline.ts rename to sdk/storage/storage-blob/samples/typescript/src/customPipeline.ts index 024a03a641d9..d1123d40911d 100644 --- a/sdk/storage/storage-blob/samples/typescript/customPipeline.ts +++ b/sdk/storage/storage-blob/samples/typescript/src/customPipeline.ts @@ -1,10 +1,13 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + /* Setup: Enter your storage account name and shared key in main() */ -import { BlobServiceClient, StorageSharedKeyCredential, newPipeline } from "../../src"; // Change to "@azure/storage-blob" in your package +import { BlobServiceClient, StorageSharedKeyCredential, newPipeline } from "@azure/storage-blob"; -async function main() { +export async function main() { // Enter your storage account name and shared key const account = process.env.ACCOUNT_NAME || ""; const accountKey = process.env.ACCOUNT_KEY || ""; @@ -44,11 +47,6 @@ async function main() { console.log("deleted container"); } -// An async method returns a Promise object, which is compatible with then().catch() coding style. -main() - .then(() => { - console.log("Successfully executed sample."); - }) - .catch((err) => { - console.log(err.message); - }); +main().catch((err) => { + console.error("Error running sample:", err.message); +}); diff --git a/sdk/storage/storage-blob/samples/typescript/customizedClientHeaders.ts b/sdk/storage/storage-blob/samples/typescript/src/customizedClientHeaders.ts similarity index 88% rename from sdk/storage/storage-blob/samples/typescript/customizedClientHeaders.ts rename to sdk/storage/storage-blob/samples/typescript/src/customizedClientHeaders.ts index f8e9dc41daba..eaef5ec8bd8e 100644 --- a/sdk/storage/storage-blob/samples/typescript/customizedClientHeaders.ts +++ b/sdk/storage/storage-blob/samples/typescript/src/customizedClientHeaders.ts @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + /* You can create your own policy and inject it into the default pipeline, or create your own Pipeline. A request policy is a filter triggered before and after a HTTP request. With a filter, we can tweak HTTP requests and responses. @@ -17,7 +20,7 @@ import { WebResource, RequestPolicy, RequestPolicyOptions -} from "../../src"; // Change to "@azure/storage-blob" in your package +} from "@azure/storage-blob"; // Create a policy factory with create() method provided class RequestIDPolicyFactory { @@ -60,7 +63,7 @@ class RequestIDPolicy extends BaseRequestPolicy { } // Main function -async function main() { +export async function main() { const account = process.env.ACCOUNT_NAME || ""; const accountSas = process.env.ACCOUNT_SAS || ""; @@ -74,17 +77,17 @@ async function main() { `https://${account}.blob.core.windows.net${accountSas}`, pipeline ); - const response = (await blobServiceClient - .listContainers() - .byPage() - .next()).value; + const response = ( + await blobServiceClient + .listContainers() + .byPage() + .next() + ).value; // Check customized client request ID console.log(response._response.request.headers.get("x-ms-client-request-id")); } -main() - .then(() => { - console.log("Successfully executed sample"); - }) - .catch(console.error); +main().catch((err) => { + console.error("Error running sample:", err.message); +}); diff --git a/sdk/storage/storage-blob/samples/typescript/errorsAndResponses.ts b/sdk/storage/storage-blob/samples/typescript/src/errorsAndResponses.ts similarity index 94% rename from sdk/storage/storage-blob/samples/typescript/errorsAndResponses.ts rename to sdk/storage/storage-blob/samples/typescript/src/errorsAndResponses.ts index d83f8c80ad57..ff53ca26233c 100644 --- a/sdk/storage/storage-blob/samples/typescript/errorsAndResponses.ts +++ b/sdk/storage/storage-blob/samples/typescript/src/errorsAndResponses.ts @@ -1,10 +1,13 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + /* Setup: Enter connection string of your storage account name in main() */ -import { BlobServiceClient } from "../../src"; // Change to "@azure/storage-blob" in your package +import { BlobServiceClient } from "@azure/storage-blob"; -async function main() { +export async function main() { // Create Blob Service Client from Account connection string or SAS connection string // Account connection string example - `DefaultEndpointsProtocol=https;AccountName=myaccount;AccountKey=accountKey;EndpointSuffix=core.windows.net` // SAS connection string example - `BlobEndpoint=https://myaccount.blob.core.windows.net/;QueueEndpoint=https://myaccount.queue.core.windows.net/;FileEndpoint=https://myaccount.file.core.windows.net/;TableEndpoint=https://myaccount.table.core.windows.net/;SharedAccessSignature=sasString` @@ -145,11 +148,6 @@ async function streamToString(readableStream: NodeJS.ReadableStream) { }); } -// An async method returns a Promise object, which is compatible with then().catch() coding style. -main() - .then(() => { - console.log("\n\nSuccessfully executed sample."); - }) - .catch((err) => { - console.log(err.message); - }); +main().catch((err) => { + console.error("Error running sample:", err.message); +}); diff --git a/sdk/storage/storage-blob/samples/typescript/iterators-blobs-hierarchy.ts b/sdk/storage/storage-blob/samples/typescript/src/iterators-blobs-hierarchy.ts similarity index 92% rename from sdk/storage/storage-blob/samples/typescript/iterators-blobs-hierarchy.ts rename to sdk/storage/storage-blob/samples/typescript/src/iterators-blobs-hierarchy.ts index 7300db67379c..2cda531e30b2 100644 --- a/sdk/storage/storage-blob/samples/typescript/iterators-blobs-hierarchy.ts +++ b/sdk/storage/storage-blob/samples/typescript/src/iterators-blobs-hierarchy.ts @@ -1,10 +1,13 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + /* Setup: Enter your storage account name and shared key in main() */ -import { BlobServiceClient, StorageSharedKeyCredential } from "../../src"; // Change to "@azure/storage-blob" in your package +import { BlobServiceClient, StorageSharedKeyCredential } from "@azure/storage-blob"; -async function main() { +export async function main() { // Enter your storage account name and shared key const account = process.env.ACCOUNT_NAME || ""; const accountKey = process.env.ACCOUNT_KEY || ""; @@ -131,11 +134,6 @@ async function main() { console.log("deleted container"); } -// An async method returns a Promise object, which is compatible with then().catch() coding style. -main() - .then(() => { - console.log("Successfully executed the sample."); - }) - .catch((err) => { - console.log(err.message); - }); +main().catch((err) => { + console.error("Error running sample:", err.message); +}); diff --git a/sdk/storage/storage-blob/samples/typescript/iterators-blobs.ts b/sdk/storage/storage-blob/samples/typescript/src/iterators-blobs.ts similarity index 91% rename from sdk/storage/storage-blob/samples/typescript/iterators-blobs.ts rename to sdk/storage/storage-blob/samples/typescript/src/iterators-blobs.ts index b443ae27020e..383b3dd7775a 100644 --- a/sdk/storage/storage-blob/samples/typescript/iterators-blobs.ts +++ b/sdk/storage/storage-blob/samples/typescript/src/iterators-blobs.ts @@ -1,10 +1,13 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + /* Setup: Enter your storage account name and shared key in main() */ -import { BlobServiceClient, StorageSharedKeyCredential } from "../../src"; // Change to "@azure/storage-blob" in your package +import { BlobServiceClient, StorageSharedKeyCredential } from "@azure/storage-blob"; -async function main() { +export async function main() { // Enter your storage account name and shared key const account = process.env.ACCOUNT_NAME || ""; const accountKey = process.env.ACCOUNT_KEY || ""; @@ -122,11 +125,6 @@ async function main() { console.log("deleted container"); } -// An async method returns a Promise object, which is compatible with then().catch() coding style. -main() - .then(() => { - console.log("Successfully executed the sample."); - }) - .catch((err) => { - console.log(err.message); - }); +main().catch((err) => { + console.error("Error running sample:", err.message); +}); diff --git a/sdk/storage/storage-blob/samples/typescript/iterators-containers.ts b/sdk/storage/storage-blob/samples/typescript/src/iterators-containers.ts similarity index 89% rename from sdk/storage/storage-blob/samples/typescript/iterators-containers.ts rename to sdk/storage/storage-blob/samples/typescript/src/iterators-containers.ts index 354feb380419..faf8e05eb705 100644 --- a/sdk/storage/storage-blob/samples/typescript/iterators-containers.ts +++ b/sdk/storage/storage-blob/samples/typescript/src/iterators-containers.ts @@ -1,10 +1,13 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + /* Setup: Enter your storage account name and shared key in main() */ -import { BlobServiceClient, StorageSharedKeyCredential } from "../../src"; // Change to "@azure/storage-blob" in your package +import { BlobServiceClient, StorageSharedKeyCredential } from "@azure/storage-blob"; -async function main() { +export async function main() { // Enter your storage account name and shared key const account = process.env.ACCOUNT_NAME || ""; const accountKey = process.env.ACCOUNT_KEY || ""; @@ -103,11 +106,6 @@ async function main() { } } -// An async method returns a Promise object, which is compatible with then().catch() coding style. -main() - .then(() => { - console.log("Successfully executed the sample."); - }) - .catch((err) => { - console.log(err.message); - }); +main().catch((err) => { + console.error("Error running sample:", err.message); +}); diff --git a/sdk/storage/storage-blob/samples/typescript/proxyAuth.ts b/sdk/storage/storage-blob/samples/typescript/src/proxyAuth.ts similarity index 51% rename from sdk/storage/storage-blob/samples/typescript/proxyAuth.ts rename to sdk/storage/storage-blob/samples/typescript/src/proxyAuth.ts index 43a3e29a4f25..59082a866743 100644 --- a/sdk/storage/storage-blob/samples/typescript/proxyAuth.ts +++ b/sdk/storage/storage-blob/samples/typescript/src/proxyAuth.ts @@ -1,10 +1,13 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + /* Setup: Enter your storage account name and shared key in main() */ -import { BlobServiceClient, StorageSharedKeyCredential } from "../../src"; // Change to "@azure/storage-blob" in your package +import { BlobServiceClient, StorageSharedKeyCredential } from "@azure/storage-blob"; -async function main() { +export async function main() { // Enter your storage account name and shared key const account = process.env.ACCOUNT_NAME || ""; const accountKey = process.env.ACCOUNT_KEY || ""; @@ -13,20 +16,27 @@ async function main() { // StorageSharedKeyCredential is only avaiable in Node.js runtime, not in browsers const sharedKeyCredential = new StorageSharedKeyCredential(account, accountKey); + // To use the manual proxyOptions below, remove this block + if (!process.env.HTTP_PROXY || !process.env.HTTPS_PROXY) { + console.warn("Proxy information not provided, but it is required to run this sample. Exiting."); + return; + } + const blobServiceClient = new BlobServiceClient( `https://${account}.blob.core.windows.net`, sharedKeyCredential, + // The library tries to load the proxy settings from the environment variables like HTTP_PROXY + // Alternatively, the service client accepts the following `proxyOptions` as part of its options: { - // proxy can either be a URL like "http://localhost:3128" - // or - // an option bag consisting {host, port, username, password } - proxyOptions: { + /* + proxyOptions : { + // To use these options, remove the section above that checks for HTTP_PROXY or HTTPS_PROXY host: "http://localhost", port: 3128, - username: "username", - password: "password" + username: "", + password: "" } - // if proxy is undefined, the library tries to load the proxy settings from the environment variables like HTTP_PROXY + */ } ); @@ -38,11 +48,6 @@ async function main() { console.log(`Created container ${containerName} successfully`, createContainerResponse.requestId); } -// An async method returns a Promise object, which is compatible with then().catch() coding style. -main() - .then(() => { - console.log("Successfully executed the sample."); - }) - .catch((err) => { - console.log(err.message); - }); +main().catch((err) => { + console.error("Error running sample:", err.message); +}); diff --git a/sdk/storage/storage-blob/samples/typescript/readingSnapshot.ts b/sdk/storage/storage-blob/samples/typescript/src/readingSnapshot.ts similarity index 89% rename from sdk/storage/storage-blob/samples/typescript/readingSnapshot.ts rename to sdk/storage/storage-blob/samples/typescript/src/readingSnapshot.ts index 396d34b69597..4d212eaecd20 100644 --- a/sdk/storage/storage-blob/samples/typescript/readingSnapshot.ts +++ b/sdk/storage/storage-blob/samples/typescript/src/readingSnapshot.ts @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + /* If you use BlobClient.download() to download an append blob which is being actively appended, you may get a 412 HTTP error, just like this issue: https://github.com/Azure/azure-storage-js/issues/51 @@ -18,9 +21,9 @@ Setup: Enter your storage account name and shared key in main() */ -import { BlobServiceClient, StorageSharedKeyCredential } from "../../src"; // Change to "@azure/storage-blob" in your package +import { BlobServiceClient, StorageSharedKeyCredential } from "@azure/storage-blob"; -async function main() { +export async function main() { // Enter your storage account name and shared key const account = process.env.ACCOUNT_NAME || ""; const accountKey = process.env.ACCOUNT_KEY || ""; @@ -82,11 +85,6 @@ async function streamToString(readableStream: NodeJS.ReadableStream) { }); } -// An async method returns a Promise object, which is compatible with then().catch() coding style. -main() - .then(() => { - console.log("Successfully executed sample."); - }) - .catch((err) => { - console.log(err.message); - }); +main().catch((err) => { + console.error("Error running sample:", err.message); +}); diff --git a/sdk/storage/storage-blob/samples/typescript/sharedKeyCred.ts b/sdk/storage/storage-blob/samples/typescript/src/sharedKeyCred.ts similarity index 75% rename from sdk/storage/storage-blob/samples/typescript/sharedKeyCred.ts rename to sdk/storage/storage-blob/samples/typescript/src/sharedKeyCred.ts index 9de6e9bd9908..7680c443b72a 100644 --- a/sdk/storage/storage-blob/samples/typescript/sharedKeyCred.ts +++ b/sdk/storage/storage-blob/samples/typescript/src/sharedKeyCred.ts @@ -1,10 +1,13 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + /* Setup: Enter your storage account name and shared key in main() */ -import { BlobServiceClient, StorageSharedKeyCredential } from "../../src"; // Change to "@azure/storage-blob" in your package +import { BlobServiceClient, StorageSharedKeyCredential } from "@azure/storage-blob"; -async function main() { +export async function main() { // Enter your storage account name and shared key const account = process.env.ACCOUNT_NAME || ""; const accountKey = process.env.ACCOUNT_KEY || ""; @@ -37,11 +40,6 @@ async function main() { console.log("deleted container"); } -// An async method returns a Promise object, which is compatible with then().catch() coding style. -main() - .then(() => { - console.log("Successfully executed sample."); - }) - .catch((err) => { - console.log(err.message); - }); +main().catch((err) => { + console.error("Error running sample:", err.message); +}); diff --git a/sdk/storage/storage-blob/samples/typescript/withConnString.ts b/sdk/storage/storage-blob/samples/typescript/src/withConnString.ts similarity index 79% rename from sdk/storage/storage-blob/samples/typescript/withConnString.ts rename to sdk/storage/storage-blob/samples/typescript/src/withConnString.ts index 72f49ce0175f..594c5dcb4d78 100644 --- a/sdk/storage/storage-blob/samples/typescript/withConnString.ts +++ b/sdk/storage/storage-blob/samples/typescript/src/withConnString.ts @@ -1,10 +1,13 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + /* Setup: Enter your storage account name and shared key in main() */ -import { BlobServiceClient } from "../../src"; // Change to "@azure/storage-blob" in your package +import { BlobServiceClient } from "@azure/storage-blob"; -async function main() { +export async function main() { // Create Blob Service Client from Account connection string or SAS connection string // Account connection string example - `DefaultEndpointsProtocol=https;AccountName=myaccount;AccountKey=accountKey;EndpointSuffix=core.windows.net` // SAS connection string example - `BlobEndpoint=https://myaccount.blob.core.windows.net/;QueueEndpoint=https://myaccount.queue.core.windows.net/;FileEndpoint=https://myaccount.file.core.windows.net/;TableEndpoint=https://myaccount.table.core.windows.net/;SharedAccessSignature=sasString` @@ -30,11 +33,6 @@ async function main() { console.log("deleted container"); } -// An async method returns a Promise object, which is compatible with then().catch() coding style. -main() - .then(() => { - console.log("Successfully executed sample."); - }) - .catch((err) => { - console.log(err.message); - }); +main().catch((err) => { + console.error("Error running sample:", err.message); +}); diff --git a/sdk/storage/storage-blob/samples/typescript/tsconfig.json b/sdk/storage/storage-blob/samples/typescript/tsconfig.json new file mode 100644 index 000000000000..4332663bf7b7 --- /dev/null +++ b/sdk/storage/storage-blob/samples/typescript/tsconfig.json @@ -0,0 +1,15 @@ +{ + "compilerOptions": { + "module": "commonjs", + "moduleResolution": "node", + + "lib": ["dom", "dom.iterable", "esnext.asynciterable"], + + "allowSyntheticDefaultImports": true, + + "outDir": "dist", + "rootDir": "src" + }, + "include": ["src/**.ts"], + "exclude": ["node_modules"] +} diff --git a/sdk/storage/storage-file-share/execute-samples.js b/sdk/storage/storage-file-share/execute-samples.js deleted file mode 100644 index aa77c71f12be..000000000000 --- a/sdk/storage/storage-file-share/execute-samples.js +++ /dev/null @@ -1,80 +0,0 @@ -const execa = require("execa"); -const fs = require("fs"); -require("dotenv").config({ path: "../.env" }); - -// Samples can be skipped by mentioning them in the skipSamples Array. -// Suppose skipSamples = ["some-entry", "sample-2"], -// some-entry.ts, sample-2.ts, some-entry.js and sample-2.js will be skipped. -const skipSamples = ["proxyAuth"]; - -const bDel = `!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!`; -const del = `${bDel}------------------------------${bDel}`; - -// Colours - green, yellow, red and blue - for console logs. -const { g, y, r, b } = [["r", 1], ["g", 2], ["b", 4], ["y", 3]].reduce( - (cols, col) => ({ - ...cols, - [col[0]]: (f) => `\x1b[3${col[1]}m${f}\x1b[0m` - }), - {} -); - -// Executes `cmd` in `cwd`(directory). -async function exec(cmd, cwd) { - let command = execa(cmd, { - cwd, - shell: true - }); - command.stderr.pipe(process.stderr); - command.stdout.pipe(process.stdout); - return command; -} - -async function runSamples(language) { - let cmd; - // Tries to execute all the samples in the `directory`. - const directory = `./samples/${language}`; - - if (language === "typescript") { - cmd = "ts-node"; - } else { - cmd = "node"; - await exec(`npm run build:js-samples`, directory); - } - - console.log(`Running ${language} samples...`); - - const files = fs.readdirSync(directory); - - for (var i = 0; i < files.length; i++) { - if (!skipSamples.includes(files[i].split(".")[0])) { - try { - console.log(`\n\n${b(del)}\n${del}`); - console.log(`${bDel}\t${files[i]} \t `); - console.log(`${del}\n${b(del)} \n`); - - console.log(`${g("Running")} ${y(files[i])} ${g("...")}`); - // Executing a sample - Example: (`ts-node samplefilename.ts`, `./samples/typescript`). - await exec(`${cmd} ${files[i]}`, directory); - console.log(`${g(files[i] + " is done..!")}`); - } catch (error) { - console.log(error.message); - console.log(`${r(del)}\n${del}`); - console.log(`${bDel}\t${files[i]} Sample - FAILED\t `); - console.log(`${del}\n${r(del)}`); - } - } - } -} - -(async () => { - try { - await runSamples("typescript"); - await runSamples("javascript"); - process.exit(0); - } catch (error) { - console.log("Samples failed!"); - console.log(error); - process.exit(1); - } -})(); diff --git a/sdk/storage/storage-file-share/package.json b/sdk/storage/storage-file-share/package.json index c318ce500e48..02cdefcb9d66 100644 --- a/sdk/storage/storage-file-share/package.json +++ b/sdk/storage/storage-file-share/package.json @@ -23,15 +23,17 @@ "build:autorest": "autorest ./swagger/README.md --typescript --package-version=12.0.0-preview.7 --use=@microsoft.azure/autorest.typescript@5.0.1", "build:es6": "tsc -p tsconfig.json", "build:nodebrowser": "rollup -c 2>&1", - "build:js-samples": "npm run clean && npm run build:es6 && cross-env ONLY_NODE=true rollup -c 2>&1", - "build:ts-samples": "npm run clean && node ../../../common/scripts/prep-samples.js && cd samples && tsc -p . ", + "build:samples": "npm run clean && npm run build:es6 && cross-env ONLY_NODE=true rollup -c 2>&1 && npm run build:prep-samples", + "build:prep-samples": "node ../../../common/scripts/prep-samples.js && cd samples && tsc", "build:test": "npm run build:es6 && rollup -c rollup.test.config.js 2>&1", "build": "npm run build:es6 && npm run build:nodebrowser && api-extractor run --local", "check-format": "prettier --list-different --config ../../.prettierrc.json \"src/**/*.ts\" \"test/**/*.ts\" \"*.{js,json}\"", "clean": "rimraf dist dist-esm dist-test typings temp browser/*.js* browser/*.zip statistics.html coverage coverage-browser .nyc_output *.tgz *.log test*.xml TEST*.xml", - "clean:samples": "rimraf samples/javascript/node_modules samples/typescript/node_modules samples/typescript/dist", + "clean:samples": "rimraf samples/javascript/node_modules samples/typescript/node_modules samples/typescript/dist samples/typescript/package-lock.json samples/javascript/package-lock.json", "extract-api": "tsc -p . && api-extractor run --local", - "execute:samples": "echo skipped for now due to https://github.com/Azure/azure-sdk-for-js/issues/6362", + "execute:js-samples": "node ../../../common/scripts/run-samples.js samples/javascript/", + "execute:ts-samples": "node ../../../common/scripts/run-samples.js samples/typescript/dist/samples/typescript/src/", + "execute:samples": "npm run build:samples && npm run execute:js-samples && npm run execute:ts-samples", "format": "prettier --write --config ../../.prettierrc.json \"src/**/*.ts\" \"test/**/*.ts\" \"*.{js,json}\"", "integration-test:browser": "karma start --single-run", "integration-test:node": "nyc mocha --require source-map-support/register --reporter mocha-multi --reporter-options spec=-,mocha-junit-reporter=- --full-trace -t 120000 --retries 2 dist-test/index.node.js", diff --git a/sdk/storage/storage-file-share/samples/javascript/README.md b/sdk/storage/storage-file-share/samples/javascript/README.md index 98bff075ab3a..89a8b2a9c38d 100644 --- a/sdk/storage/storage-file-share/samples/javascript/README.md +++ b/sdk/storage/storage-file-share/samples/javascript/README.md @@ -29,7 +29,7 @@ These sample programs show how to use the JavaScript client libraries for Azure The sample are compatible with Node.js >= 8.0.0, except for the samples that use the async `for await` syntax, which require Node.js >= 10.0.0. -You need [an Azure subscription][freesub] and [an Azure Storage account][azstorage] to run these sample programs. Samples retrieve credentials to access the storage account from environment variables. See each individual sample for details on which environment variables it requires to function. +You need [an Azure subscription][freesub] and [an Azure Storage account][azstorage] to run these sample programs. Samples retrieve credentials to access the storage account from environment variables. Alternatively, edit the source code to include the appropriate credentials. See each individual sample for details on which environment variables/credentials it requires to function. Adapting the samples to run in the browser requires some additional consideration. For details, please see the [package README][package]. @@ -43,7 +43,15 @@ To run the samples using the published version of the package: npm install ``` -2. Run the sample with the correct environment variables set, for example (cross-platform): +2. Edit the file `sample.env`, adding the correct credentials to access the Azure service and run the samples. Then rename the file from `sample.env` to just `.env`. The sample programs will read this file automatically. + +3. Run whichever samples you like (note that some samples may require additional setup, see the table above): + +```bash +node basic.js +``` + +Alternatively, run a single sample with the correct environment variables set (step 3 is not required if you do this), for example (cross-platform): ```bash npx cross-env ACCOUNT_NAME="" ACCOUNT_KEY="" node basic.js diff --git a/sdk/storage/storage-file-share/samples/javascript/advanced.js b/sdk/storage/storage-file-share/samples/javascript/advanced.js index 50f11b81f0e5..c209f0271064 100644 --- a/sdk/storage/storage-file-share/samples/javascript/advanced.js +++ b/sdk/storage/storage-file-share/samples/javascript/advanced.js @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + /* Setup: Enter your storage account name, SAS and a path pointing to local file in main() */ @@ -21,7 +24,7 @@ async function main() { // Fill in following settings before running this sample const account = process.env.ACCOUNT_NAME || ""; const accountSas = process.env.ACCOUNT_SAS || ""; - const localFilePath = "../README.md"; + const localFilePath = "README.md"; const pipeline = newPipeline(new AnonymousCredential(), { // httpClient: MyHTTPClient, // A customized HTTP client implementing IHttpClient interface @@ -99,11 +102,8 @@ async function main() { console.log("deleted share"); } -// An async method returns a Promise object, which is compatible with then().catch() coding style. -main() - .then(() => { - console.log("Successfully executed sample."); - }) - .catch((err) => { - console.log(err.message); - }); +module.exports = { main }; + +main().catch((err) => { + console.error("Error running sample:", err.message); +}); diff --git a/sdk/storage/storage-file-share/samples/javascript/anonymousCred.js b/sdk/storage/storage-file-share/samples/javascript/anonymousCred.js index 5b129ffd90bd..5f1d04dd36ef 100644 --- a/sdk/storage/storage-file-share/samples/javascript/anonymousCred.js +++ b/sdk/storage/storage-file-share/samples/javascript/anonymousCred.js @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + /* Setup: Enter your storage account name and SAS in main() */ @@ -36,11 +39,8 @@ async function main() { console.log(`deleted share ${shareName}`); } -// An async method returns a Promise object, which is compatible with then().catch() coding style. -main() - .then(() => { - console.log("Successfully executed sample."); - }) - .catch((err) => { - console.log(err.message); - }); +module.exports = { main }; + +main().catch((err) => { + console.error("Error running sample:", err.message); +}); diff --git a/sdk/storage/storage-file-share/samples/javascript/basic.js b/sdk/storage/storage-file-share/samples/javascript/basic.js index 9a454e33cd8b..ee24fdf092dd 100644 --- a/sdk/storage/storage-file-share/samples/javascript/basic.js +++ b/sdk/storage/storage-file-share/samples/javascript/basic.js @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + /* Setup: Enter your storage account name and shared key in main() */ @@ -90,11 +93,8 @@ async function streamToString(readableStream) { }); } -// An async method returns a Promise object, which is compatible with then().catch() coding style. -main() - .then(() => { - console.log("Successfully executed sample."); - }) - .catch((err) => { - console.log(err.message); - }); +module.exports = { main }; + +main().catch((err) => { + console.error("Error running sample:", err.message); +}); diff --git a/sdk/storage/storage-file-share/samples/javascript/customPipeline.js b/sdk/storage/storage-file-share/samples/javascript/customPipeline.js index 977d9b19ae49..26dce67e53a6 100644 --- a/sdk/storage/storage-file-share/samples/javascript/customPipeline.js +++ b/sdk/storage/storage-file-share/samples/javascript/customPipeline.js @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + /* Setup: Enter your storage account name and shared key in main() */ @@ -47,11 +50,8 @@ async function main() { console.log(`deleted share ${shareName}`); } -// An async method returns a Promise object, which is compatible with then().catch() coding style. -main() - .then(() => { - console.log("Successfully executed sample."); - }) - .catch((err) => { - console.log(err.message); - }); +module.exports = { main }; + +main().catch((err) => { + console.error("Error running sample:", err.message); +}); diff --git a/sdk/storage/storage-file-share/samples/javascript/iterators-files-and-directories.js b/sdk/storage/storage-file-share/samples/javascript/iterators-files-and-directories.js index a18648ccb2bd..e5eb7c0496b7 100644 --- a/sdk/storage/storage-file-share/samples/javascript/iterators-files-and-directories.js +++ b/sdk/storage/storage-file-share/samples/javascript/iterators-files-and-directories.js @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + /* Setup: Enter your storage account name and shared key in main() */ @@ -157,11 +160,8 @@ async function main() { console.log(`deleted share ${shareName}`); } -// An async method returns a Promise object, which is compatible with then().catch() coding style. -main() - .then(() => { - console.log("Successfully executed sample."); - }) - .catch((err) => { - console.log(err.message); - }); +module.exports = { main }; + +main().catch((err) => { + console.error("Error running sample:", err.message); +}); diff --git a/sdk/storage/storage-file-share/samples/javascript/iterators-handles.js b/sdk/storage/storage-file-share/samples/javascript/iterators-handles.js index b7a55898b2ae..963611f1fc6b 100644 --- a/sdk/storage/storage-file-share/samples/javascript/iterators-handles.js +++ b/sdk/storage/storage-file-share/samples/javascript/iterators-handles.js @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + /* Setup: Enter your storage account name and shared key in main() */ @@ -12,8 +15,15 @@ async function main() { // https://docs.microsoft.com/en-us/azure/storage/files/storage-how-to-use-files-mac const account = process.env.ACCOUNT_NAME || ""; const accountKey = process.env.ACCOUNT_KEY || ""; - const shareName = ""; - const dirName = ""; + const shareName = process.env.SHARE_NAME || ""; + const dirName = process.env.DIR_NAME || ""; + + if (shareName === "" || dirName === "") { + console.warn( + "Share/directory information not provided, but it is required to run this sample. Exiting." + ); + return; + } // Use StorageSharedKeyCredential with storage account and account key // StorageSharedKeyCredential is only avaiable in Node.js runtime, not in browsers @@ -150,11 +160,8 @@ async function main() { } } -// An async method returns a Promise object, which is compatible with then().catch() coding style. -main() - .then(() => { - console.log("Successfully executed sample."); - }) - .catch((err) => { - console.log(err.message); - }); +module.exports = { main }; + +main().catch((err) => { + console.error("Error running sample:", err.message); +}); diff --git a/sdk/storage/storage-file-share/samples/javascript/iterators-shares.js b/sdk/storage/storage-file-share/samples/javascript/iterators-shares.js index 13c7deaedb5a..77821b82a0ac 100644 --- a/sdk/storage/storage-file-share/samples/javascript/iterators-shares.js +++ b/sdk/storage/storage-file-share/samples/javascript/iterators-shares.js @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + /* Setup: Enter your storage account name and shared key in main() */ @@ -102,11 +105,8 @@ async function main() { } } -// An async method returns a Promise object, which is compatible with then().catch() coding style. -main() - .then(() => { - console.log("Successfully executed sample."); - }) - .catch((err) => { - console.log(err.message); - }); +module.exports = { main }; + +main().catch((err) => { + console.error("Error running sample:", err.message); +}); diff --git a/sdk/storage/storage-file-share/samples/javascript/package.json b/sdk/storage/storage-file-share/samples/javascript/package.json index aa33f87c82c2..6e58f95bb61e 100644 --- a/sdk/storage/storage-file-share/samples/javascript/package.json +++ b/sdk/storage/storage-file-share/samples/javascript/package.json @@ -1,15 +1,11 @@ { - "name": "azure-file-share-samples-js", + "name": "azure-storage-file-share-samples-js", "private": true, "version": "0.1.0", "description": "Azure Storage File Share client library samples for TypeScript", "engine": { "node": ">=8.0.0" }, - "scripts": { - "build": "tsc", - "prebuild": "rimraf dist/" - }, "repository": { "type": "git", "url": "git+https://github.com/Azure/azure-sdk-for-js.git" @@ -29,12 +25,12 @@ "homepage": "https://github.com/Azure/azure-sdk-for-js#readme", "sideEffects": false, "dependencies": { - "@azure/abort-controller": "^1.0.0", - "@azure/storage-file-share": "latest" + "@azure/abort-controller": "latest", + "@azure/storage-file-share": "latest", + "dotenv": "^8.2.0" }, "devDependencies": { - "@types/node": "^8.0.0", - "rimraf": "^3.0.0", - "typescript": "~3.6.4" + "cross-env": "^6.0.3", + "rimraf": "^3.0.0" } } diff --git a/sdk/storage/storage-file-share/samples/javascript/proxyAuth.js b/sdk/storage/storage-file-share/samples/javascript/proxyAuth.js index 10e765978cae..e13be1d424df 100644 --- a/sdk/storage/storage-file-share/samples/javascript/proxyAuth.js +++ b/sdk/storage/storage-file-share/samples/javascript/proxyAuth.js @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + /* Setup: Enter your storage account name and shared key in main() */ @@ -13,20 +16,27 @@ async function main() { // StorageSharedKeyCredential is only avaiable in Node.js runtime, not in browsers const sharedKeyCredential = new StorageSharedKeyCredential(account, accountKey); + // To use the manual proxyOptions below, remove this block + if (!process.env.HTTP_PROXY || !process.env.HTTPS_PROXY) { + console.warn("Proxy information not provided, but it is required to run this sample. Exiting."); + return; + } + const serviceClient = new ShareServiceClient( `https://${account}.file.core.windows.net`, sharedKeyCredential, + // The library tries to load the proxy settings from the environment variables like HTTP_PROXY + // Alternatively, the service client accepts the following `proxyOptions` as part of its options: { - // proxy can either be a URL like "http://localhost:3128" - // or - // an option bag consisting {host, port, username, password } - proxyOptions: { + /* + proxyOptions : { + // To use these options, remove the section above that checks for HTTP_PROXY or HTTPS_PROXY host: "http://localhost", port: 3128, - username: "username", - password: "password" + username: "", + password: "" } - // if proxy is undefined, the library tries to load the proxy settings from the environment variables like HTTP_PROXY + */ } ); @@ -41,11 +51,8 @@ async function main() { console.log(`deleted share ${shareName}`); } -// An async method returns a Promise object, which is compatible with then().catch() coding style. -main() - .then(() => { - console.log("Successfully executed the sample."); - }) - .catch((err) => { - console.log(err.message); - }); +module.exports = { main }; + +main().catch((err) => { + console.error("Error running sample:", err.message); +}); diff --git a/sdk/storage/storage-file-share/samples/javascript/sample.env b/sdk/storage/storage-file-share/samples/javascript/sample.env new file mode 100644 index 000000000000..020e02500273 --- /dev/null +++ b/sdk/storage/storage-file-share/samples/javascript/sample.env @@ -0,0 +1,16 @@ +# Used in most samples. Retrieve these values from a storage account in the Azure Portal. +ACCOUNT_NAME= +ACCOUNT_KEY= + +# Used for withConnString +STORAGE_CONNECTION_STRING= + +# Used for the advanced and anonymousCred tests. Create a SAS token for a storage account in the Azure Portal. +ACCOUNT_SAS= + +# Used for iterators-handles, provide an existing share and directory name. +SHARE_NAME= +DIR_NAME= + +# To run the proxyAuth sample, set up an HTTP proxy and enter your information: +# HTTP_PROXY=http://localhost:3128 diff --git a/sdk/storage/storage-file-share/samples/javascript/sharedKeyCred.js b/sdk/storage/storage-file-share/samples/javascript/sharedKeyCred.js index 54d0e497c77c..e0a9ac7bc19d 100644 --- a/sdk/storage/storage-file-share/samples/javascript/sharedKeyCred.js +++ b/sdk/storage/storage-file-share/samples/javascript/sharedKeyCred.js @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + /* Setup: Enter your storage account name and shared key in main() */ @@ -36,11 +39,8 @@ async function main() { console.log(`deleted share ${shareName}`); } -// An async method returns a Promise object, which is compatible with then().catch() coding style. -main() - .then(() => { - console.log("Successfully executed sample."); - }) - .catch((err) => { - console.log(err.message); - }); +module.exports = { main }; + +main().catch((err) => { + console.error("Error running sample:", err.message); +}); diff --git a/sdk/storage/storage-file-share/samples/javascript/withConnString.js b/sdk/storage/storage-file-share/samples/javascript/withConnString.js index 43d394582cb6..8646d1214e59 100644 --- a/sdk/storage/storage-file-share/samples/javascript/withConnString.js +++ b/sdk/storage/storage-file-share/samples/javascript/withConnString.js @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + /* Setup: Enter your storage account name and shared key in main() */ @@ -29,11 +32,8 @@ async function main() { console.log(`deleted share ${shareName}`); } -// An async method returns a Promise object, which is compatible with then().catch() coding style. -main() - .then(() => { - console.log("Successfully executed sample."); - }) - .catch((err) => { - console.log(err.message); - }); +module.exports = { main }; + +main().catch((err) => { + console.error("Error running sample:", err.message); +}); diff --git a/sdk/storage/storage-file-share/samples/tsconfig.json b/sdk/storage/storage-file-share/samples/tsconfig.json index 375ae59feb0b..3a37abdb0902 100644 --- a/sdk/storage/storage-file-share/samples/tsconfig.json +++ b/sdk/storage/storage-file-share/samples/tsconfig.json @@ -1,8 +1,9 @@ { "extends": "../tsconfig.json", "compilerOptions": { - "module": "commonjs" + "module": "commonjs", + "outDir": "typescript/dist" }, - "include": ["typescript/**/*.ts"], + "include": ["typescript/src/**.ts"], "exclude": ["typescript/*.json", "**/node_modules/", "../node_modules", "../typings"] } diff --git a/sdk/storage/storage-file-share/samples/typescript/README.md b/sdk/storage/storage-file-share/samples/typescript/README.md index acda221d2f6c..8663bc9c120f 100644 --- a/sdk/storage/storage-file-share/samples/typescript/README.md +++ b/sdk/storage/storage-file-share/samples/typescript/README.md @@ -18,10 +18,10 @@ These sample programs show how to use the TypeScript client libraries for Azure | [withConnString.ts][withconnstring] | connect to and authenticate with the service using a connection string | | [sharedKeyCred.ts][sharedkeycred] | authenticate with the service using an account name and a shared key | | [anonymousCred.ts][anonymouscred] | authenticate with the service anonymously using a SAS URL | -| [proxyAuth.ts][proxyauth] | connect to the service using a proxy and authenticate with an account name & key | +| [proxyAuth.ts][proxyauth] | connect to the service using a proxy and authenticate with an account name & key (requires a proxy configuration) | | [iterators-shares.ts][iterators-shares] | connect to the service and iterate through the shares in the account | | [iterators-files-and-directories.ts][iterators-files-and-directories] | create a few directories and iterate through them individually (using async `for await` syntax), by page, and resume paging using a marker | -| [iterators-handles.ts][iterators-handles] | connect to the service and iterate through open handles | +| [iterators-handles.ts][iterators-handles] | connect to the service and iterate through open handles (requires a pre-existing share and directory) | | [customPipeline.ts][custompipeline] | use custom HTTP pipeline options when connecting to the service | | [advanced.ts][advanced] | use custom logging and pipeline options, then upload a local file to a share | @@ -35,7 +35,7 @@ Before running the samples in Node, they must be compiled to JavaScript using th npm install -g typescript ``` -You need [an Azure subscription][freesub] and [an Azure Storage account][azstorage] to run these sample programs. Samples retrieve credentials to access the storage account from environment variables. See each individual sample for details on which environment variables it requires to function. +You need [an Azure subscription][freesub] and [an Azure Storage account][azstorage] to run these sample programs. Samples retrieve credentials to access the storage account from environment variables. Alternatively, edit the source code to include the appropriate credentials. See each individual sample for details on which environment variables/credentials it requires to function. Adapting the samples to run in the browser requires some additional consideration. For details, please see the [package README][package]. @@ -55,7 +55,15 @@ npm install npm run build ``` -3. Run the sample with the correct environment variables set, for example (cross-platform): +3. Edit the file `sample.env`, adding the correct credentials to access the Azure service and run the samples. Then rename the file from `sample.env` to just `.env`. The sample programs will read this file automatically. + +4. Run whichever samples you like (note that some samples may require additional setup, see the table above): + +```bash +node dist/basic.js +``` + +Alternatively, run a single sample with the correct environment variables set (step 3 is not required if you do this), for example (cross-platform): ```bash npx cross-env ACCOUNT_NAME="" ACCOUNT_KEY="" node dist/basic.js @@ -65,16 +73,16 @@ npx cross-env ACCOUNT_NAME="" ACCOUNT_KEY="" node dis Take a look at our [API Documentation][apiref] for more information about the APIs that are available in the clients. -[basic]: https://github.com/Azure/azure-sdk-for-js/tree/master/sdk/storage/storage-file-share/samples/typescript/basic.ts -[proxyauth]: https://github.com/Azure/azure-sdk-for-js/tree/master/sdk/storage/storage-file-share/samples/typescript/proxyAuth.ts -[withconnstring]: https://github.com/Azure/azure-sdk-for-js/tree/master/sdk/storage/storage-file-share/samples/typescript/withConnString.ts -[iterators-files-and-directories]: https://github.com/Azure/azure-sdk-for-js/tree/master/sdk/storage/storage-file-share/samples/typescript/iterators-files-and-directories.ts -[sharedkeycred]: https://github.com/Azure/azure-sdk-for-js/tree/master/sdk/storage/storage-file-share/samples/typescript/sharedKeyCred.ts -[anonymouscred]: https://github.com/Azure/azure-sdk-for-js/tree/master/sdk/storage/storage-file-share/samples/typescript/anonymousCred.ts -[iterators-handles]: https://github.com/Azure/azure-sdk-for-js/tree/master/sdk/storage/storage-file-share/samples/typescript/iterators-handles.ts -[custompipeline]: https://github.com/Azure/azure-sdk-for-js/tree/master/sdk/storage/storage-file-share/samples/typescript/customPipeline.ts -[advanced]: https://github.com/Azure/azure-sdk-for-js/tree/master/sdk/storage/storage-file-share/samples/typescript/advanced.ts -[iterators-shares]: https://github.com/Azure/azure-sdk-for-js/tree/master/sdk/storage/storage-file-share/samples/typescript/iterators-shares.ts +[basic]: https://github.com/Azure/azure-sdk-for-js/tree/master/sdk/storage/storage-file-share/samples/typescript/src/basic.ts +[proxyauth]: https://github.com/Azure/azure-sdk-for-js/tree/master/sdk/storage/storage-file-share/samples/typescript/src/proxyAuth.ts +[withconnstring]: https://github.com/Azure/azure-sdk-for-js/tree/master/sdk/storage/storage-file-share/samples/typescript/src/withConnString.ts +[iterators-files-and-directories]: https://github.com/Azure/azure-sdk-for-js/tree/master/sdk/storage/storage-file-share/samples/typescript/src/iterators-files-and-directories.ts +[sharedkeycred]: https://github.com/Azure/azure-sdk-for-js/tree/master/sdk/storage/storage-file-share/samples/typescript/src/sharedKeyCred.ts +[anonymouscred]: https://github.com/Azure/azure-sdk-for-js/tree/master/sdk/storage/storage-file-share/samples/typescript/src/anonymousCred.ts +[iterators-handles]: https://github.com/Azure/azure-sdk-for-js/tree/master/sdk/storage/storage-file-share/samples/typescript/src/iterators-handles.ts +[custompipeline]: https://github.com/Azure/azure-sdk-for-js/tree/master/sdk/storage/storage-file-share/samples/typescript/src/customPipeline.ts +[advanced]: https://github.com/Azure/azure-sdk-for-js/tree/master/sdk/storage/storage-file-share/samples/typescript/src/advanced.ts +[iterators-shares]: https://github.com/Azure/azure-sdk-for-js/tree/master/sdk/storage/storage-file-share/samples/typescript/src/iterators-shares.ts [apiref]: https://docs.microsoft.com/javascript/api/@azure/storage-file-share [azstorage]: https://docs.microsoft.com/azure/storage/common/storage-account-overview [freesub]: https://azure.microsoft.com/free/ diff --git a/sdk/storage/storage-file-share/samples/typescript/package.json b/sdk/storage/storage-file-share/samples/typescript/package.json index 295096d98ba0..19e69bd3b291 100644 --- a/sdk/storage/storage-file-share/samples/typescript/package.json +++ b/sdk/storage/storage-file-share/samples/typescript/package.json @@ -1,5 +1,5 @@ { - "name": "azure-file-share-samples-ts", + "name": "azure-storage-file-share-samples-ts", "private": true, "version": "0.1.0", "description": "Azure Storage File Share client library samples for TypeScript", @@ -29,12 +29,15 @@ "homepage": "https://github.com/Azure/azure-sdk-for-js#readme", "sideEffects": false, "dependencies": { - "@azure/abort-controller": "^1.0.0", - "@azure/storage-file-share": "latest" + "@azure/abort-controller": "latest", + "@azure/storage-file-share": "latest", + "dotenv": "^8.2.0" }, "devDependencies": { "@types/node": "^8.0.0", + "cross-env": "^6.0.3", "rimraf": "^3.0.0", + "ts-node": "^8.3.0", "typescript": "~3.6.4" } } diff --git a/sdk/storage/storage-file-share/samples/typescript/sample.env b/sdk/storage/storage-file-share/samples/typescript/sample.env new file mode 100644 index 000000000000..020e02500273 --- /dev/null +++ b/sdk/storage/storage-file-share/samples/typescript/sample.env @@ -0,0 +1,16 @@ +# Used in most samples. Retrieve these values from a storage account in the Azure Portal. +ACCOUNT_NAME= +ACCOUNT_KEY= + +# Used for withConnString +STORAGE_CONNECTION_STRING= + +# Used for the advanced and anonymousCred tests. Create a SAS token for a storage account in the Azure Portal. +ACCOUNT_SAS= + +# Used for iterators-handles, provide an existing share and directory name. +SHARE_NAME= +DIR_NAME= + +# To run the proxyAuth sample, set up an HTTP proxy and enter your information: +# HTTP_PROXY=http://localhost:3128 diff --git a/sdk/storage/storage-file-share/samples/typescript/advanced.ts b/sdk/storage/storage-file-share/samples/typescript/src/advanced.ts similarity index 91% rename from sdk/storage/storage-file-share/samples/typescript/advanced.ts rename to sdk/storage/storage-file-share/samples/typescript/src/advanced.ts index b430f6713667..e6bd3bfcf77f 100644 --- a/sdk/storage/storage-file-share/samples/typescript/advanced.ts +++ b/sdk/storage/storage-file-share/samples/typescript/src/advanced.ts @@ -1,16 +1,19 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + /* Setup: Enter your storage account name, SAS and a path pointing to local file in main() */ -import fs from "fs"; +import * as fs from "fs"; import { AbortController } from "@azure/abort-controller"; import { AnonymousCredential, ShareServiceClient, newPipeline } from "@azure/storage-file-share"; -async function main() { +export async function main() { // Fill in following settings before running this sample const account = process.env.ACCOUNT_NAME || ""; const accountSas = process.env.ACCOUNT_SAS || ""; - const localFilePath = "../README.md"; + const localFilePath = "README.md"; const pipeline = newPipeline(new AnonymousCredential(), { // httpClient: MyHTTPClient, // A customized HTTP client implementing IHttpClient interface @@ -88,11 +91,6 @@ async function main() { console.log("deleted share"); } -// An async method returns a Promise object, which is compatible with then().catch() coding style. -main() - .then(() => { - console.log("Successfully executed sample."); - }) - .catch((err) => { - console.log(err.message); - }); +main().catch((err) => { + console.error("Error running sample:", err.message); +}); diff --git a/sdk/storage/storage-file-share/samples/typescript/anonymousCred.ts b/sdk/storage/storage-file-share/samples/typescript/src/anonymousCred.ts similarity index 81% rename from sdk/storage/storage-file-share/samples/typescript/anonymousCred.ts rename to sdk/storage/storage-file-share/samples/typescript/src/anonymousCred.ts index 8ae5342a6e60..182001a40db7 100644 --- a/sdk/storage/storage-file-share/samples/typescript/anonymousCred.ts +++ b/sdk/storage/storage-file-share/samples/typescript/src/anonymousCred.ts @@ -1,10 +1,13 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + /* Setup: Enter your storage account name and SAS in main() */ import { ShareServiceClient, AnonymousCredential } from "@azure/storage-file-share"; -async function main() { +export async function main() { // Enter your storage account name and SAS const account = process.env.ACCOUNT_NAME || ""; const accountSas = process.env.ACCOUNT_SAS || ""; @@ -36,11 +39,6 @@ async function main() { console.log(`deleted share ${shareName}`); } -// An async method returns a Promise object, which is compatible with then().catch() coding style. -main() - .then(() => { - console.log("Successfully executed sample."); - }) - .catch((err) => { - console.log(err.message); - }); +main().catch((err) => { + console.error("Error running sample:", err.message); +}); diff --git a/sdk/storage/storage-file-share/samples/typescript/basic.ts b/sdk/storage/storage-file-share/samples/typescript/src/basic.ts similarity index 92% rename from sdk/storage/storage-file-share/samples/typescript/basic.ts rename to sdk/storage/storage-file-share/samples/typescript/src/basic.ts index 0206878e81e6..a5efc001b618 100644 --- a/sdk/storage/storage-file-share/samples/typescript/basic.ts +++ b/sdk/storage/storage-file-share/samples/typescript/src/basic.ts @@ -1,10 +1,13 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + /* Setup: Enter your storage account name and shared key in main() */ import { ShareServiceClient, StorageSharedKeyCredential } from "@azure/storage-file-share"; -async function main() { +export async function main() { // Enter your storage account name and shared key const account = process.env.ACCOUNT_NAME || ""; const accountKey = process.env.ACCOUNT_KEY || ""; @@ -90,11 +93,6 @@ async function streamToString(readableStream: NodeJS.ReadableStream) { }); } -// An async method returns a Promise object, which is compatible with then().catch() coding style. -main() - .then(() => { - console.log("Successfully executed sample."); - }) - .catch((err) => { - console.log(err.message); - }); +main().catch((err) => { + console.error("Error running sample:", err.message); +}); diff --git a/sdk/storage/storage-file-share/samples/typescript/customPipeline.ts b/sdk/storage/storage-file-share/samples/typescript/src/customPipeline.ts similarity index 85% rename from sdk/storage/storage-file-share/samples/typescript/customPipeline.ts rename to sdk/storage/storage-file-share/samples/typescript/src/customPipeline.ts index ee8bf0b0d880..192505a67334 100644 --- a/sdk/storage/storage-file-share/samples/typescript/customPipeline.ts +++ b/sdk/storage/storage-file-share/samples/typescript/src/customPipeline.ts @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + /* Setup: Enter your storage account name and shared key in main() */ @@ -8,7 +11,7 @@ import { StorageSharedKeyCredential } from "@azure/storage-file-share"; -async function main() { +export async function main() { // Enter your storage account name and shared key const account = process.env.ACCOUNT_NAME || ""; const accountKey = process.env.ACCOUNT_KEY || ""; @@ -47,11 +50,6 @@ async function main() { console.log(`deleted share ${shareName}`); } -// An async method returns a Promise object, which is compatible with then().catch() coding style. -main() - .then(() => { - console.log("Successfully executed sample."); - }) - .catch((err) => { - console.log(err.message); - }); +main().catch((err) => { + console.error("Error running sample:", err.message); +}); diff --git a/sdk/storage/storage-file-share/samples/typescript/iterators-files-and-directories.ts b/sdk/storage/storage-file-share/samples/typescript/src/iterators-files-and-directories.ts similarity index 95% rename from sdk/storage/storage-file-share/samples/typescript/iterators-files-and-directories.ts rename to sdk/storage/storage-file-share/samples/typescript/src/iterators-files-and-directories.ts index 10741181a4b7..87b42dbd471a 100644 --- a/sdk/storage/storage-file-share/samples/typescript/iterators-files-and-directories.ts +++ b/sdk/storage/storage-file-share/samples/typescript/src/iterators-files-and-directories.ts @@ -1,10 +1,13 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + /* Setup: Enter your storage account name and shared key in main() */ import { ShareServiceClient, StorageSharedKeyCredential } from "@azure/storage-file-share"; -async function main() { +export async function main() { // Enter your storage account name and shared key const account = process.env.ACCOUNT_NAME || ""; const accountKey = process.env.ACCOUNT_KEY || ""; @@ -157,11 +160,6 @@ async function main() { console.log(`deleted share ${shareName}`); } -// An async method returns a Promise object, which is compatible with then().catch() coding style. -main() - .then(() => { - console.log("Successfully executed sample."); - }) - .catch((err) => { - console.log(err.message); - }); +main().catch((err) => { + console.error("Error running sample:", err.message); +}); diff --git a/sdk/storage/storage-file-share/samples/typescript/iterators-handles.ts b/sdk/storage/storage-file-share/samples/typescript/src/iterators-handles.ts similarity index 91% rename from sdk/storage/storage-file-share/samples/typescript/iterators-handles.ts rename to sdk/storage/storage-file-share/samples/typescript/src/iterators-handles.ts index 9671d418b4a6..ba20b26d1bff 100644 --- a/sdk/storage/storage-file-share/samples/typescript/iterators-handles.ts +++ b/sdk/storage/storage-file-share/samples/typescript/src/iterators-handles.ts @@ -1,10 +1,13 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + /* Setup: Enter your storage account name and shared key in main() */ import { ShareServiceClient, StorageSharedKeyCredential } from "@azure/storage-file-share"; -async function main() { +export async function main() { // Enter your storage account name, shared key, share name, and directory name. // Please ensure your directory is mounted // https://docs.microsoft.com/en-us/azure/storage/files/storage-how-to-use-files-windows @@ -12,8 +15,15 @@ async function main() { // https://docs.microsoft.com/en-us/azure/storage/files/storage-how-to-use-files-mac const account = process.env.ACCOUNT_NAME || ""; const accountKey = process.env.ACCOUNT_KEY || ""; - const shareName = ""; - const dirName = ""; + const shareName = process.env.SHARE_NAME || ""; + const dirName = process.env.DIR_NAME || ""; + + if (shareName === "" || dirName === "") { + console.warn( + "Share/directory information not provided, but it is required to run this sample. Exiting." + ); + return; + } // Use StorageSharedKeyCredential with storage account and account key // StorageSharedKeyCredential is only avaiable in Node.js runtime, not in browsers @@ -150,11 +160,6 @@ async function main() { } } -// An async method returns a Promise object, which is compatible with then().catch() coding style. -main() - .then(() => { - console.log("Successfully executed sample."); - }) - .catch((err) => { - console.log(err.message); - }); +main().catch((err) => { + console.error("Error running sample:", err.message); +}); diff --git a/sdk/storage/storage-file-share/samples/typescript/iterators-shares.ts b/sdk/storage/storage-file-share/samples/typescript/src/iterators-shares.ts similarity index 92% rename from sdk/storage/storage-file-share/samples/typescript/iterators-shares.ts rename to sdk/storage/storage-file-share/samples/typescript/src/iterators-shares.ts index 7bd7f80908df..55af7a37c8c6 100644 --- a/sdk/storage/storage-file-share/samples/typescript/iterators-shares.ts +++ b/sdk/storage/storage-file-share/samples/typescript/src/iterators-shares.ts @@ -1,10 +1,13 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + /* Setup: Enter your storage account name and shared key in main() */ import { ShareServiceClient, StorageSharedKeyCredential } from "@azure/storage-file-share"; -async function main() { +export async function main() { // Enter your storage account name and shared key const account = process.env.ACCOUNT_NAME || ""; const accountKey = process.env.ACCOUNT_KEY || ""; @@ -102,11 +105,6 @@ async function main() { } } -// An async method returns a Promise object, which is compatible with then().catch() coding style. -main() - .then(() => { - console.log("Successfully executed sample."); - }) - .catch((err) => { - console.log(err.message); - }); +main().catch((err) => { + console.error("Error running sample:", err.message); +}); diff --git a/sdk/storage/storage-file-share/samples/typescript/proxyAuth.ts b/sdk/storage/storage-file-share/samples/typescript/src/proxyAuth.ts similarity index 56% rename from sdk/storage/storage-file-share/samples/typescript/proxyAuth.ts rename to sdk/storage/storage-file-share/samples/typescript/src/proxyAuth.ts index ee67036c2793..d48e31440900 100644 --- a/sdk/storage/storage-file-share/samples/typescript/proxyAuth.ts +++ b/sdk/storage/storage-file-share/samples/typescript/src/proxyAuth.ts @@ -1,10 +1,13 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + /* Setup: Enter your storage account name and shared key in main() */ import { StorageSharedKeyCredential, ShareServiceClient } from "@azure/storage-file-share"; -async function main() { +export async function main() { // Enter your storage account name and shared key const account = process.env.ACCOUNT_NAME || ""; const accountKey = process.env.ACCOUNT_KEY || ""; @@ -13,20 +16,27 @@ async function main() { // StorageSharedKeyCredential is only avaiable in Node.js runtime, not in browsers const sharedKeyCredential = new StorageSharedKeyCredential(account, accountKey); + // To use the manual proxyOptions below, remove this block + if (!process.env.HTTP_PROXY || !process.env.HTTPS_PROXY) { + console.warn("Proxy information not provided, but it is required to run this sample. Exiting."); + return; + } + const serviceClient = new ShareServiceClient( `https://${account}.file.core.windows.net`, sharedKeyCredential, + // The library tries to load the proxy settings from the environment variables like HTTP_PROXY + // Alternatively, the service client accepts the following `proxyOptions` as part of its options: { - // proxy can either be a URL like "http://localhost:3128" - // or - // an option bag consisting {host, port, username, password } - proxyOptions: { + /* + proxyOptions : { + // To use these options, remove the section above that checks for HTTP_PROXY or HTTPS_PROXY host: "http://localhost", port: 3128, - username: "username", - password: "password" + username: "", + password: "" } - // if proxy is undefined, the library tries to load the proxy settings from the environment variables like HTTP_PROXY + */ } ); @@ -41,11 +51,6 @@ async function main() { console.log(`deleted share ${shareName}`); } -// An async method returns a Promise object, which is compatible with then().catch() coding style. -main() - .then(() => { - console.log("Successfully executed the sample."); - }) - .catch((err) => { - console.log(err.message); - }); +main().catch((err) => { + console.error("Error running sample:", err.message); +}); diff --git a/sdk/storage/storage-file-share/samples/typescript/sharedKeyCred.ts b/sdk/storage/storage-file-share/samples/typescript/src/sharedKeyCred.ts similarity index 82% rename from sdk/storage/storage-file-share/samples/typescript/sharedKeyCred.ts rename to sdk/storage/storage-file-share/samples/typescript/src/sharedKeyCred.ts index 09e478a223e3..e92bbf370864 100644 --- a/sdk/storage/storage-file-share/samples/typescript/sharedKeyCred.ts +++ b/sdk/storage/storage-file-share/samples/typescript/src/sharedKeyCred.ts @@ -1,10 +1,13 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + /* Setup: Enter your storage account name and shared key in main() */ import { ShareServiceClient, StorageSharedKeyCredential } from "@azure/storage-file-share"; -async function main() { +export async function main() { // Enter your storage account name and shared key const account = process.env.ACCOUNT_NAME || ""; const accountKey = process.env.ACCOUNT_KEY || ""; @@ -36,11 +39,6 @@ async function main() { console.log(`deleted share ${shareName}`); } -// An async method returns a Promise object, which is compatible with then().catch() coding style. -main() - .then(() => { - console.log("Successfully executed sample."); - }) - .catch((err) => { - console.log(err.message); - }); +main().catch((err) => { + console.error("Error running sample:", err.message); +}); diff --git a/sdk/storage/storage-file-share/samples/typescript/withConnString.ts b/sdk/storage/storage-file-share/samples/typescript/src/withConnString.ts similarity index 84% rename from sdk/storage/storage-file-share/samples/typescript/withConnString.ts rename to sdk/storage/storage-file-share/samples/typescript/src/withConnString.ts index 006f6fc1996e..9c05d32e9ef8 100644 --- a/sdk/storage/storage-file-share/samples/typescript/withConnString.ts +++ b/sdk/storage/storage-file-share/samples/typescript/src/withConnString.ts @@ -1,10 +1,13 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + /* Setup: Enter your storage account name and shared key in main() */ import { ShareServiceClient } from "@azure/storage-file-share"; -async function main() { +export async function main() { // Create File Service Client from Account connection string or SAS connection string // Account connection string example - `DefaultEndpointsProtocol=https;AccountName=myaccount;AccountKey=accountKey;EndpointSuffix=core.windows.net` // SAS connection string example - `BlobEndpoint=https://myaccount.blob.core.windows.net/;QueueEndpoint=https://myaccount.queue.core.windows.net/;FileEndpoint=https://myaccount.file.core.windows.net/;TableEndpoint=https://myaccount.table.core.windows.net/;SharedAccessSignature=sasString` @@ -29,11 +32,6 @@ async function main() { console.log(`deleted share ${shareName}`); } -// An async method returns a Promise object, which is compatible with then().catch() coding style. -main() - .then(() => { - console.log("Successfully executed sample."); - }) - .catch((err) => { - console.log(err.message); - }); +main().catch((err) => { + console.error("Error running sample:", err.message); +}); diff --git a/sdk/storage/storage-file-share/samples/typescript/tsconfig.json b/sdk/storage/storage-file-share/samples/typescript/tsconfig.json index 639c5d296a23..4332663bf7b7 100644 --- a/sdk/storage/storage-file-share/samples/typescript/tsconfig.json +++ b/sdk/storage/storage-file-share/samples/typescript/tsconfig.json @@ -7,6 +7,9 @@ "allowSyntheticDefaultImports": true, - "outDir": "dist" - } + "outDir": "dist", + "rootDir": "src" + }, + "include": ["src/**.ts"], + "exclude": ["node_modules"] } diff --git a/sdk/storage/storage-queue/execute-samples.js b/sdk/storage/storage-queue/execute-samples.js deleted file mode 100644 index aa77c71f12be..000000000000 --- a/sdk/storage/storage-queue/execute-samples.js +++ /dev/null @@ -1,80 +0,0 @@ -const execa = require("execa"); -const fs = require("fs"); -require("dotenv").config({ path: "../.env" }); - -// Samples can be skipped by mentioning them in the skipSamples Array. -// Suppose skipSamples = ["some-entry", "sample-2"], -// some-entry.ts, sample-2.ts, some-entry.js and sample-2.js will be skipped. -const skipSamples = ["proxyAuth"]; - -const bDel = `!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!`; -const del = `${bDel}------------------------------${bDel}`; - -// Colours - green, yellow, red and blue - for console logs. -const { g, y, r, b } = [["r", 1], ["g", 2], ["b", 4], ["y", 3]].reduce( - (cols, col) => ({ - ...cols, - [col[0]]: (f) => `\x1b[3${col[1]}m${f}\x1b[0m` - }), - {} -); - -// Executes `cmd` in `cwd`(directory). -async function exec(cmd, cwd) { - let command = execa(cmd, { - cwd, - shell: true - }); - command.stderr.pipe(process.stderr); - command.stdout.pipe(process.stdout); - return command; -} - -async function runSamples(language) { - let cmd; - // Tries to execute all the samples in the `directory`. - const directory = `./samples/${language}`; - - if (language === "typescript") { - cmd = "ts-node"; - } else { - cmd = "node"; - await exec(`npm run build:js-samples`, directory); - } - - console.log(`Running ${language} samples...`); - - const files = fs.readdirSync(directory); - - for (var i = 0; i < files.length; i++) { - if (!skipSamples.includes(files[i].split(".")[0])) { - try { - console.log(`\n\n${b(del)}\n${del}`); - console.log(`${bDel}\t${files[i]} \t `); - console.log(`${del}\n${b(del)} \n`); - - console.log(`${g("Running")} ${y(files[i])} ${g("...")}`); - // Executing a sample - Example: (`ts-node samplefilename.ts`, `./samples/typescript`). - await exec(`${cmd} ${files[i]}`, directory); - console.log(`${g(files[i] + " is done..!")}`); - } catch (error) { - console.log(error.message); - console.log(`${r(del)}\n${del}`); - console.log(`${bDel}\t${files[i]} Sample - FAILED\t `); - console.log(`${del}\n${r(del)}`); - } - } - } -} - -(async () => { - try { - await runSamples("typescript"); - await runSamples("javascript"); - process.exit(0); - } catch (error) { - console.log("Samples failed!"); - console.log(error); - process.exit(1); - } -})(); diff --git a/sdk/storage/storage-queue/package.json b/sdk/storage/storage-queue/package.json index 9eb0cd963227..7653e6ea7006 100644 --- a/sdk/storage/storage-queue/package.json +++ b/sdk/storage/storage-queue/package.json @@ -21,14 +21,17 @@ "build:autorest": "autorest ./swagger/README.md --typescript --package-version=12.0.1 --use=@microsoft.azure/autorest.typescript@5.0.1", "build:es6": "tsc -p tsconfig.json", "build:nodebrowser": "rollup -c 2>&1", - "build:js-samples": "npm run clean && npm run build:es6 && cross-env ONLY_NODE=true rollup -c 2>&1", - "build:ts-samples": "npm run clean && cd samples && tsc -p . ", + "build:samples": "npm run clean && npm run build:es6 && cross-env ONLY_NODE=true rollup -c 2>&1 && npm run build:prep-samples", + "build:prep-samples": "node ../../../common/scripts/prep-samples.js && cd samples && tsc", "build:test": "npm run build:es6 && rollup -c rollup.test.config.js 2>&1", "build": "npm run build:es6 && npm run build:nodebrowser && api-extractor run --local", "check-format": "prettier --list-different --config ../../.prettierrc.json \"src/**/*.ts\" \"test/**/*.ts\" \"*.{js,json}\"", "clean": "rimraf dist dist-esm dist-test typings temp browser/*.js* browser/*.zip statistics.html coverage coverage-browser .nyc_output *.tgz *.log test*.xml TEST*.xml", + "clean:samples": "rimraf samples/javascript/node_modules samples/typescript/node_modules samples/typescript/dist samples/typescript/package-lock.json samples/javascript/package-lock.json", "extract-api": "tsc -p . && api-extractor run --local", - "execute:samples": "node execute-samples.js", + "execute:js-samples": "node ../../../common/scripts/run-samples.js samples/javascript/", + "execute:ts-samples": "node ../../../common/scripts/run-samples.js samples/typescript/dist/samples/typescript/src/", + "execute:samples": "npm run build:samples && npm run execute:js-samples && npm run execute:ts-samples", "format": "prettier --write --config ../../.prettierrc.json \"src/**/*.ts\" \"test/**/*.ts\" \"*.{js,json}\"", "integration-test:browser": "karma start --single-run", "integration-test:node": "nyc mocha --require source-map-support/register --reporter mocha-multi --reporter-options spec=-,mocha-junit-reporter=- --full-trace -t 120000 --retries 2 dist-test/index.node.js", diff --git a/sdk/storage/storage-queue/samples/javascript/README.md b/sdk/storage/storage-queue/samples/javascript/README.md new file mode 100644 index 000000000000..57046bc373b8 --- /dev/null +++ b/sdk/storage/storage-queue/samples/javascript/README.md @@ -0,0 +1,73 @@ +--- +page_type: sample +languages: + - javascript +products: + - azure + - azure-storage +urlFragment: storage-queue-javascript +--- + +# Azure Storage Queue client library samples for JavaScript + +These sample programs show how to use the JavaScript client libraries for Azure Storage Queues in some common scenarios. + +| **File Name** | **Description** | +| ----------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| [basic.js][basic] | authenticate with the service using an account name & key (or anonymously with a SAS URL); send, peek, and dequeue messages | +| [withConnString.js][withconnstring] | connect to and authenticate with the service using a connection string | +| [sharedKeyCred.js][sharedkeycred] | authenticate with the service using an account name and a shared key | +| [anonymousCred.js][anonymouscred] | authenticate with the service anonymously using a SAS URL | +| [azureAdAuth.js][azureadauth] | authenticate with the service using Azure Active Directory | +| [proxyAuth.js][proxyauth] | connect to the service using a proxy and authenticate with an account name & key | +| [iterators.js][iterators] | different options for iterating over messages, showing options for paging, resuming paging etc. (requires several queues to already exist in order to see output) | +| [customPipeline.js][custompipeline] | use custom HTTP pipeline options when connecting to the service | + +## Prerequisites + +The sample are compatible with Node.js >= 8.0.0, except for the samples that use the async `for await` syntax, which require Node.js >= 10.0.0. + +You need [an Azure subscription][freesub] and [an Azure Storage account][azstorage] to run these sample programs. Samples retrieve credentials to access the storage account from environment variables. Alternatively, edit the source code to include the appropriate credentials. See each individual sample for details on which environment variables/credentials it requires to function. + +Adapting the samples to run in the browser requires some additional consideration. For details, please see the [package README][package]. + +## Setup + +To run the samples using the published version of the package: + +1. Install the dependencies using `npm`: + +```bash +npm install +``` + +2. Edit the file `sample.env`, adding the correct credentials to access the Azure service and run the samples. Then rename the file from `sample.env` to just `.env`. The sample programs will read this file automatically. + +3. Run whichever samples you like (note that some samples may require additional setup, see the table above): + +```bash +node basic.js +``` + +Alternatively, run a single sample with the correct environment variables set (step 3 is not required if you do this), for example (cross-platform): + +```bash +npx cross-env ACCOUNT_NAME="" ACCOUNT_KEY="" node basic.js +``` + +## Next Steps + +Take a look at our [API Documentation][apiref] for more information about the APIs that are available in the clients. + +[anonymouscred]: https://github.com/Azure/azure-sdk-for-js/tree/master/sdk/storage/storage-queue/samples/javascript/anonymousCred.js +[azureadauth]: https://github.com/Azure/azure-sdk-for-js/tree/master/sdk/storage/storage-queue/samples/javascript/azureAdAuth.js +[basic]: https://github.com/Azure/azure-sdk-for-js/tree/master/sdk/storage/storage-queue/samples/javascript/basic.js +[custompipeline]: https://github.com/Azure/azure-sdk-for-js/tree/master/sdk/storage/storage-queue/samples/javascript/customPipeline.js +[iterators]: https://github.com/Azure/azure-sdk-for-js/tree/master/sdk/storage/storage-queue/samples/javascript/iterators.js +[proxyauth]: https://github.com/Azure/azure-sdk-for-js/tree/master/sdk/storage/storage-queue/samples/javascript/proxyAuth.js +[sharedkeycred]: https://github.com/Azure/azure-sdk-for-js/tree/master/sdk/storage/storage-queue/samples/javascript/sharedKeyCred.js +[withconnstring]: https://github.com/Azure/azure-sdk-for-js/tree/master/sdk/storage/storage-queue/samples/javascript/withConnString.js +[apiref]: https://docs.microsoft.com/javascript/api/@azure/storage-queue +[azstorage]: https://docs.microsoft.com/azure/storage/common/storage-account-overview +[freesub]: https://azure.microsoft.com/free/ +[package]: https://github.com/Azure/azure-sdk-for-js/tree/master/sdk/storage/storage-queue/README.md diff --git a/sdk/storage/storage-queue/samples/javascript/anonymousCred.js b/sdk/storage/storage-queue/samples/javascript/anonymousCred.js index f6e17a48c6bf..5b803b60a265 100644 --- a/sdk/storage/storage-queue/samples/javascript/anonymousCred.js +++ b/sdk/storage/storage-queue/samples/javascript/anonymousCred.js @@ -1,8 +1,11 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + /* Setup: Enter your storage account name and SAS in main() */ -const { QueueServiceClient, AnonymousCredential } = require("../.."); // Change to "@azure/storage-queue" in your package +const { QueueServiceClient, AnonymousCredential } = require("@azure/storage-queue"); async function main() { // Enter your storage account name and SAS @@ -33,11 +36,8 @@ async function main() { ); } -// An async method returns a Promise object, which is compatible with then().catch() coding style. -main() - .then(() => { - console.log("Successfully executed sample."); - }) - .catch((err) => { - console.log(err.message); - }); +module.exports = { main }; + +main().catch((err) => { + console.error("Error running sample:", err.message); +}); diff --git a/sdk/storage/storage-queue/samples/javascript/azureAdAuth.js b/sdk/storage/storage-queue/samples/javascript/azureAdAuth.js index 05979df93de3..3e4eef84b735 100644 --- a/sdk/storage/storage-queue/samples/javascript/azureAdAuth.js +++ b/sdk/storage/storage-queue/samples/javascript/azureAdAuth.js @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + /* ONLY AVAILABLE IN NODE.JS RUNTIME @@ -18,7 +21,7 @@ - Make sure you have AZURE_TENANT_ID, AZURE_CLIENT_ID, AZURE_CLIENT_SECRET as environment variables to successfully execute the sample(Can leverage process.env). */ -const { QueueServiceClient } = require("../.."); // Change to "@azure/storage-queue" in your package +const { QueueServiceClient } = require("@azure/storage-queue"); const { DefaultAzureCredential } = require("@azure/identity"); @@ -26,6 +29,18 @@ async function main() { // Enter your storage account name and shared key const account = process.env.ACCOUNT_NAME || ""; + // Azure AD Credential information is required to run this sample: + if ( + !process.env.AZURE_TENANT_ID || + !process.env.AZURE_CLIENT_ID || + !process.env.AZURE_CLIENT_SECRET + ) { + console.warn( + "Azure AD authentication information not provided, but it is required to run this sample. Exiting." + ); + return; + } + // ONLY AVAILABLE IN NODE.JS RUNTIME // DefaultAzureCredential will first look for Azure Active Directory (AAD) // client secret credentials in the following environment variables: @@ -51,11 +66,8 @@ async function main() { } } -// An async method returns a Promise object, which is compatible with then().catch() coding style. -main() - .then(() => { - console.log("Successfully executed sample."); - }) - .catch((err) => { - console.log(err.message); - }); +module.exports = { main }; + +main().catch((err) => { + console.error("Error running sample:", err.message); +}); diff --git a/sdk/storage/storage-queue/samples/javascript/basic.js b/sdk/storage/storage-queue/samples/javascript/basic.js index b1ec573a5677..f8649d6ba214 100644 --- a/sdk/storage/storage-queue/samples/javascript/basic.js +++ b/sdk/storage/storage-queue/samples/javascript/basic.js @@ -1,8 +1,11 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + /* Setup: Enter your storage account name and shared key in main() */ -const { QueueServiceClient, StorageSharedKeyCredential } = require("../.."); // Change to "@azure/storage-queue" in your package +const { QueueServiceClient, StorageSharedKeyCredential } = require("@azure/storage-queue"); async function main() { // Enter your storage account name and shared key @@ -87,11 +90,8 @@ async function main() { ); } -// An async method returns a Promise object, which is compatible with then().catch() coding style. -main() - .then(() => { - console.log("Successfully executed sample."); - }) - .catch((err) => { - console.log(err.message); - }); +module.exports = { main }; + +main().catch((err) => { + console.error("Error running sample:", err.message); +}); diff --git a/sdk/storage/storage-queue/samples/javascript/customPipeline.js b/sdk/storage/storage-queue/samples/javascript/customPipeline.js index 04a6cbd3af05..f8941f941433 100644 --- a/sdk/storage/storage-queue/samples/javascript/customPipeline.js +++ b/sdk/storage/storage-queue/samples/javascript/customPipeline.js @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + /* Setup: Enter your storage account name and shared key in main() */ @@ -6,7 +9,7 @@ const { QueueServiceClient, newPipeline, StorageSharedKeyCredential -} = require("../.."); // Change to "@azure/storage-queue" in your package +} = require("@azure/storage-queue"); async function main() { // Enter your storage account name and shared key @@ -53,11 +56,8 @@ async function main() { ); } -// An async method returns a Promise object, which is compatible with then().catch() coding style. -main() - .then(() => { - console.log("Successfully executed sample."); - }) - .catch((err) => { - console.log(err.message); - }); +module.exports = { main }; + +main().catch((err) => { + console.error("Error running sample:", err.message); +}); diff --git a/sdk/storage/storage-queue/samples/javascript/iterators.js b/sdk/storage/storage-queue/samples/javascript/iterators.js index 3a7847c9b471..c05f0182a1e5 100644 --- a/sdk/storage/storage-queue/samples/javascript/iterators.js +++ b/sdk/storage/storage-queue/samples/javascript/iterators.js @@ -1,8 +1,11 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + /* Setup: Enter your storage account name and shared key in main() */ -const { QueueServiceClient, StorageSharedKeyCredential } = require("../.."); // Change to "@azure/storage-queue" in your package +const { QueueServiceClient, StorageSharedKeyCredential } = require("@azure/storage-queue"); async function main() { // Enter your storage account name and shared key @@ -91,22 +94,23 @@ async function main() { } // Gets next marker let marker = response.value.continuationToken; - // Passing next marker as continuationToken - iterator = queueServiceClient.listQueues().byPage({ continuationToken: marker, maxPageSize: 10 }); - response = await iterator.next(); - // Prints 10 queue names - if (response.value.queueItems) { - for (const queueItem of response.value.queueItems) { - console.log(`Queue ${i++}: ${queueItem.name}`); + if (marker) { + // Passing next marker as continuationToken + iterator = queueServiceClient + .listQueues() + .byPage({ continuationToken: marker, maxPageSize: 10 }); + response = await iterator.next(); + // Prints 10 queue names + if (response.value.queueItems) { + for (const queueItem of response.value.queueItems) { + console.log(`Queue ${i++}: ${queueItem.name}`); + } } } } -// An async method returns a Promise object, which is compatible with then().catch() coding style. -main() - .then(() => { - console.log("Successfully executed sample."); - }) - .catch((err) => { - console.log(err.message); - }); +module.exports = { main }; + +main().catch((err) => { + console.error("Error running sample:", err.message); +}); diff --git a/sdk/storage/storage-queue/samples/javascript/package.json b/sdk/storage/storage-queue/samples/javascript/package.json new file mode 100644 index 000000000000..808753da1928 --- /dev/null +++ b/sdk/storage/storage-queue/samples/javascript/package.json @@ -0,0 +1,36 @@ +{ + "name": "azure-storage-queue-samples-js", + "private": true, + "version": "0.1.0", + "description": "Azure Storage Queue client library samples for TypeScript", + "engine": { + "node": ">=8.0.0" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/Azure/azure-sdk-for-js.git" + }, + "keywords": [ + "Azure", + "Storage", + "Queue", + "Node.js", + "JavaScript" + ], + "author": "Microsoft Corporation", + "license": "MIT", + "bugs": { + "url": "https://github.com/Azure/azure-sdk-for-js/issues" + }, + "homepage": "https://github.com/Azure/azure-sdk-for-js#readme", + "sideEffects": false, + "dependencies": { + "@azure/identity": "latest", + "@azure/storage-queue": "latest", + "dotenv": "^8.2.0" + }, + "devDependencies": { + "cross-env": "^6.0.3", + "rimraf": "^3.0.0" + } +} diff --git a/sdk/storage/storage-queue/samples/javascript/proxyAuth.js b/sdk/storage/storage-queue/samples/javascript/proxyAuth.js index c7b9a160bad4..e492602cae25 100644 --- a/sdk/storage/storage-queue/samples/javascript/proxyAuth.js +++ b/sdk/storage/storage-queue/samples/javascript/proxyAuth.js @@ -1,8 +1,11 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + /* Setup: Enter your storage account name and shared key in main() */ -const { QueueServiceClient, StorageSharedKeyCredential } = require("../.."); // Change to "@azure/storage-queue" in your package +const { QueueServiceClient, StorageSharedKeyCredential } = require("@azure/storage-queue"); async function main() { // Enter your storage account name and shared key @@ -13,20 +16,27 @@ async function main() { // StorageSharedKeyCredential is only avaiable in Node.js runtime, not in browsers const sharedKeyCredential = new StorageSharedKeyCredential(account, accountKey); + // To use the manual proxyOptions below, remove this block + if (!process.env.HTTP_PROXY || !process.env.HTTPS_PROXY) { + console.warn("Proxy information not provided, but it is required to run this sample. Exiting."); + return; + } + const queueServiceClient = new QueueServiceClient( `https://${account}.queue.core.windows.net`, sharedKeyCredential, + // The library tries to load the proxy settings from the environment variables like HTTP_PROXY + // Alternatively, the service client accepts the following `proxyOptions` as part of its options: { - // proxy can either be a URL like "http://localhost:3128" - // or - // an option bag consisting {host, port, username, password } - proxyOptions: { + /* + proxyOptions : { + // To use these options, remove the section above that checks for HTTP_PROXY or HTTPS_PROXY host: "http://localhost", port: 3128, - username: "username", - password: "password" + username: "", + password: "" } - // if proxy is undefined, the library tries to load the proxy settings from the environment variables like HTTP_PROXY + */ } ); @@ -45,11 +55,8 @@ async function main() { ); } -// An async method returns a Promise object, which is compatible with then().catch() coding style. -main() - .then(() => { - console.log("Successfully executed the sample."); - }) - .catch((err) => { - console.log(err.message); - }); +module.exports = { main }; + +main().catch((err) => { + console.error("Error running sample:", err.message); +}); diff --git a/sdk/storage/storage-queue/samples/javascript/sample.env b/sdk/storage/storage-queue/samples/javascript/sample.env new file mode 100644 index 000000000000..92a81cac6547 --- /dev/null +++ b/sdk/storage/storage-queue/samples/javascript/sample.env @@ -0,0 +1,20 @@ +# Used in most samples. Retrieve these values from a storage account in the Azure Portal. +ACCOUNT_NAME= +ACCOUNT_KEY= + +# Used for withConnString +STORAGE_CONNECTION_STRING= + +# Used for the advanced and anonymousCred tests. Create a SAS token for a storage account in the Azure Portal. +ACCOUNT_SAS= + +# Used to authenticate using Azure AD as a service principal for role-based authentication. +# +# See the documentation for `EnvironmentCredential` at the following link: +# https://docs.microsoft.com/javascript/api/@azure/identity/environmentcredential +AZURE_TENANT_ID= +AZURE_CLIENT_ID= +AZURE_CLIENT_SECRET= + +# To run the proxyAuth sample, set up an HTTP proxy and enter your information: +# HTTP_PROXY=http://localhost:3128 diff --git a/sdk/storage/storage-queue/samples/javascript/sharedKeyCred.js b/sdk/storage/storage-queue/samples/javascript/sharedKeyCred.js index 60a31c934449..60468c60c03b 100644 --- a/sdk/storage/storage-queue/samples/javascript/sharedKeyCred.js +++ b/sdk/storage/storage-queue/samples/javascript/sharedKeyCred.js @@ -1,8 +1,11 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + /* Setup: Enter your storage account name and shared key in main() */ -const { QueueServiceClient, StorageSharedKeyCredential } = require("../.."); // Change to "@azure/storage-queue" in your package +const { QueueServiceClient, StorageSharedKeyCredential } = require("@azure/storage-queue"); async function main() { // Enter your storage account name and shared key @@ -33,11 +36,8 @@ async function main() { ); } -// An async method returns a Promise object, which is compatible with then().catch() coding style. -main() - .then(() => { - console.log("Successfully executed sample."); - }) - .catch((err) => { - console.log(err.message); - }); +module.exports = { main }; + +main().catch((err) => { + console.error("Error running sample:", err.message); +}); diff --git a/sdk/storage/storage-queue/samples/javascript/withConnString.js b/sdk/storage/storage-queue/samples/javascript/withConnString.js index 55d138da18ab..9bb10bc6195d 100644 --- a/sdk/storage/storage-queue/samples/javascript/withConnString.js +++ b/sdk/storage/storage-queue/samples/javascript/withConnString.js @@ -1,8 +1,11 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + /* Setup: Enter your storage account name and shared key in main() */ -const { QueueServiceClient } = require("../.."); // Change to "@azure/storage-queue" in your package +const { QueueServiceClient } = require("@azure/storage-queue"); async function main() { // Create Queue Service Client from Account connection string or SAS connection string @@ -27,11 +30,8 @@ async function main() { ); } -// An async method returns a Promise object, which is compatible with then().catch() coding style. -main() - .then(() => { - console.log("Successfully executed sample."); - }) - .catch((err) => { - console.log(err.message); - }); +module.exports = { main }; + +main().catch((err) => { + console.error("Error running sample:", err.message); +}); diff --git a/sdk/storage/storage-queue/samples/tsconfig.json b/sdk/storage/storage-queue/samples/tsconfig.json index c01d1f002034..3a37abdb0902 100644 --- a/sdk/storage/storage-queue/samples/tsconfig.json +++ b/sdk/storage/storage-queue/samples/tsconfig.json @@ -1,13 +1,9 @@ { - "extends": "../tsconfig.json", - "compilerOptions": { - "module": "commonjs" - }, - "include": [ - "**/*.ts" - ], - "exclude": [ - "../node_modules", - "../typings/**", - ] -} \ No newline at end of file + "extends": "../tsconfig.json", + "compilerOptions": { + "module": "commonjs", + "outDir": "typescript/dist" + }, + "include": ["typescript/src/**.ts"], + "exclude": ["typescript/*.json", "**/node_modules/", "../node_modules", "../typings"] +} diff --git a/sdk/storage/storage-queue/samples/typescript/README.md b/sdk/storage/storage-queue/samples/typescript/README.md new file mode 100644 index 000000000000..9107a5c4b234 --- /dev/null +++ b/sdk/storage/storage-queue/samples/typescript/README.md @@ -0,0 +1,86 @@ +--- +page_type: sample +languages: + - typescript +products: + - azure + - azure-storage +urlFragment: storage-queue-typescript +--- + +# Azure Storage Queue client library samples for TypeScript + +These sample programs show how to use the TypeScript client libraries for Azure Storage Queues in some common scenarios. + +| **File Name** | **Description** | +| ----------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| [basic.ts][basic] | authenticate with the service using an account name & key (or anonymously with a SAS URL); send, peek, and dequeue messages | +| [withConnString.ts][withconnstring] | connect to and authenticate with the service using a connection string | +| [sharedKeyCred.ts][sharedkeycred] | authenticate with the service using an account name and a shared key | +| [anonymousCred.ts][anonymouscred] | authenticate with the service anonymously using a SAS URL | +| [azureAdAuth.ts][azureadauth] | authenticate with the service using Azure Active Directory | +| [proxyAuth.ts][proxyauth] | connect to the service using a proxy and authenticate with an account name & key | +| [iterators.ts][iterators] | different options for iterating over messages, showing options for paging, resuming paging etc. (requires several queues to already exist in order to see output) | +| [customPipeline.ts][custompipeline] | use custom HTTP pipeline options when connecting to the service | + +## Prerequisites + +The samples are compatible with Node.js >= 8.0.0, except for the samples that use the async `for await` syntax, which require a Node.js >= 10.0.0. + +Before running the samples in Node, they must be compiled to JavaScript using the TypeScript compiler. For more information on TypeScript, see the [TypeScript documentation][typescript]. Install the TypeScript compiler using + +```bash +npm install -g typescript +``` + +You need [an Azure subscription][freesub] and [an Azure Storage account][azstorage] to run these sample programs. Samples retrieve credentials to access the storage account from environment variables. Alternatively, edit the source code to include the appropriate credentials. See each individual sample for details on which environment variables/credentials it requires to function. + +Adapting the samples to run in the browser requires some additional consideration. For details, please see the [package README][package]. + +## Setup + +To run the samples using the published version of the package: + +1. Install the dependencies using `npm`: + +```bash +npm install +``` + +2. Compile the samples + +```bash +npm run build +``` + +3. Edit the file `sample.env`, adding the correct credentials to access the Azure service and run the samples. Then rename the file from `sample.env` to just `.env`. The sample programs will read this file automatically. + +4. Run whichever samples you like (note that some samples may require additional setup, see the table above): + +```bash +node dist/basic.js +``` + +Alternatively, run a single sample with the correct environment variables set (step 3 is not required if you do this), for example (cross-platform): + +```bash +npx cross-env ACCOUNT_NAME="" ACCOUNT_KEY="" node dist/basic.js +``` + +## Next Steps + +Take a look at our [API Documentation][apiref] for more information about the APIs that are available in the clients. + +[anonymouscred]: https://github.com/Azure/azure-sdk-for-js/tree/master/sdk/storage/storage-queue/samples/typescript/src/anonymousCred.ts +[azureadauth]: https://github.com/Azure/azure-sdk-for-js/tree/master/sdk/storage/storage-queue/samples/typescript/src/azureAdAuth.ts +[basic]: https://github.com/Azure/azure-sdk-for-js/tree/master/sdk/storage/storage-queue/samples/typescript/src/basic.ts +[custompipeline]: https://github.com/Azure/azure-sdk-for-js/tree/master/sdk/storage/storage-queue/samples/typescript/src/customPipeline.ts +[iterators]: https://github.com/Azure/azure-sdk-for-js/tree/master/sdk/storage/storage-queue/samples/typescript/src/iterators.ts +[proxyauth]: https://github.com/Azure/azure-sdk-for-js/tree/master/sdk/storage/storage-queue/samples/typescript/src/proxyAuth.ts +[sharedkeycred]: https://github.com/Azure/azure-sdk-for-js/tree/master/sdk/storage/storage-queue/samples/typescript/src/sharedKeyCred.ts +[withconnstring]: https://github.com/Azure/azure-sdk-for-js/tree/master/sdk/storage/storage-queue/samples/typescript/src/withConnString.ts +[apiref]: https://docs.microsoft.com/javascript/api/@azure/storage-queue +[azstorage]: https://docs.microsoft.com/azure/storage/common/storage-account-overview +[freesub]: https://azure.microsoft.com/free/ +[package]: https://github.com/Azure/azure-sdk-for-js/tree/master/sdk/storage/storage-queue/README.md +[typescript]: https://www.typescriptlang.org/docs/home.html diff --git a/sdk/storage/storage-queue/samples/typescript/package.json b/sdk/storage/storage-queue/samples/typescript/package.json new file mode 100644 index 000000000000..f3bc35e4e910 --- /dev/null +++ b/sdk/storage/storage-queue/samples/typescript/package.json @@ -0,0 +1,43 @@ +{ + "name": "azure-storage-queue-samples-ts", + "private": true, + "version": "0.1.0", + "description": "Azure Storage Queue client library samples for TypeScript", + "engine": { + "node": ">=8.0.0" + }, + "scripts": { + "build": "tsc", + "prebuild": "rimraf dist/" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/Azure/azure-sdk-for-js.git" + }, + "keywords": [ + "Azure", + "Storage", + "Queue", + "Node.js", + "TypeScript" + ], + "author": "Microsoft Corporation", + "license": "MIT", + "bugs": { + "url": "https://github.com/Azure/azure-sdk-for-js/issues" + }, + "homepage": "https://github.com/Azure/azure-sdk-for-js#readme", + "sideEffects": false, + "dependencies": { + "@azure/identity": "latest", + "@azure/storage-queue": "latest", + "dotenv": "^8.2.0" + }, + "devDependencies": { + "@types/node": "^8.0.0", + "cross-env": "^6.0.3", + "rimraf": "^3.0.0", + "ts-node": "^8.3.0", + "typescript": "~3.6.4" + } +} diff --git a/sdk/storage/storage-queue/samples/typescript/sample.env b/sdk/storage/storage-queue/samples/typescript/sample.env new file mode 100644 index 000000000000..92a81cac6547 --- /dev/null +++ b/sdk/storage/storage-queue/samples/typescript/sample.env @@ -0,0 +1,20 @@ +# Used in most samples. Retrieve these values from a storage account in the Azure Portal. +ACCOUNT_NAME= +ACCOUNT_KEY= + +# Used for withConnString +STORAGE_CONNECTION_STRING= + +# Used for the advanced and anonymousCred tests. Create a SAS token for a storage account in the Azure Portal. +ACCOUNT_SAS= + +# Used to authenticate using Azure AD as a service principal for role-based authentication. +# +# See the documentation for `EnvironmentCredential` at the following link: +# https://docs.microsoft.com/javascript/api/@azure/identity/environmentcredential +AZURE_TENANT_ID= +AZURE_CLIENT_ID= +AZURE_CLIENT_SECRET= + +# To run the proxyAuth sample, set up an HTTP proxy and enter your information: +# HTTP_PROXY=http://localhost:3128 diff --git a/sdk/storage/storage-queue/samples/typescript/anonymousCred.ts b/sdk/storage/storage-queue/samples/typescript/src/anonymousCred.ts similarity index 74% rename from sdk/storage/storage-queue/samples/typescript/anonymousCred.ts rename to sdk/storage/storage-queue/samples/typescript/src/anonymousCred.ts index b73850dfda6c..7b0dd1d52885 100644 --- a/sdk/storage/storage-queue/samples/typescript/anonymousCred.ts +++ b/sdk/storage/storage-queue/samples/typescript/src/anonymousCred.ts @@ -1,10 +1,13 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + /* Setup: Enter your storage account name and SAS in main() */ -import { QueueServiceClient, AnonymousCredential } from "../../src"; // Change to "@azure/storage-queue" in your package +import { QueueServiceClient, AnonymousCredential } from "@azure/storage-queue"; -async function main() { +export async function main() { // Enter your storage account name and SAS const account = process.env.ACCOUNT_NAME || ""; const accountSas = process.env.ACCOUNT_SAS || ""; @@ -33,11 +36,6 @@ async function main() { ); } -// An async method returns a Promise object, which is compatible with then().catch() coding style. -main() - .then(() => { - console.log("Successfully executed sample."); - }) - .catch((err) => { - console.log(err.message); - }); +main().catch((err) => { + console.error("Error running sample:", err.message); +}); diff --git a/sdk/storage/storage-queue/samples/typescript/azureAdAuth.ts b/sdk/storage/storage-queue/samples/typescript/src/azureAdAuth.ts similarity index 82% rename from sdk/storage/storage-queue/samples/typescript/azureAdAuth.ts rename to sdk/storage/storage-queue/samples/typescript/src/azureAdAuth.ts index fdebc142fd2d..7c0fbab464d7 100644 --- a/sdk/storage/storage-queue/samples/typescript/azureAdAuth.ts +++ b/sdk/storage/storage-queue/samples/typescript/src/azureAdAuth.ts @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + /* ONLY AVAILABLE IN NODE.JS RUNTIME @@ -18,14 +21,26 @@ - Make sure you have AZURE_TENANT_ID, AZURE_CLIENT_ID, AZURE_CLIENT_SECRET as environment variables to successfully execute the sample(Can leverage process.env). */ -import { QueueServiceClient } from "../../src"; // Change to "@azure/storage-queue" in your package +import { QueueServiceClient } from "@azure/storage-queue"; import { DefaultAzureCredential } from "@azure/identity"; -async function main() { +export async function main() { // Enter your storage account name and shared key const account = process.env.ACCOUNT_NAME || ""; + // Azure AD Credential information is required to run this sample: + if ( + !process.env.AZURE_TENANT_ID || + !process.env.AZURE_CLIENT_ID || + !process.env.AZURE_CLIENT_SECRET + ) { + console.warn( + "Azure AD authentication information not provided, but it is required to run this sample. Exiting." + ); + return; + } + // ONLY AVAILABLE IN NODE.JS RUNTIME // DefaultAzureCredential will first look for Azure Active Directory (AAD) // client secret credentials in the following environment variables: @@ -51,11 +66,6 @@ async function main() { } } -// An async method returns a Promise object, which is compatible with then().catch() coding style. -main() - .then(() => { - console.log("Successfully executed sample."); - }) - .catch((err) => { - console.log(err.message); - }); +main().catch((err) => { + console.error("Error running sample:", err.message); +}); diff --git a/sdk/storage/storage-queue/samples/typescript/basic.ts b/sdk/storage/storage-queue/samples/typescript/src/basic.ts similarity index 92% rename from sdk/storage/storage-queue/samples/typescript/basic.ts rename to sdk/storage/storage-queue/samples/typescript/src/basic.ts index 5596cd8d0618..86f4ad8fa5d9 100644 --- a/sdk/storage/storage-queue/samples/typescript/basic.ts +++ b/sdk/storage/storage-queue/samples/typescript/src/basic.ts @@ -1,10 +1,13 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + /* Setup: Enter your storage account name and shared key in main() */ -import { QueueServiceClient, StorageSharedKeyCredential } from "../../src"; // Change to "@azure/storage-queue" in your package +import { QueueServiceClient, StorageSharedKeyCredential } from "@azure/storage-queue"; -async function main() { +export async function main() { // Enter your storage account name and shared key const account = process.env.ACCOUNT_NAME || ""; const accountKey = process.env.ACCOUNT_KEY || ""; @@ -88,11 +91,6 @@ async function main() { ); } -// An async method returns a Promise object, which is compatible with then().catch() coding style. -main() - .then(() => { - console.log("Successfully executed sample."); - }) - .catch((err) => { - console.log(err.message); - }); +main().catch((err) => { + console.error("Error running sample:", err.message); +}); diff --git a/sdk/storage/storage-queue/samples/typescript/customPipeline.ts b/sdk/storage/storage-queue/samples/typescript/src/customPipeline.ts similarity index 84% rename from sdk/storage/storage-queue/samples/typescript/customPipeline.ts rename to sdk/storage/storage-queue/samples/typescript/src/customPipeline.ts index ac988cd05f87..245626532895 100644 --- a/sdk/storage/storage-queue/samples/typescript/customPipeline.ts +++ b/sdk/storage/storage-queue/samples/typescript/src/customPipeline.ts @@ -1,10 +1,13 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + /* Setup: Enter your storage account name and shared key in main() */ -import { QueueServiceClient, newPipeline, StorageSharedKeyCredential } from "../../src"; // Change to "@azure/storage-queue" in your package +import { QueueServiceClient, newPipeline, StorageSharedKeyCredential } from "@azure/storage-queue"; -async function main() { +export async function main() { // Enter your storage account name and shared key const account = process.env.ACCOUNT_NAME || ""; const accountKey = process.env.ACCOUNT_KEY || ""; @@ -49,11 +52,6 @@ async function main() { ); } -// An async method returns a Promise object, which is compatible with then().catch() coding style. -main() - .then(() => { - console.log("Successfully executed sample."); - }) - .catch((err) => { - console.log(err.message); - }); +main().catch((err) => { + console.error("Error running sample:", err.message); +}); diff --git a/sdk/storage/storage-queue/samples/typescript/iterators.ts b/sdk/storage/storage-queue/samples/typescript/src/iterators.ts similarity index 81% rename from sdk/storage/storage-queue/samples/typescript/iterators.ts rename to sdk/storage/storage-queue/samples/typescript/src/iterators.ts index e06bbc00cbb7..12570674f969 100644 --- a/sdk/storage/storage-queue/samples/typescript/iterators.ts +++ b/sdk/storage/storage-queue/samples/typescript/src/iterators.ts @@ -1,10 +1,15 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + /* Setup: Enter your storage account name and shared key in main() */ -import { QueueServiceClient, StorageSharedKeyCredential } from "../../src"; // Change to "@azure/storage-queue" in your package +import { QueueServiceClient, StorageSharedKeyCredential } from "@azure/storage-queue"; + + -async function main() { +export async function main() { // Enter your storage account name and shared key const account = process.env.ACCOUNT_NAME || ""; const accountKey = process.env.ACCOUNT_KEY || ""; @@ -91,22 +96,21 @@ async function main() { } // Gets next marker let marker = response.value.continuationToken; - // Passing next marker as continuationToken - iterator = queueServiceClient.listQueues().byPage({ continuationToken: marker, maxPageSize: 10 }); - response = await iterator.next(); - // Prints 10 queue names - if (response.value.queueItems) { - for (const queueItem of response.value.queueItems) { - console.log(`Queue ${i++}: ${queueItem.name}`); + if (marker) { + // Passing next marker as continuationToken + iterator = queueServiceClient + .listQueues() + .byPage({ continuationToken: marker, maxPageSize: 10 }); + response = await iterator.next(); + // Prints 10 queue names + if (response.value.queueItems) { + for (const queueItem of response.value.queueItems) { + console.log(`Queue ${i++}: ${queueItem.name}`); + } } } } -// An async method returns a Promise object, which is compatible with then().catch() coding style. -main() - .then(() => { - console.log("Successfully executed sample."); - }) - .catch((err) => { - console.log(err.message); - }); +main().catch((err) => { + console.error("Error running sample:", err.message); +}); diff --git a/sdk/storage/storage-queue/samples/typescript/proxyAuth.ts b/sdk/storage/storage-queue/samples/typescript/src/proxyAuth.ts similarity index 59% rename from sdk/storage/storage-queue/samples/typescript/proxyAuth.ts rename to sdk/storage/storage-queue/samples/typescript/src/proxyAuth.ts index 1b52e7b07084..4616ed1ec649 100644 --- a/sdk/storage/storage-queue/samples/typescript/proxyAuth.ts +++ b/sdk/storage/storage-queue/samples/typescript/src/proxyAuth.ts @@ -1,10 +1,13 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + /* Setup: Enter your storage account name and shared key in main() */ -import { StorageSharedKeyCredential, QueueServiceClient } from "../../src"; // Change to "@azure/storage-queue" in your package +import { StorageSharedKeyCredential, QueueServiceClient } from "@azure/storage-queue"; -async function main() { +export async function main() { // Enter your storage account name and shared key const account = process.env.ACCOUNT_NAME || ""; const accountKey = process.env.ACCOUNT_KEY || ""; @@ -13,20 +16,27 @@ async function main() { // StorageSharedKeyCredential is only avaiable in Node.js runtime, not in browsers const sharedKeyCredential = new StorageSharedKeyCredential(account, accountKey); + // To use the manual proxyOptions below, remove this block + if (!process.env.HTTP_PROXY || !process.env.HTTPS_PROXY) { + console.warn("Proxy information not provided, but it is required to run this sample. Exiting."); + return; + } + const queueServiceClient = new QueueServiceClient( `https://${account}.queue.core.windows.net`, sharedKeyCredential, + // The library tries to load the proxy settings from the environment variables like HTTP_PROXY + // Alternatively, the service client accepts the following `proxyOptions` as part of its options: { - // proxy can either be a URL like "http://localhost:3128" - // or - // an option bag consisting {host, port, username, password } - proxyOptions: { + /* + proxyOptions : { + // To use these options, remove the section above that checks for HTTP_PROXY or HTTPS_PROXY host: "http://localhost", port: 3128, - username: "username", - password: "password" + username: "", + password: "" } - // if proxy is undefined, the library tries to load the proxy settings from the environment variables like HTTP_PROXY + */ } ); @@ -45,11 +55,6 @@ async function main() { ); } -// An async method returns a Promise object, which is compatible with then().catch() coding style. -main() - .then(() => { - console.log("Successfully executed the sample."); - }) - .catch((err) => { - console.log(err.message); - }); +main().catch((err) => { + console.error("Error running sample:", err.message); +}); diff --git a/sdk/storage/storage-queue/samples/typescript/sharedKeyCred.ts b/sdk/storage/storage-queue/samples/typescript/src/sharedKeyCred.ts similarity index 78% rename from sdk/storage/storage-queue/samples/typescript/sharedKeyCred.ts rename to sdk/storage/storage-queue/samples/typescript/src/sharedKeyCred.ts index 114c9371b500..fbc13a880353 100644 --- a/sdk/storage/storage-queue/samples/typescript/sharedKeyCred.ts +++ b/sdk/storage/storage-queue/samples/typescript/src/sharedKeyCred.ts @@ -1,10 +1,13 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + /* Setup: Enter your storage account name and shared key in main() */ -import { QueueServiceClient, StorageSharedKeyCredential } from "../../src"; // Change to "@azure/storage-queue" in your package +import { QueueServiceClient, StorageSharedKeyCredential } from "@azure/storage-queue"; -async function main() { +export async function main() { // Enter your storage account name and shared key const account = process.env.ACCOUNT_NAME || ""; const accountKey = process.env.ACCOUNT_KEY || ""; @@ -33,11 +36,6 @@ async function main() { ); } -// An async method returns a Promise object, which is compatible with then().catch() coding style. -main() - .then(() => { - console.log("Successfully executed sample."); - }) - .catch((err) => { - console.log(err.message); - }); +main().catch((err) => { + console.error("Error running sample:", err.message); +}); diff --git a/sdk/storage/storage-queue/samples/typescript/withConnString.ts b/sdk/storage/storage-queue/samples/typescript/src/withConnString.ts similarity index 79% rename from sdk/storage/storage-queue/samples/typescript/withConnString.ts rename to sdk/storage/storage-queue/samples/typescript/src/withConnString.ts index 329acd5c00f4..949f8a63a2bd 100644 --- a/sdk/storage/storage-queue/samples/typescript/withConnString.ts +++ b/sdk/storage/storage-queue/samples/typescript/src/withConnString.ts @@ -1,10 +1,13 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + /* Setup: Enter your storage account name and shared key in main() */ -import { QueueServiceClient } from "../../src"; // Change to "@azure/storage-queue" in your package +import { QueueServiceClient } from "@azure/storage-queue"; -async function main() { +export async function main() { // Create Queue Service Client from Account connection string or SAS connection string // Account connection string example - `DefaultEndpointsProtocol=https;AccountName=myaccount;AccountKey=accountKey;EndpointSuffix=core.windows.net` // SAS connection string example - `BlobEndpoint=https://myaccount.blob.core.windows.net/;QueueEndpoint=https://myaccount.queue.core.windows.net/;FileEndpoint=https://myaccount.file.core.windows.net/;TableEndpoint=https://myaccount.table.core.windows.net/;SharedAccessSignature=sasString` @@ -27,11 +30,6 @@ async function main() { ); } -// An async method returns a Promise object, which is compatible with then().catch() coding style. -main() - .then(() => { - console.log("Successfully executed sample."); - }) - .catch((err) => { - console.log(err.message); - }); +main().catch((err) => { + console.error("Error running sample:", err.message); +}); diff --git a/sdk/storage/storage-queue/samples/typescript/tsconfig.json b/sdk/storage/storage-queue/samples/typescript/tsconfig.json new file mode 100644 index 000000000000..4332663bf7b7 --- /dev/null +++ b/sdk/storage/storage-queue/samples/typescript/tsconfig.json @@ -0,0 +1,15 @@ +{ + "compilerOptions": { + "module": "commonjs", + "moduleResolution": "node", + + "lib": ["dom", "dom.iterable", "esnext.asynciterable"], + + "allowSyntheticDefaultImports": true, + + "outDir": "dist", + "rootDir": "src" + }, + "include": ["src/**.ts"], + "exclude": ["node_modules"] +}