|
| 1 | +// Copyright (c) Microsoft Corporation. |
| 2 | +// Licensed under the MIT license. |
| 3 | + |
| 4 | +/** |
| 5 | + * Management-plane libraries currently do not support authentication using |
| 6 | + * the `@azure/identity` package. However, there is an adapter that can be used |
| 7 | + * to add support for it without introducing breaking changes. This script |
| 8 | + * enables this adapter in an management-plane library. |
| 9 | + */ |
| 10 | + |
| 11 | +const fs = require("fs"); |
| 12 | +const p = require("path"); |
| 13 | + |
| 14 | +function rewriteFile(path, f) { |
| 15 | + fs.readFile(path, "utf-8", (err, data) => { |
| 16 | + if (err) throw err; |
| 17 | + fs.writeFile(path, f(data), "utf-8", function(err) { |
| 18 | + if (err) throw err; |
| 19 | + console.log(`${p.basename(path)} has been updated`); |
| 20 | + }); |
| 21 | + }); |
| 22 | +} |
| 23 | + |
| 24 | +function getMatch(matches, search, location) { |
| 25 | + if (matches.length < 2) { |
| 26 | + throw new Error(`Could not find ${search} in ${location}`); |
| 27 | + } else { |
| 28 | + return matches[1]; |
| 29 | + } |
| 30 | +} |
| 31 | + |
| 32 | +function updateREADME(content) { |
| 33 | + const pkgName = getMatch( |
| 34 | + content.match(/.+?npm install (@azure\/.+?)$.*/ms), |
| 35 | + "package name", |
| 36 | + "README file" |
| 37 | + ); |
| 38 | + const clientName = getMatch( |
| 39 | + content.match(/## Azure (.+?) SDK for JavaScript$.*/ms), |
| 40 | + "client name", |
| 41 | + "README file" |
| 42 | + ); |
| 43 | + |
| 44 | + return `## Azure ${clientName} SDK for JavaScript |
| 45 | +
|
| 46 | +This package contains an isomorphic SDK (runs both in node.js and in browsers) for ${clientName}. |
| 47 | +
|
| 48 | +### Currently supported environments |
| 49 | +
|
| 50 | +- Node.js version 8.x.x or higher |
| 51 | +- Browser JavaScript |
| 52 | +
|
| 53 | +### How to install |
| 54 | +
|
| 55 | +To use this SDK in your project, you will need to install two packages. |
| 56 | +- \`${pkgName}\` that contains the client. |
| 57 | +- \`@azure/identity\` that contains different credentials for you to authenticate the client using Azure Active Directory. |
| 58 | +
|
| 59 | +Install both packages using the below commands. |
| 60 | +\`\`\`bash |
| 61 | +npm install ${pkgName} |
| 62 | +npm install @azure/identity |
| 63 | +\`\`\` |
| 64 | +Please note that while the credentials from the older [\`@azure/ms-rest-nodeauth\`](https://www.npmjs.com/package/@azure/ms-rest-nodeauth) and [\`@azure/ms-rest-browserauth\`](https://www.npmjs.com/package/@azure/ms-rest-browserauth) packages are still supported, these packages are in maintenance mode receiving critical bug fixes, but no new features. |
| 65 | +We strongly encourage you to use the credentials from \`@azure/identity\` where the latest versions of Azure Active Directory and MSAL APIs are used and more authentication options are provided. |
| 66 | +
|
| 67 | +### How to use |
| 68 | +
|
| 69 | +There are multiple credentials available in the \`@azure/identity\` package to suit your different authentication needs. |
| 70 | +Read about them in detail in [readme for @azure/identity package](https://www.npmjs.com/package/@azure/identity). |
| 71 | +To get started you can use the [DefaultAzureCredential](https://github.com/Azure/azure-sdk-for-js/blob/master/sdk/identity/identity/README.md#defaultazurecredential) which tries different credentials internally until one of them succeeds. |
| 72 | +Most of the credentials would require you to [create an Azure App Registration](https://docs.microsoft.com/en-us/azure/active-directory/develop/app-objects-and-service-principals#application-registration) first. |
| 73 | +#### nodejs - Authentication, client creation, and get apps as an example written in JavaScript. |
| 74 | +
|
| 75 | +##### Sample code |
| 76 | +
|
| 77 | +\`\`\`javascript |
| 78 | +const { DefaultAzureCredential } = require("@azure/identity"); |
| 79 | +const { IotCentralClient } = require("@azure/arm-iotcentral"); |
| 80 | +const subscriptionId = process.env["AZURE_SUBSCRIPTION_ID"]; |
| 81 | +
|
| 82 | +// Create credentials using the \`@azure/identity\` package. |
| 83 | +// Please note that you can also use credentials from the \`@azure/ms-rest-nodeauth\` package instead. |
| 84 | +const creds = new DefaultAzureCredential(); |
| 85 | +const client = new IotCentralClient(creds, subscriptionId); |
| 86 | +const resourceGroupName = "testresourceGroupName"; |
| 87 | +const resourceName = "testresourceName"; |
| 88 | +client.apps.get(resourceGroupName, resourceName).then((result) => { |
| 89 | + console.log("The result is:"); |
| 90 | + console.log(result); |
| 91 | +}).catch((err) => { |
| 92 | + console.log("An error occurred:"); |
| 93 | + console.error(err); |
| 94 | +}); |
| 95 | +\`\`\` |
| 96 | +
|
| 97 | +#### browser - Authentication, client creation, and get apps as an example written in JavaScript. |
| 98 | +
|
| 99 | +In browser applications, we recommend using the \`InteractiveBrowserCredential\` that interactively authenticates using the default system browser. |
| 100 | +It is necessary to [create an Azure App Registration](https://docs.microsoft.com/azure/active-directory/develop/scenario-spa-app-registration) in the portal for your web application first. |
| 101 | +
|
| 102 | +##### Sample code |
| 103 | +
|
| 104 | +- index.html |
| 105 | +
|
| 106 | +\`\`\`html |
| 107 | +<!DOCTYPE html> |
| 108 | +<html lang="en"> |
| 109 | + <head> |
| 110 | + <title>@azure/arm-iotcentral sample</title> |
| 111 | + <script src="node_modules/@azure/ms-rest-azure-js/dist/msRestAzure.js"></script> |
| 112 | + <script src="node_modules/@azure/identity/dist/index.js"></script> |
| 113 | + <script src="node_modules/@azure/arm-iotcentral/dist/arm-iotcentral.js"></script> |
| 114 | + <script type="text/javascript"> |
| 115 | + const subscriptionId = "<Subscription_Id>"; |
| 116 | + // Create credentials using the \`@azure/identity\` package. |
| 117 | + // Please note that you can also use credentials from the \`@azure/ms-rest-browserauth\` package instead. |
| 118 | + const credential = new InteractiveBrowserCredential( |
| 119 | + { |
| 120 | + clientId: "<client id for your Azure AD app>", |
| 121 | + tenant: "<optional tenant for your organization>" |
| 122 | + }); |
| 123 | + const client = new Azure.ArmIotcentral.IotCentralClient(creds, subscriptionId); |
| 124 | + const resourceGroupName = "testresourceGroupName"; |
| 125 | + const resourceName = "testresourceName"; |
| 126 | + client.apps.get(resourceGroupName, resourceName).then((result) => { |
| 127 | + console.log("The result is:"); |
| 128 | + console.log(result); |
| 129 | + }).catch((err) => { |
| 130 | + console.log("An error occurred:"); |
| 131 | + console.error(err); |
| 132 | + }); |
| 133 | + </script> |
| 134 | + </head> |
| 135 | + <body></body> |
| 136 | +</html> |
| 137 | +\`\`\` |
| 138 | +
|
| 139 | +## Related projects |
| 140 | +
|
| 141 | +- [Microsoft Azure SDK for Javascript](https://github.com/Azure/azure-sdk-for-js) |
| 142 | +
|
| 143 | + |
| 144 | +`; |
| 145 | +} |
| 146 | + |
| 147 | +function updatePackageJson(newPackageVersion) { |
| 148 | + return function(content) { |
| 149 | + return content |
| 150 | + .replace(/"version": "\d+.\d+.\d+",/ms, `"version": "${newPackageVersion}",`) |
| 151 | + .replace(/"@azure\/ms-rest-azure-js": "\^?(\d+).\d+.\d+"/ms, function(match, major) { |
| 152 | + return major === "1" |
| 153 | + ? '"@azure/ms-rest-azure-js": "^1.4.0"' |
| 154 | + : '"@azure/ms-rest-azure-js": "^2.1.0"'; |
| 155 | + }) |
| 156 | + .replace(/"@azure\/ms-rest-js": "\^?(\d+).\d+.\d+"/ms, function(match, major) { |
| 157 | + return ( |
| 158 | + (major === "1" ? '"@azure/ms-rest-js": "^1.11.0"' : '"@azure/ms-rest-js": "^2.2.0"') + |
| 159 | + ',\n "@azure/core-auth": "^1.1.4"' |
| 160 | + ); |
| 161 | + }) |
| 162 | + .replace(/"typescript": ".+?"/ms, '"typescript": "^3.6.0"'); |
| 163 | + }; |
| 164 | +} |
| 165 | + |
| 166 | +function getClientFilePath(path) { |
| 167 | + const files = fs.readdirSync(p.join(path, "src")); |
| 168 | + for (const file of files) { |
| 169 | + if (file.match(/.+?Client.ts/)) { |
| 170 | + return p.join("src", file); |
| 171 | + } |
| 172 | + } |
| 173 | + throw new Error(`Could not find the src/*Client.ts file`); |
| 174 | +} |
| 175 | + |
| 176 | +function getClientContextFilePath(path) { |
| 177 | + const files = fs.readdirSync(p.join(path, "src")); |
| 178 | + for (const file of files) { |
| 179 | + if (file.match(/.+?ClientContext.ts/)) { |
| 180 | + return p.join("src", file); |
| 181 | + } |
| 182 | + } |
| 183 | + throw new Error(`Could not find the src/*ClientContext.ts file`); |
| 184 | +} |
| 185 | + |
| 186 | +function updateClient(content) { |
| 187 | + const newCredComment = `@param credentials Credentials needed for the client to connect to Azure. Credentials |
| 188 | + * implementing the TokenCredential interface from the @azure/identity package are recommended. For |
| 189 | + * more information about these credentials, see |
| 190 | + * {@link https://www.npmjs.com/package/@azure/identity}. Credentials implementing the |
| 191 | + * ServiceClientCredentials interface from the older packages @azure/ms-rest-nodeauth and |
| 192 | + * @azure/ms-rest-browserauth are also supported.`; |
| 193 | + return content |
| 194 | + .replace( |
| 195 | + /^import \* as msRest from "@azure\/ms-rest-js";/ms, |
| 196 | + 'import * as msRest from "@azure/ms-rest-js";\nimport { TokenCredential } from "@azure/core-auth";' |
| 197 | + ) |
| 198 | + .replace(/ServiceClientCredentials/gms, "ServiceClientCredentials | TokenCredential") |
| 199 | + .replace( |
| 200 | + /@param credentials Credentials needed for the client to connect to Azure./ms, |
| 201 | + newCredComment |
| 202 | + ); |
| 203 | +} |
| 204 | + |
| 205 | +function updateClientContext(newPackageVersion) { |
| 206 | + return function(content) { |
| 207 | + return updateClient(content).replace( |
| 208 | + /const packageVersion = "\d+\.\d+\.\d+";/, |
| 209 | + `const packageVersion = "${newPackageVersion}";` |
| 210 | + ); |
| 211 | + }; |
| 212 | +} |
| 213 | + |
| 214 | +function getPackageVersion(packageJsonPath) { |
| 215 | + const data = fs.readFileSync(packageJsonPath, "utf-8"); |
| 216 | + const versionMatch = data.match(/"version": "(\d+).(\d+).\d+",/ms); |
| 217 | + return `${versionMatch[1]}.${(parseInt(versionMatch[2]) + 1).toString()}.0`; |
| 218 | +} |
| 219 | + |
| 220 | +function main(args) { |
| 221 | + if (args.length !== 3) { |
| 222 | + throw new Error( |
| 223 | + "Expected exactly one command-line argument for the path of the package to be updated" |
| 224 | + ); |
| 225 | + } |
| 226 | + const path = args[2]; |
| 227 | + const packageJsonPath = p.join(path, "package.json"); |
| 228 | + const newPackageVersion = getPackageVersion(packageJsonPath); |
| 229 | + rewriteFile(p.join(path, "README.md"), updateREADME); |
| 230 | + rewriteFile(packageJsonPath, updatePackageJson(newPackageVersion)); |
| 231 | + rewriteFile(p.join(path, getClientFilePath(path)), updateClient); |
| 232 | + rewriteFile(p.join(path, getClientContextFilePath(path)), updateClientContext(newPackageVersion)); |
| 233 | +} |
| 234 | + |
| 235 | +main(process.argv); |
0 commit comments