diff --git a/.github/workflows/check-dist.yml b/.github/workflows/check-dist.yml index ec05c3e..f476ceb 100644 --- a/.github/workflows/check-dist.yml +++ b/.github/workflows/check-dist.yml @@ -23,10 +23,10 @@ jobs: steps: - uses: actions/checkout@v4 - - name: Set Node.js 16.x + - name: Set Node.js 20 uses: actions/setup-node@v3 with: - node-version: 16.x + node-version: 20.x - name: Install dependencies run: npm ci diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 64ef4f2..a2537fa 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -33,7 +33,5 @@ jobs: - name: Live Test uses: ./ with: - subscriptionId: ${{ vars.AZURE_SUBSCRIPTION_ID }} - resourceGroup: ${{ vars.AZURE_RESOURCE_GROUP }} - templateFile: test/scenarios/static-error/main.bicep - parametersFile: test/scenarios/static-error/main.bicepparam + action: validate + config: test/live/config.json \ No newline at end of file diff --git a/action.yml b/action.yml index 96ed49b..174aaa8 100644 --- a/action.yml +++ b/action.yml @@ -1,27 +1,17 @@ name: 'Bicep Action' -description: 'Testing with Bicep Action' +description: 'Runs various Bicep deployment scenarios' author: 'Anthony Martin' inputs: repo-token: description: "A GitHub token for API access. Defaults to {{ github.token }}." default: "${{ github.token }}" required: true - subscriptionId: + config: + description: "Path to the JSON configuration file" required: true - description: 'Subscription Id' - resourceGroup: + action: + description: "The action to perform" required: true - description: 'Resource Group' - templateFile: - required: true - description: 'Template File' - parametersFile: - required: true - description: 'Parameters File' - whatIf: - required: false - description: 'Run what-if' - default: false runs: - using: 'node16' + using: 'node20' main: 'dist/index.js' \ No newline at end of file diff --git a/dist/index.js b/dist/index.js index 5e641e4..21301d5 100644 --- a/dist/index.js +++ b/dist/index.js @@ -1,156 +1,114 @@ require('./sourcemap-register.js');/******/ (() => { // webpackBootstrap /******/ var __webpack_modules__ = ({ -/***/ 446: -/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { - -"use strict"; - -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.whatif = exports.validate = exports.AzCli = void 0; -const io_1 = __nccwpck_require__(436); -const exec_1 = __nccwpck_require__(514); -class AzCli { - execute(parameters) { - return __awaiter(this, void 0, void 0, function* () { - const azPath = yield (0, io_1.which)("az"); - return yield (0, exec_1.getExecOutput)(azPath, parameters, { - silent: true, - failOnStdErr: false, - ignoreReturnCode: true - }); - }); - } -} -exports.AzCli = AzCli; -function validate(wrapper, params) { - return __awaiter(this, void 0, void 0, function* () { - const parameters = [ - "deployment", - "group", - "validate", - ...(params.managementGroup - ? ["--management-group", params.managementGroup] - : []), - ...(params.subscriptionId ? ["--subscription", params.subscriptionId] : []), - ...(params.resourceGroup ? ["--resource-group", params.resourceGroup] : []), - ...(params.deploymentName ? ["--name", params.deploymentName] : []), - ...["--template-file", params.templateFile], - ...(params.parametersFile ? ["--parameters", params.parametersFile] : []), - ...["--output", "json"], - ...["--only-show-errors"] - ]; - return yield wrapper.execute(parameters); - }); -} -exports.validate = validate; -function whatif(wrapper, params) { - return __awaiter(this, void 0, void 0, function* () { - const parameters = [ - "deployment", - "group", - "what-if", - ...(params.managementGroup - ? ["--management-group", params.managementGroup] - : []), - ...(params.subscriptionId ? ["--subscription", params.subscriptionId] : []), - ...(params.resourceGroup ? ["--resource-group", params.resourceGroup] : []), - ...(params.deploymentName ? ["--name", params.deploymentName] : []), - ...["--template-file", params.templateFile], - ...(params.parametersFile ? ["--parameters", params.parametersFile] : []), - ...["--output", "json"], - ...["--only-show-errors"], - ...["--no-pretty-print"] - ]; - return yield wrapper.execute(parameters); - }); -} -exports.whatif = whatif; - - -/***/ }), - -/***/ 180: -/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { +/***/ 4690: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { "use strict"; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; Object.defineProperty(exports, "__esModule", ({ value: true })); exports.getInputs = void 0; -const core_1 = __nccwpck_require__(186); -function getInputs() { - return __awaiter(this, void 0, void 0, function* () { - const subscriptionId = (0, core_1.getInput)("subscriptionId", { required: true }); - const resourceGroup = (0, core_1.getInput)("resourceGroup", { required: true }); - const templateFile = (0, core_1.getInput)("templateFile", { required: true }); - const parametersFile = (0, core_1.getInput)("parametersFile", { required: true }); - const runWhatIf = (0, core_1.getBooleanInput)('whatIf', { required: false }); - return { - subscriptionId, - resourceGroup, - templateFile, - parametersFile, - runWhatIf, - }; - }); +const core_1 = __nccwpck_require__(2186); +async function getInputs() { + const action = (0, core_1.getInput)("action", { required: true }); + const config = (0, core_1.getInput)("config", { required: true }); + return { + action, + config + }; } exports.getInputs = getInputs; - +//# sourceMappingURL=inputs.js.map /***/ }), -/***/ 109: +/***/ 9496: /***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { "use strict"; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", ({ value: true })); -const core_1 = __nccwpck_require__(186); -const azcli_1 = __nccwpck_require__(446); -const run_1 = __nccwpck_require__(884); -const inputs_1 = __nccwpck_require__(180); -function run() { - return __awaiter(this, void 0, void 0, function* () { - const inputs = yield (0, inputs_1.getInputs)(); - const markdown = inputs.runWhatIf ? - yield (0, run_1.whatIfAndGetMarkdown)(new azcli_1.AzCli(), inputs) : - yield (0, run_1.validateAndGetMarkdown)(new azcli_1.AzCli(), inputs); +const core_1 = __nccwpck_require__(2186); +const exec_1 = __nccwpck_require__(1514); +const inputs_1 = __nccwpck_require__(4690); +const promises_1 = __nccwpck_require__(3292); +const bicep_node_1 = __nccwpck_require__(837); +const os_1 = __importDefault(__nccwpck_require__(2037)); +const core_rest_pipeline_1 = __nccwpck_require__(8121); +const arm_resources_1 = __nccwpck_require__(4280); +const identity_1 = __nccwpck_require__(3084); +const markdown_1 = __nccwpck_require__(8794); +const path_1 = __importDefault(__nccwpck_require__(1017)); +async function run() { + const inputs = await (0, inputs_1.getInputs)(); + const configPath = path_1.default.normalize(inputs.config); + const config = JSON.parse(await (0, promises_1.readFile)(configPath, "utf8")); + const bicepParamsPath = path_1.default.join(path_1.default.dirname(configPath), config.bicepParamsFile); + if (inputs.action !== "validate") { + throw `Unsupported action: ${inputs.action}`; + } + const bicepPath = await bicep_node_1.Bicep.install(os_1.default.tmpdir(), config.bicepVersion); + //export BICEP_PARAMETERS_OVERRIDES='{"env": "dev"}' + const result = await (0, exec_1.getExecOutput)(bicepPath, [ + "build-params", + "--stdout", + bicepParamsPath + ]); + if (result.exitCode !== 0) { + throw result.stderr; + } + const buildParamsOutput = JSON.parse(result.stdout); + if (!buildParamsOutput.templateJson) { + throw "Template JSON not found in build-params output"; + } + const client = new arm_resources_1.ResourceManagementClient(new identity_1.AzureCliCredential(), config.subscriptionId); + const template = JSON.parse(buildParamsOutput.templateJson); + const { parameters } = JSON.parse(buildParamsOutput.parametersJson); + const scope = `/subscriptions/${config.subscriptionId}/resourceGroups/${config.resourceGroup}`; + let error; + try { + const poller = await client.deployments.beginValidateAtScope(scope, config.name, { + properties: { + template, + parameters, + mode: "Incremental" + } + }); + const validateResult = await poller.pollUntilDone(); + error = validateResult.error; + } + catch (e) { + error = parseError(e); + } + if (error === null || error === void 0 ? void 0 : error.details) { + const markdown = (0, markdown_1.combine)([ + (0, markdown_1.getResultHeading)("Validate Results", false), + (0, markdown_1.convertTableToString)((0, markdown_1.getErrorTable)(error.details)) + ]); core_1.summary.addRaw(markdown).write(); - }); + } + else { + const markdown = (0, markdown_1.getResultHeading)("Validate Results", true); + core_1.summary.addRaw(markdown).write(); + } +} +function parseError(error) { + if (error instanceof core_rest_pipeline_1.RestError) { + return error.details.error; + } + return { + message: `${error}`, + }; } run(); - +//# sourceMappingURL=main.js.map /***/ }), -/***/ 821: +/***/ 8794: /***/ ((__unused_webpack_module, exports) => { "use strict"; @@ -210,83 +168,11 @@ function convertTableToString(rows) { return mdRows.join("\n"); } exports.convertTableToString = convertTableToString; - - -/***/ }), - -/***/ 884: -/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { - -"use strict"; - -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.whatIfAndGetMarkdown = exports.validateAndGetMarkdown = void 0; -const azcli_1 = __nccwpck_require__(446); -const markdown_1 = __nccwpck_require__(821); -function validateAndGetMarkdown(azCli, parameters) { - return __awaiter(this, void 0, void 0, function* () { - const heading = "Validate Results"; - const result = yield (0, azcli_1.validate)(azCli, parameters); - if (result.exitCode !== 0) { - const errors = parseErrors(result.stderr); - return (0, markdown_1.combine)([(0, markdown_1.getResultHeading)(heading, false), (0, markdown_1.convertTableToString)((0, markdown_1.getErrorTable)(errors))]); - } - else { - return (0, markdown_1.combine)([(0, markdown_1.getResultHeading)(heading, true)]); - } - }); -} -exports.validateAndGetMarkdown = validateAndGetMarkdown; -function whatIfAndGetMarkdown(azCli, parameters) { - var _a; - return __awaiter(this, void 0, void 0, function* () { - const heading = "What-If Results"; - const result = yield (0, azcli_1.whatif)(azCli, parameters); - let resultHeading, body; - if (result.exitCode !== 0) { - resultHeading = (0, markdown_1.getResultHeading)(heading, false); - const errors = parseErrors(result.stderr); - body = (0, markdown_1.getErrorTable)(errors); - } - else { - resultHeading = (0, markdown_1.getResultHeading)(heading, true); - const response = JSON.parse(result.stdout); - body = (0, markdown_1.getWhatIfTable)((_a = response.changes) !== null && _a !== void 0 ? _a : []); - } - return (0, markdown_1.combine)([resultHeading, (0, markdown_1.convertTableToString)(body)]); - }); -} -exports.whatIfAndGetMarkdown = whatIfAndGetMarkdown; -function parseErrors(stderr) { - if (stderr.startsWith("ERROR: ")) { - stderr = stderr.substring("ERROR: ".length); - } - const errors = []; - const split = stderr.split(/\r?\n/); - for (const line of split) { - if (line.startsWith("{")) { - errors.push(JSON.parse(line)); - } - else if (/^(.+)\((\d+),(\d+)\)\s:\s(Error|Warning|Info)\s(.+):\s(.+)$/.test(line)) { - errors.push({ code: "BicepBuildError", message: line }); - } - } - return errors; -} - +//# sourceMappingURL=markdown.js.map /***/ }), -/***/ 351: +/***/ 7351: /***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { "use strict"; @@ -312,8 +198,8 @@ var __importStar = (this && this.__importStar) || function (mod) { }; Object.defineProperty(exports, "__esModule", ({ value: true })); exports.issue = exports.issueCommand = void 0; -const os = __importStar(__nccwpck_require__(37)); -const utils_1 = __nccwpck_require__(278); +const os = __importStar(__nccwpck_require__(2037)); +const utils_1 = __nccwpck_require__(5278); /** * Commands * @@ -385,7 +271,7 @@ function escapeProperty(s) { /***/ }), -/***/ 186: +/***/ 2186: /***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { "use strict"; @@ -420,12 +306,12 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge }; Object.defineProperty(exports, "__esModule", ({ value: true })); exports.getIDToken = exports.getState = exports.saveState = exports.group = exports.endGroup = exports.startGroup = exports.info = exports.notice = exports.warning = exports.error = exports.debug = exports.isDebug = exports.setFailed = exports.setCommandEcho = exports.setOutput = exports.getBooleanInput = exports.getMultilineInput = exports.getInput = exports.addPath = exports.setSecret = exports.exportVariable = exports.ExitCode = void 0; -const command_1 = __nccwpck_require__(351); +const command_1 = __nccwpck_require__(7351); const file_command_1 = __nccwpck_require__(717); -const utils_1 = __nccwpck_require__(278); -const os = __importStar(__nccwpck_require__(37)); -const path = __importStar(__nccwpck_require__(17)); -const oidc_utils_1 = __nccwpck_require__(41); +const utils_1 = __nccwpck_require__(5278); +const os = __importStar(__nccwpck_require__(2037)); +const path = __importStar(__nccwpck_require__(1017)); +const oidc_utils_1 = __nccwpck_require__(8041); /** * The code to exit an action */ @@ -710,17 +596,17 @@ exports.getIDToken = getIDToken; /** * Summary exports */ -var summary_1 = __nccwpck_require__(327); +var summary_1 = __nccwpck_require__(1327); Object.defineProperty(exports, "summary", ({ enumerable: true, get: function () { return summary_1.summary; } })); /** * @deprecated use core.summary */ -var summary_2 = __nccwpck_require__(327); +var summary_2 = __nccwpck_require__(1327); Object.defineProperty(exports, "markdownSummary", ({ enumerable: true, get: function () { return summary_2.markdownSummary; } })); /** * Path exports */ -var path_utils_1 = __nccwpck_require__(981); +var path_utils_1 = __nccwpck_require__(2981); Object.defineProperty(exports, "toPosixPath", ({ enumerable: true, get: function () { return path_utils_1.toPosixPath; } })); Object.defineProperty(exports, "toWin32Path", ({ enumerable: true, get: function () { return path_utils_1.toWin32Path; } })); Object.defineProperty(exports, "toPlatformPath", ({ enumerable: true, get: function () { return path_utils_1.toPlatformPath; } })); @@ -757,10 +643,10 @@ Object.defineProperty(exports, "__esModule", ({ value: true })); exports.prepareKeyValueMessage = exports.issueFileCommand = void 0; // We use any as a valid input type /* eslint-disable @typescript-eslint/no-explicit-any */ -const fs = __importStar(__nccwpck_require__(147)); -const os = __importStar(__nccwpck_require__(37)); -const uuid_1 = __nccwpck_require__(840); -const utils_1 = __nccwpck_require__(278); +const fs = __importStar(__nccwpck_require__(7147)); +const os = __importStar(__nccwpck_require__(2037)); +const uuid_1 = __nccwpck_require__(5840); +const utils_1 = __nccwpck_require__(5278); function issueFileCommand(command, message) { const filePath = process.env[`GITHUB_${command}`]; if (!filePath) { @@ -793,7 +679,7 @@ exports.prepareKeyValueMessage = prepareKeyValueMessage; /***/ }), -/***/ 41: +/***/ 8041: /***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { "use strict"; @@ -809,9 +695,9 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge }; Object.defineProperty(exports, "__esModule", ({ value: true })); exports.OidcClient = void 0; -const http_client_1 = __nccwpck_require__(255); -const auth_1 = __nccwpck_require__(526); -const core_1 = __nccwpck_require__(186); +const http_client_1 = __nccwpck_require__(6255); +const auth_1 = __nccwpck_require__(5526); +const core_1 = __nccwpck_require__(2186); class OidcClient { static createHttpClient(allowRetry = true, maxRetry = 10) { const requestOptions = { @@ -877,7 +763,7 @@ exports.OidcClient = OidcClient; /***/ }), -/***/ 981: +/***/ 2981: /***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { "use strict"; @@ -903,7 +789,7 @@ var __importStar = (this && this.__importStar) || function (mod) { }; Object.defineProperty(exports, "__esModule", ({ value: true })); exports.toPlatformPath = exports.toWin32Path = exports.toPosixPath = void 0; -const path = __importStar(__nccwpck_require__(17)); +const path = __importStar(__nccwpck_require__(1017)); /** * toPosixPath converts the given path to the posix form. On Windows, \\ will be * replaced with /. @@ -942,7 +828,7 @@ exports.toPlatformPath = toPlatformPath; /***/ }), -/***/ 327: +/***/ 1327: /***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { "use strict"; @@ -958,8 +844,8 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge }; Object.defineProperty(exports, "__esModule", ({ value: true })); exports.summary = exports.markdownSummary = exports.SUMMARY_DOCS_URL = exports.SUMMARY_ENV_VAR = void 0; -const os_1 = __nccwpck_require__(37); -const fs_1 = __nccwpck_require__(147); +const os_1 = __nccwpck_require__(2037); +const fs_1 = __nccwpck_require__(7147); const { access, appendFile, writeFile } = fs_1.promises; exports.SUMMARY_ENV_VAR = 'GITHUB_STEP_SUMMARY'; exports.SUMMARY_DOCS_URL = 'https://docs.github.com/actions/using-workflows/workflow-commands-for-github-actions#adding-a-job-summary'; @@ -1232,7 +1118,7 @@ exports.summary = _summary; /***/ }), -/***/ 278: +/***/ 5278: /***/ ((__unused_webpack_module, exports) => { "use strict"; @@ -1279,7 +1165,7 @@ exports.toCommandProperties = toCommandProperties; /***/ }), -/***/ 514: +/***/ 1514: /***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { "use strict"; @@ -1314,8 +1200,8 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge }; Object.defineProperty(exports, "__esModule", ({ value: true })); exports.getExecOutput = exports.exec = void 0; -const string_decoder_1 = __nccwpck_require__(576); -const tr = __importStar(__nccwpck_require__(159)); +const string_decoder_1 = __nccwpck_require__(1576); +const tr = __importStar(__nccwpck_require__(8159)); /** * Exec a command. * Output will be streamed to the live console. @@ -1389,7 +1275,7 @@ exports.getExecOutput = getExecOutput; /***/ }), -/***/ 159: +/***/ 8159: /***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { "use strict"; @@ -1424,13 +1310,13 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge }; Object.defineProperty(exports, "__esModule", ({ value: true })); exports.argStringToArray = exports.ToolRunner = void 0; -const os = __importStar(__nccwpck_require__(37)); -const events = __importStar(__nccwpck_require__(361)); -const child = __importStar(__nccwpck_require__(81)); -const path = __importStar(__nccwpck_require__(17)); -const io = __importStar(__nccwpck_require__(436)); -const ioUtil = __importStar(__nccwpck_require__(962)); -const timers_1 = __nccwpck_require__(512); +const os = __importStar(__nccwpck_require__(2037)); +const events = __importStar(__nccwpck_require__(2361)); +const child = __importStar(__nccwpck_require__(2081)); +const path = __importStar(__nccwpck_require__(1017)); +const io = __importStar(__nccwpck_require__(7436)); +const ioUtil = __importStar(__nccwpck_require__(1962)); +const timers_1 = __nccwpck_require__(9512); /* eslint-disable @typescript-eslint/unbound-method */ const IS_WINDOWS = process.platform === 'win32'; /* @@ -2014,7 +1900,7 @@ class ExecState extends events.EventEmitter { /***/ }), -/***/ 526: +/***/ 5526: /***/ (function(__unused_webpack_module, exports) { "use strict"; @@ -2102,7 +1988,7 @@ exports.PersonalAccessTokenCredentialHandler = PersonalAccessTokenCredentialHand /***/ }), -/***/ 255: +/***/ 6255: /***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { "use strict"; @@ -2138,10 +2024,10 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge }; Object.defineProperty(exports, "__esModule", ({ value: true })); exports.HttpClient = exports.isHttps = exports.HttpClientResponse = exports.HttpClientError = exports.getProxyUrl = exports.MediaTypes = exports.Headers = exports.HttpCodes = void 0; -const http = __importStar(__nccwpck_require__(685)); -const https = __importStar(__nccwpck_require__(687)); -const pm = __importStar(__nccwpck_require__(835)); -const tunnel = __importStar(__nccwpck_require__(294)); +const http = __importStar(__nccwpck_require__(3685)); +const https = __importStar(__nccwpck_require__(5687)); +const pm = __importStar(__nccwpck_require__(9835)); +const tunnel = __importStar(__nccwpck_require__(4294)); var HttpCodes; (function (HttpCodes) { HttpCodes[HttpCodes["OK"] = 200] = "OK"; @@ -2727,7 +2613,7 @@ const lowercaseKeys = (obj) => Object.keys(obj).reduce((c, k) => ((c[k.toLowerCa /***/ }), -/***/ 835: +/***/ 9835: /***/ ((__unused_webpack_module, exports) => { "use strict"; @@ -2816,7 +2702,7 @@ function isLoopbackAddress(host) { /***/ }), -/***/ 962: +/***/ 1962: /***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { "use strict"; @@ -2852,8 +2738,8 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge var _a; Object.defineProperty(exports, "__esModule", ({ value: true })); exports.getCmdPath = exports.tryGetExecutablePath = exports.isRooted = exports.isDirectory = exports.exists = exports.READONLY = exports.UV_FS_O_EXLOCK = exports.IS_WINDOWS = exports.unlink = exports.symlink = exports.stat = exports.rmdir = exports.rm = exports.rename = exports.readlink = exports.readdir = exports.open = exports.mkdir = exports.lstat = exports.copyFile = exports.chmod = void 0; -const fs = __importStar(__nccwpck_require__(147)); -const path = __importStar(__nccwpck_require__(17)); +const fs = __importStar(__nccwpck_require__(7147)); +const path = __importStar(__nccwpck_require__(1017)); _a = fs.promises // export const {open} = 'fs' , exports.chmod = _a.chmod, exports.copyFile = _a.copyFile, exports.lstat = _a.lstat, exports.mkdir = _a.mkdir, exports.open = _a.open, exports.readdir = _a.readdir, exports.readlink = _a.readlink, exports.rename = _a.rename, exports.rm = _a.rm, exports.rmdir = _a.rmdir, exports.stat = _a.stat, exports.symlink = _a.symlink, exports.unlink = _a.unlink; @@ -3006,7 +2892,7 @@ exports.getCmdPath = getCmdPath; /***/ }), -/***/ 436: +/***/ 7436: /***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { "use strict"; @@ -3041,9 +2927,9 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge }; Object.defineProperty(exports, "__esModule", ({ value: true })); exports.findInPath = exports.which = exports.mkdirP = exports.rmRF = exports.mv = exports.cp = void 0; -const assert_1 = __nccwpck_require__(491); -const path = __importStar(__nccwpck_require__(17)); -const ioUtil = __importStar(__nccwpck_require__(962)); +const assert_1 = __nccwpck_require__(9491); +const path = __importStar(__nccwpck_require__(1017)); +const ioUtil = __importStar(__nccwpck_require__(1962)); /** * Copies a file or folder. * Based off of shelljs - https://github.com/shelljs/shelljs/blob/9237f66c52e5daa40458f94f9565e18e8132f5a6/src/cp.js @@ -3312,75 +3198,61031 @@ function copyFile(srcFile, destFile, force) { /***/ }), -/***/ 294: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { +/***/ 2557: +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ value: true })); + +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. +/// +const listenersMap = new WeakMap(); +const abortedMap = new WeakMap(); +/** + * An aborter instance implements AbortSignal interface, can abort HTTP requests. + * + * - Call AbortSignal.none to create a new AbortSignal instance that cannot be cancelled. + * Use `AbortSignal.none` when you are required to pass a cancellation token but the operation + * cannot or will not ever be cancelled. + * + * @example + * Abort without timeout + * ```ts + * await doAsyncWork(AbortSignal.none); + * ``` + */ +class AbortSignal { + constructor() { + /** + * onabort event listener. + */ + this.onabort = null; + listenersMap.set(this, []); + abortedMap.set(this, false); + } + /** + * Status of whether aborted or not. + * + * @readonly + */ + get aborted() { + if (!abortedMap.has(this)) { + throw new TypeError("Expected `this` to be an instance of AbortSignal."); + } + return abortedMap.get(this); + } + /** + * Creates a new AbortSignal instance that will never be aborted. + * + * @readonly + */ + static get none() { + return new AbortSignal(); + } + /** + * Added new "abort" event listener, only support "abort" event. + * + * @param _type - Only support "abort" event + * @param listener - The listener to be added + */ + addEventListener( + // tslint:disable-next-line:variable-name + _type, listener) { + if (!listenersMap.has(this)) { + throw new TypeError("Expected `this` to be an instance of AbortSignal."); + } + const listeners = listenersMap.get(this); + listeners.push(listener); + } + /** + * Remove "abort" event listener, only support "abort" event. + * + * @param _type - Only support "abort" event + * @param listener - The listener to be removed + */ + removeEventListener( + // tslint:disable-next-line:variable-name + _type, listener) { + if (!listenersMap.has(this)) { + throw new TypeError("Expected `this` to be an instance of AbortSignal."); + } + const listeners = listenersMap.get(this); + const index = listeners.indexOf(listener); + if (index > -1) { + listeners.splice(index, 1); + } + } + /** + * Dispatches a synthetic event to the AbortSignal. + */ + dispatchEvent(_event) { + throw new Error("This is a stub dispatchEvent implementation that should not be used. It only exists for type-checking purposes."); + } +} +/** + * Helper to trigger an abort event immediately, the onabort and all abort event listeners will be triggered. + * Will try to trigger abort event for all linked AbortSignal nodes. + * + * - If there is a timeout, the timer will be cancelled. + * - If aborted is true, nothing will happen. + * + * @internal + */ +// eslint-disable-next-line @azure/azure-sdk/ts-use-interface-parameters +function abortSignal(signal) { + if (signal.aborted) { + return; + } + if (signal.onabort) { + signal.onabort.call(signal); + } + const listeners = listenersMap.get(signal); + if (listeners) { + // Create a copy of listeners so mutations to the array + // (e.g. via removeListener calls) don't affect the listeners + // we invoke. + listeners.slice().forEach((listener) => { + listener.call(signal, { type: "abort" }); + }); + } + abortedMap.set(signal, true); +} + +// Copyright (c) Microsoft Corporation. +/** + * This error is thrown when an asynchronous operation has been aborted. + * Check for this error by testing the `name` that the name property of the + * error matches `"AbortError"`. + * + * @example + * ```ts + * const controller = new AbortController(); + * controller.abort(); + * try { + * doAsyncWork(controller.signal) + * } catch (e) { + * if (e.name === 'AbortError') { + * // handle abort error here. + * } + * } + * ``` + */ +class AbortError extends Error { + constructor(message) { + super(message); + this.name = "AbortError"; + } +} +/** + * An AbortController provides an AbortSignal and the associated controls to signal + * that an asynchronous operation should be aborted. + * + * @example + * Abort an operation when another event fires + * ```ts + * const controller = new AbortController(); + * const signal = controller.signal; + * doAsyncWork(signal); + * button.addEventListener('click', () => controller.abort()); + * ``` + * + * @example + * Share aborter cross multiple operations in 30s + * ```ts + * // Upload the same data to 2 different data centers at the same time, + * // abort another when any of them is finished + * const controller = AbortController.withTimeout(30 * 1000); + * doAsyncWork(controller.signal).then(controller.abort); + * doAsyncWork(controller.signal).then(controller.abort); + *``` + * + * @example + * Cascaded aborting + * ```ts + * // All operations can't take more than 30 seconds + * const aborter = Aborter.timeout(30 * 1000); + * + * // Following 2 operations can't take more than 25 seconds + * await doAsyncWork(aborter.withTimeout(25 * 1000)); + * await doAsyncWork(aborter.withTimeout(25 * 1000)); + * ``` + */ +class AbortController { + // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types + constructor(parentSignals) { + this._signal = new AbortSignal(); + if (!parentSignals) { + return; + } + // coerce parentSignals into an array + if (!Array.isArray(parentSignals)) { + // eslint-disable-next-line prefer-rest-params + parentSignals = arguments; + } + for (const parentSignal of parentSignals) { + // if the parent signal has already had abort() called, + // then call abort on this signal as well. + if (parentSignal.aborted) { + this.abort(); + } + else { + // when the parent signal aborts, this signal should as well. + parentSignal.addEventListener("abort", () => { + this.abort(); + }); + } + } + } + /** + * The AbortSignal associated with this controller that will signal aborted + * when the abort method is called on this controller. + * + * @readonly + */ + get signal() { + return this._signal; + } + /** + * Signal that any operations passed this controller's associated abort signal + * to cancel any remaining work and throw an `AbortError`. + */ + abort() { + abortSignal(this._signal); + } + /** + * Creates a new AbortSignal instance that will abort after the provided ms. + * @param ms - Elapsed time in milliseconds to trigger an abort. + */ + static timeout(ms) { + const signal = new AbortSignal(); + const timer = setTimeout(abortSignal, ms, signal); + // Prevent the active Timer from keeping the Node.js event loop active. + if (typeof timer.unref === "function") { + timer.unref(); + } + return signal; + } +} -module.exports = __nccwpck_require__(219); +exports.AbortController = AbortController; +exports.AbortError = AbortError; +exports.AbortSignal = AbortSignal; +//# sourceMappingURL=index.js.map /***/ }), -/***/ 219: +/***/ 4280: /***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { "use strict"; -var net = __nccwpck_require__(808); -var tls = __nccwpck_require__(404); -var http = __nccwpck_require__(685); -var https = __nccwpck_require__(687); -var events = __nccwpck_require__(361); -var assert = __nccwpck_require__(491); -var util = __nccwpck_require__(837); - - -exports.httpOverHttp = httpOverHttp; -exports.httpsOverHttp = httpsOverHttp; -exports.httpOverHttps = httpOverHttps; -exports.httpsOverHttps = httpsOverHttps; +Object.defineProperty(exports, "__esModule", ({ value: true })); +var tslib = __nccwpck_require__(4351); +var coreClient = __nccwpck_require__(9729); +var coreRestPipeline = __nccwpck_require__(8121); +var coreLro = __nccwpck_require__(7094); -function httpOverHttp(options) { - var agent = new TunnelingAgent(options); - agent.request = http.request; - return agent; +function _interopNamespace(e) { + if (e && e.__esModule) return e; + var n = Object.create(null); + if (e) { + Object.keys(e).forEach(function (k) { + if (k !== 'default') { + var d = Object.getOwnPropertyDescriptor(e, k); + Object.defineProperty(n, k, d.get ? d : { + enumerable: true, + get: function () { return e[k]; } + }); + } + }); + } + n["default"] = e; + return Object.freeze(n); } -function httpsOverHttp(options) { - var agent = new TunnelingAgent(options); - agent.request = http.request; - agent.createSocket = createSecureSocket; - agent.defaultPort = 443; - return agent; -} +var coreClient__namespace = /*#__PURE__*/_interopNamespace(coreClient); +var coreRestPipeline__namespace = /*#__PURE__*/_interopNamespace(coreRestPipeline); -function httpOverHttps(options) { - var agent = new TunnelingAgent(options); - agent.request = https.request; - return agent; +/* + * Copyright (c) Microsoft Corporation. + * Licensed under the MIT License. + * + * Code generated by Microsoft (R) AutoRest Code Generator. + * Changes may cause incorrect behavior and will be lost if the code is regenerated. + */ +const pageMap = new WeakMap(); +/** + * Given the last `.value` produced by the `byPage` iterator, + * returns a continuation token that can be used to begin paging from + * that point later. + * @param page An object from accessing `value` on the IteratorResult from a `byPage` iterator. + * @returns The continuation token that can be passed into byPage() during future calls. + */ +function getContinuationToken(page) { + var _a; + if (typeof page !== "object" || page === null) { + return undefined; + } + return (_a = pageMap.get(page)) === null || _a === void 0 ? void 0 : _a.continuationToken; } - -function httpsOverHttps(options) { - var agent = new TunnelingAgent(options); - agent.request = https.request; - agent.createSocket = createSecureSocket; - agent.defaultPort = 443; - return agent; +function setContinuationToken(page, continuationToken) { + var _a; + if (typeof page !== "object" || page === null || !continuationToken) { + return; + } + const pageInfo = (_a = pageMap.get(page)) !== null && _a !== void 0 ? _a : {}; + pageInfo.continuationToken = continuationToken; + pageMap.set(page, pageInfo); } +/* + * Copyright (c) Microsoft Corporation. + * Licensed under the MIT License. + * + * Code generated by Microsoft (R) AutoRest Code Generator. + * Changes may cause incorrect behavior and will be lost if the code is regenerated. + */ +/** Known values of {@link ExpressionEvaluationOptionsScopeType} that the service accepts. */ +exports.KnownExpressionEvaluationOptionsScopeType = void 0; +(function (KnownExpressionEvaluationOptionsScopeType) { + /** NotSpecified */ + KnownExpressionEvaluationOptionsScopeType["NotSpecified"] = "NotSpecified"; + /** Outer */ + KnownExpressionEvaluationOptionsScopeType["Outer"] = "Outer"; + /** Inner */ + KnownExpressionEvaluationOptionsScopeType["Inner"] = "Inner"; +})(exports.KnownExpressionEvaluationOptionsScopeType || (exports.KnownExpressionEvaluationOptionsScopeType = {})); +/** Known values of {@link ProvisioningState} that the service accepts. */ +exports.KnownProvisioningState = void 0; +(function (KnownProvisioningState) { + /** NotSpecified */ + KnownProvisioningState["NotSpecified"] = "NotSpecified"; + /** Accepted */ + KnownProvisioningState["Accepted"] = "Accepted"; + /** Running */ + KnownProvisioningState["Running"] = "Running"; + /** Ready */ + KnownProvisioningState["Ready"] = "Ready"; + /** Creating */ + KnownProvisioningState["Creating"] = "Creating"; + /** Created */ + KnownProvisioningState["Created"] = "Created"; + /** Deleting */ + KnownProvisioningState["Deleting"] = "Deleting"; + /** Deleted */ + KnownProvisioningState["Deleted"] = "Deleted"; + /** Canceled */ + KnownProvisioningState["Canceled"] = "Canceled"; + /** Failed */ + KnownProvisioningState["Failed"] = "Failed"; + /** Succeeded */ + KnownProvisioningState["Succeeded"] = "Succeeded"; + /** Updating */ + KnownProvisioningState["Updating"] = "Updating"; +})(exports.KnownProvisioningState || (exports.KnownProvisioningState = {})); +/** Known values of {@link AliasPathTokenType} that the service accepts. */ +exports.KnownAliasPathTokenType = void 0; +(function (KnownAliasPathTokenType) { + /** The token type is not specified. */ + KnownAliasPathTokenType["NotSpecified"] = "NotSpecified"; + /** The token type can be anything. */ + KnownAliasPathTokenType["Any"] = "Any"; + /** The token type is string. */ + KnownAliasPathTokenType["String"] = "String"; + /** The token type is object. */ + KnownAliasPathTokenType["Object"] = "Object"; + /** The token type is array. */ + KnownAliasPathTokenType["Array"] = "Array"; + /** The token type is integer. */ + KnownAliasPathTokenType["Integer"] = "Integer"; + /** The token type is number. */ + KnownAliasPathTokenType["Number"] = "Number"; + /** The token type is boolean. */ + KnownAliasPathTokenType["Boolean"] = "Boolean"; +})(exports.KnownAliasPathTokenType || (exports.KnownAliasPathTokenType = {})); +/** Known values of {@link AliasPathAttributes} that the service accepts. */ +exports.KnownAliasPathAttributes = void 0; +(function (KnownAliasPathAttributes) { + /** The token that the alias path is referring to has no attributes. */ + KnownAliasPathAttributes["None"] = "None"; + /** The token that the alias path is referring to is modifiable by policies with 'modify' effect. */ + KnownAliasPathAttributes["Modifiable"] = "Modifiable"; +})(exports.KnownAliasPathAttributes || (exports.KnownAliasPathAttributes = {})); +/** Known values of {@link ProviderAuthorizationConsentState} that the service accepts. */ +exports.KnownProviderAuthorizationConsentState = void 0; +(function (KnownProviderAuthorizationConsentState) { + /** NotSpecified */ + KnownProviderAuthorizationConsentState["NotSpecified"] = "NotSpecified"; + /** Required */ + KnownProviderAuthorizationConsentState["Required"] = "Required"; + /** NotRequired */ + KnownProviderAuthorizationConsentState["NotRequired"] = "NotRequired"; + /** Consented */ + KnownProviderAuthorizationConsentState["Consented"] = "Consented"; +})(exports.KnownProviderAuthorizationConsentState || (exports.KnownProviderAuthorizationConsentState = {})); +/** Known values of {@link ExtendedLocationType} that the service accepts. */ +exports.KnownExtendedLocationType = void 0; +(function (KnownExtendedLocationType) { + /** EdgeZone */ + KnownExtendedLocationType["EdgeZone"] = "EdgeZone"; +})(exports.KnownExtendedLocationType || (exports.KnownExtendedLocationType = {})); +/** Known values of {@link TagsPatchOperation} that the service accepts. */ +exports.KnownTagsPatchOperation = void 0; +(function (KnownTagsPatchOperation) { + /** The 'replace' option replaces the entire set of existing tags with a new set. */ + KnownTagsPatchOperation["Replace"] = "Replace"; + /** The 'merge' option allows adding tags with new names and updating the values of tags with existing names. */ + KnownTagsPatchOperation["Merge"] = "Merge"; + /** The 'delete' option allows selectively deleting tags based on given names or name\/value pairs. */ + KnownTagsPatchOperation["Delete"] = "Delete"; +})(exports.KnownTagsPatchOperation || (exports.KnownTagsPatchOperation = {})); -function TunnelingAgent(options) { - var self = this; - self.options = options || {}; - self.proxyOptions = self.options.proxy || {}; - self.maxSockets = self.options.maxSockets || http.Agent.defaultMaxSockets; - self.requests = []; - self.sockets = []; - - self.on('free', function onFree(socket, host, port, localAddress) { - var options = toOptions(host, port, localAddress); - for (var i = 0, len = self.requests.length; i < len; ++i) { +/* + * Copyright (c) Microsoft Corporation. + * Licensed under the MIT License. + * + * Code generated by Microsoft (R) AutoRest Code Generator. + * Changes may cause incorrect behavior and will be lost if the code is regenerated. + */ +const OperationListResult = { + type: { + name: "Composite", + className: "OperationListResult", + modelProperties: { + value: { + serializedName: "value", + type: { + name: "Sequence", + element: { + type: { + name: "Composite", + className: "Operation" + } + } + } + }, + nextLink: { + serializedName: "nextLink", + type: { + name: "String" + } + } + } + } +}; +const Operation = { + type: { + name: "Composite", + className: "Operation", + modelProperties: { + name: { + serializedName: "name", + type: { + name: "String" + } + }, + display: { + serializedName: "display", + type: { + name: "Composite", + className: "OperationDisplay" + } + } + } + } +}; +const OperationDisplay = { + type: { + name: "Composite", + className: "OperationDisplay", + modelProperties: { + provider: { + serializedName: "provider", + type: { + name: "String" + } + }, + resource: { + serializedName: "resource", + type: { + name: "String" + } + }, + operation: { + serializedName: "operation", + type: { + name: "String" + } + }, + description: { + serializedName: "description", + type: { + name: "String" + } + } + } + } +}; +const CloudError = { + type: { + name: "Composite", + className: "CloudError", + modelProperties: { + error: { + serializedName: "error", + type: { + name: "Composite", + className: "ErrorResponse" + } + } + } + } +}; +const ErrorResponse = { + type: { + name: "Composite", + className: "ErrorResponse", + modelProperties: { + code: { + serializedName: "code", + readOnly: true, + type: { + name: "String" + } + }, + message: { + serializedName: "message", + readOnly: true, + type: { + name: "String" + } + }, + target: { + serializedName: "target", + readOnly: true, + type: { + name: "String" + } + }, + details: { + serializedName: "details", + readOnly: true, + type: { + name: "Sequence", + element: { + type: { + name: "Composite", + className: "ErrorResponse" + } + } + } + }, + additionalInfo: { + serializedName: "additionalInfo", + readOnly: true, + type: { + name: "Sequence", + element: { + type: { + name: "Composite", + className: "ErrorAdditionalInfo" + } + } + } + } + } + } +}; +const ErrorAdditionalInfo = { + type: { + name: "Composite", + className: "ErrorAdditionalInfo", + modelProperties: { + type: { + serializedName: "type", + readOnly: true, + type: { + name: "String" + } + }, + info: { + serializedName: "info", + readOnly: true, + type: { + name: "Dictionary", + value: { type: { name: "any" } } + } + } + } + } +}; +const Deployment = { + type: { + name: "Composite", + className: "Deployment", + modelProperties: { + location: { + serializedName: "location", + type: { + name: "String" + } + }, + properties: { + serializedName: "properties", + type: { + name: "Composite", + className: "DeploymentProperties" + } + }, + tags: { + serializedName: "tags", + type: { + name: "Dictionary", + value: { type: { name: "String" } } + } + } + } + } +}; +const DeploymentProperties = { + type: { + name: "Composite", + className: "DeploymentProperties", + modelProperties: { + template: { + serializedName: "template", + type: { + name: "Dictionary", + value: { type: { name: "any" } } + } + }, + templateLink: { + serializedName: "templateLink", + type: { + name: "Composite", + className: "TemplateLink" + } + }, + parameters: { + serializedName: "parameters", + type: { + name: "Dictionary", + value: { type: { name: "any" } } + } + }, + parametersLink: { + serializedName: "parametersLink", + type: { + name: "Composite", + className: "ParametersLink" + } + }, + mode: { + serializedName: "mode", + required: true, + type: { + name: "Enum", + allowedValues: ["Incremental", "Complete"] + } + }, + debugSetting: { + serializedName: "debugSetting", + type: { + name: "Composite", + className: "DebugSetting" + } + }, + onErrorDeployment: { + serializedName: "onErrorDeployment", + type: { + name: "Composite", + className: "OnErrorDeployment" + } + }, + expressionEvaluationOptions: { + serializedName: "expressionEvaluationOptions", + type: { + name: "Composite", + className: "ExpressionEvaluationOptions" + } + } + } + } +}; +const TemplateLink = { + type: { + name: "Composite", + className: "TemplateLink", + modelProperties: { + uri: { + serializedName: "uri", + type: { + name: "String" + } + }, + id: { + serializedName: "id", + type: { + name: "String" + } + }, + relativePath: { + serializedName: "relativePath", + type: { + name: "String" + } + }, + contentVersion: { + serializedName: "contentVersion", + type: { + name: "String" + } + }, + queryString: { + serializedName: "queryString", + type: { + name: "String" + } + } + } + } +}; +const ParametersLink = { + type: { + name: "Composite", + className: "ParametersLink", + modelProperties: { + uri: { + serializedName: "uri", + required: true, + type: { + name: "String" + } + }, + contentVersion: { + serializedName: "contentVersion", + type: { + name: "String" + } + } + } + } +}; +const DebugSetting = { + type: { + name: "Composite", + className: "DebugSetting", + modelProperties: { + detailLevel: { + serializedName: "detailLevel", + type: { + name: "String" + } + } + } + } +}; +const OnErrorDeployment = { + type: { + name: "Composite", + className: "OnErrorDeployment", + modelProperties: { + type: { + serializedName: "type", + type: { + name: "Enum", + allowedValues: ["LastSuccessful", "SpecificDeployment"] + } + }, + deploymentName: { + serializedName: "deploymentName", + type: { + name: "String" + } + } + } + } +}; +const ExpressionEvaluationOptions = { + type: { + name: "Composite", + className: "ExpressionEvaluationOptions", + modelProperties: { + scope: { + serializedName: "scope", + type: { + name: "String" + } + } + } + } +}; +const DeploymentExtended = { + type: { + name: "Composite", + className: "DeploymentExtended", + modelProperties: { + id: { + serializedName: "id", + readOnly: true, + type: { + name: "String" + } + }, + name: { + serializedName: "name", + readOnly: true, + type: { + name: "String" + } + }, + type: { + serializedName: "type", + readOnly: true, + type: { + name: "String" + } + }, + location: { + serializedName: "location", + type: { + name: "String" + } + }, + properties: { + serializedName: "properties", + type: { + name: "Composite", + className: "DeploymentPropertiesExtended" + } + }, + tags: { + serializedName: "tags", + type: { + name: "Dictionary", + value: { type: { name: "String" } } + } + } + } + } +}; +const DeploymentPropertiesExtended = { + type: { + name: "Composite", + className: "DeploymentPropertiesExtended", + modelProperties: { + provisioningState: { + serializedName: "provisioningState", + readOnly: true, + type: { + name: "String" + } + }, + correlationId: { + serializedName: "correlationId", + readOnly: true, + type: { + name: "String" + } + }, + timestamp: { + serializedName: "timestamp", + readOnly: true, + type: { + name: "DateTime" + } + }, + duration: { + serializedName: "duration", + readOnly: true, + type: { + name: "String" + } + }, + outputs: { + serializedName: "outputs", + readOnly: true, + type: { + name: "Dictionary", + value: { type: { name: "any" } } + } + }, + providers: { + serializedName: "providers", + readOnly: true, + type: { + name: "Sequence", + element: { + type: { + name: "Composite", + className: "Provider" + } + } + } + }, + dependencies: { + serializedName: "dependencies", + readOnly: true, + type: { + name: "Sequence", + element: { + type: { + name: "Composite", + className: "Dependency" + } + } + } + }, + templateLink: { + serializedName: "templateLink", + type: { + name: "Composite", + className: "TemplateLink" + } + }, + parameters: { + serializedName: "parameters", + readOnly: true, + type: { + name: "Dictionary", + value: { type: { name: "any" } } + } + }, + parametersLink: { + serializedName: "parametersLink", + type: { + name: "Composite", + className: "ParametersLink" + } + }, + mode: { + serializedName: "mode", + readOnly: true, + type: { + name: "Enum", + allowedValues: ["Incremental", "Complete"] + } + }, + debugSetting: { + serializedName: "debugSetting", + type: { + name: "Composite", + className: "DebugSetting" + } + }, + onErrorDeployment: { + serializedName: "onErrorDeployment", + type: { + name: "Composite", + className: "OnErrorDeploymentExtended" + } + }, + templateHash: { + serializedName: "templateHash", + readOnly: true, + type: { + name: "String" + } + }, + outputResources: { + serializedName: "outputResources", + readOnly: true, + type: { + name: "Sequence", + element: { + type: { + name: "Composite", + className: "ResourceReference" + } + } + } + }, + validatedResources: { + serializedName: "validatedResources", + readOnly: true, + type: { + name: "Sequence", + element: { + type: { + name: "Composite", + className: "ResourceReference" + } + } + } + }, + error: { + serializedName: "error", + type: { + name: "Composite", + className: "ErrorResponse" + } + } + } + } +}; +const Provider = { + type: { + name: "Composite", + className: "Provider", + modelProperties: { + id: { + serializedName: "id", + readOnly: true, + type: { + name: "String" + } + }, + namespace: { + serializedName: "namespace", + type: { + name: "String" + } + }, + registrationState: { + serializedName: "registrationState", + readOnly: true, + type: { + name: "String" + } + }, + registrationPolicy: { + serializedName: "registrationPolicy", + readOnly: true, + type: { + name: "String" + } + }, + resourceTypes: { + serializedName: "resourceTypes", + readOnly: true, + type: { + name: "Sequence", + element: { + type: { + name: "Composite", + className: "ProviderResourceType" + } + } + } + }, + providerAuthorizationConsentState: { + serializedName: "providerAuthorizationConsentState", + type: { + name: "String" + } + } + } + } +}; +const ProviderResourceType = { + type: { + name: "Composite", + className: "ProviderResourceType", + modelProperties: { + resourceType: { + serializedName: "resourceType", + type: { + name: "String" + } + }, + locations: { + serializedName: "locations", + type: { + name: "Sequence", + element: { + type: { + name: "String" + } + } + } + }, + locationMappings: { + serializedName: "locationMappings", + type: { + name: "Sequence", + element: { + type: { + name: "Composite", + className: "ProviderExtendedLocation" + } + } + } + }, + aliases: { + serializedName: "aliases", + type: { + name: "Sequence", + element: { + type: { + name: "Composite", + className: "Alias" + } + } + } + }, + apiVersions: { + serializedName: "apiVersions", + type: { + name: "Sequence", + element: { + type: { + name: "String" + } + } + } + }, + defaultApiVersion: { + serializedName: "defaultApiVersion", + readOnly: true, + type: { + name: "String" + } + }, + zoneMappings: { + serializedName: "zoneMappings", + type: { + name: "Sequence", + element: { + type: { + name: "Composite", + className: "ZoneMapping" + } + } + } + }, + apiProfiles: { + serializedName: "apiProfiles", + readOnly: true, + type: { + name: "Sequence", + element: { + type: { + name: "Composite", + className: "ApiProfile" + } + } + } + }, + capabilities: { + serializedName: "capabilities", + type: { + name: "String" + } + }, + properties: { + serializedName: "properties", + type: { + name: "Dictionary", + value: { type: { name: "String" } } + } + } + } + } +}; +const ProviderExtendedLocation = { + type: { + name: "Composite", + className: "ProviderExtendedLocation", + modelProperties: { + location: { + serializedName: "location", + type: { + name: "String" + } + }, + type: { + serializedName: "type", + type: { + name: "String" + } + }, + extendedLocations: { + serializedName: "extendedLocations", + type: { + name: "Sequence", + element: { + type: { + name: "String" + } + } + } + } + } + } +}; +const Alias = { + type: { + name: "Composite", + className: "Alias", + modelProperties: { + name: { + serializedName: "name", + type: { + name: "String" + } + }, + paths: { + serializedName: "paths", + type: { + name: "Sequence", + element: { + type: { + name: "Composite", + className: "AliasPath" + } + } + } + }, + type: { + serializedName: "type", + type: { + name: "Enum", + allowedValues: ["NotSpecified", "PlainText", "Mask"] + } + }, + defaultPath: { + serializedName: "defaultPath", + type: { + name: "String" + } + }, + defaultPattern: { + serializedName: "defaultPattern", + type: { + name: "Composite", + className: "AliasPattern" + } + }, + defaultMetadata: { + serializedName: "defaultMetadata", + type: { + name: "Composite", + className: "AliasPathMetadata" + } + } + } + } +}; +const AliasPath = { + type: { + name: "Composite", + className: "AliasPath", + modelProperties: { + path: { + serializedName: "path", + type: { + name: "String" + } + }, + apiVersions: { + serializedName: "apiVersions", + type: { + name: "Sequence", + element: { + type: { + name: "String" + } + } + } + }, + pattern: { + serializedName: "pattern", + type: { + name: "Composite", + className: "AliasPattern" + } + }, + metadata: { + serializedName: "metadata", + type: { + name: "Composite", + className: "AliasPathMetadata" + } + } + } + } +}; +const AliasPattern = { + type: { + name: "Composite", + className: "AliasPattern", + modelProperties: { + phrase: { + serializedName: "phrase", + type: { + name: "String" + } + }, + variable: { + serializedName: "variable", + type: { + name: "String" + } + }, + type: { + serializedName: "type", + type: { + name: "Enum", + allowedValues: ["NotSpecified", "Extract"] + } + } + } + } +}; +const AliasPathMetadata = { + type: { + name: "Composite", + className: "AliasPathMetadata", + modelProperties: { + type: { + serializedName: "type", + readOnly: true, + type: { + name: "String" + } + }, + attributes: { + serializedName: "attributes", + readOnly: true, + type: { + name: "String" + } + } + } + } +}; +const ZoneMapping = { + type: { + name: "Composite", + className: "ZoneMapping", + modelProperties: { + location: { + serializedName: "location", + type: { + name: "String" + } + }, + zones: { + serializedName: "zones", + type: { + name: "Sequence", + element: { + type: { + name: "String" + } + } + } + } + } + } +}; +const ApiProfile = { + type: { + name: "Composite", + className: "ApiProfile", + modelProperties: { + profileVersion: { + serializedName: "profileVersion", + readOnly: true, + type: { + name: "String" + } + }, + apiVersion: { + serializedName: "apiVersion", + readOnly: true, + type: { + name: "String" + } + } + } + } +}; +const Dependency = { + type: { + name: "Composite", + className: "Dependency", + modelProperties: { + dependsOn: { + serializedName: "dependsOn", + type: { + name: "Sequence", + element: { + type: { + name: "Composite", + className: "BasicDependency" + } + } + } + }, + id: { + serializedName: "id", + type: { + name: "String" + } + }, + resourceType: { + serializedName: "resourceType", + type: { + name: "String" + } + }, + resourceName: { + serializedName: "resourceName", + type: { + name: "String" + } + } + } + } +}; +const BasicDependency = { + type: { + name: "Composite", + className: "BasicDependency", + modelProperties: { + id: { + serializedName: "id", + type: { + name: "String" + } + }, + resourceType: { + serializedName: "resourceType", + type: { + name: "String" + } + }, + resourceName: { + serializedName: "resourceName", + type: { + name: "String" + } + } + } + } +}; +const OnErrorDeploymentExtended = { + type: { + name: "Composite", + className: "OnErrorDeploymentExtended", + modelProperties: { + provisioningState: { + serializedName: "provisioningState", + readOnly: true, + type: { + name: "String" + } + }, + type: { + serializedName: "type", + type: { + name: "Enum", + allowedValues: ["LastSuccessful", "SpecificDeployment"] + } + }, + deploymentName: { + serializedName: "deploymentName", + type: { + name: "String" + } + } + } + } +}; +const ResourceReference = { + type: { + name: "Composite", + className: "ResourceReference", + modelProperties: { + id: { + serializedName: "id", + readOnly: true, + type: { + name: "String" + } + } + } + } +}; +const DeploymentValidateResult = { + type: { + name: "Composite", + className: "DeploymentValidateResult", + modelProperties: { + error: { + serializedName: "error", + type: { + name: "Composite", + className: "ErrorResponse" + } + }, + properties: { + serializedName: "properties", + type: { + name: "Composite", + className: "DeploymentPropertiesExtended" + } + } + } + } +}; +const DeploymentExportResult = { + type: { + name: "Composite", + className: "DeploymentExportResult", + modelProperties: { + template: { + serializedName: "template", + type: { + name: "Dictionary", + value: { type: { name: "any" } } + } + } + } + } +}; +const DeploymentListResult = { + type: { + name: "Composite", + className: "DeploymentListResult", + modelProperties: { + value: { + serializedName: "value", + type: { + name: "Sequence", + element: { + type: { + name: "Composite", + className: "DeploymentExtended" + } + } + } + }, + nextLink: { + serializedName: "nextLink", + readOnly: true, + type: { + name: "String" + } + } + } + } +}; +const ScopedDeployment = { + type: { + name: "Composite", + className: "ScopedDeployment", + modelProperties: { + location: { + serializedName: "location", + required: true, + type: { + name: "String" + } + }, + properties: { + serializedName: "properties", + type: { + name: "Composite", + className: "DeploymentProperties" + } + }, + tags: { + serializedName: "tags", + type: { + name: "Dictionary", + value: { type: { name: "String" } } + } + } + } + } +}; +const ScopedDeploymentWhatIf = { + type: { + name: "Composite", + className: "ScopedDeploymentWhatIf", + modelProperties: { + location: { + serializedName: "location", + required: true, + type: { + name: "String" + } + }, + properties: { + serializedName: "properties", + type: { + name: "Composite", + className: "DeploymentWhatIfProperties" + } + } + } + } +}; +const DeploymentWhatIfSettings = { + type: { + name: "Composite", + className: "DeploymentWhatIfSettings", + modelProperties: { + resultFormat: { + serializedName: "resultFormat", + type: { + name: "Enum", + allowedValues: ["ResourceIdOnly", "FullResourcePayloads"] + } + } + } + } +}; +const WhatIfOperationResult = { + type: { + name: "Composite", + className: "WhatIfOperationResult", + modelProperties: { + status: { + serializedName: "status", + type: { + name: "String" + } + }, + error: { + serializedName: "error", + type: { + name: "Composite", + className: "ErrorResponse" + } + }, + changes: { + serializedName: "properties.changes", + type: { + name: "Sequence", + element: { + type: { + name: "Composite", + className: "WhatIfChange" + } + } + } + } + } + } +}; +const WhatIfChange = { + type: { + name: "Composite", + className: "WhatIfChange", + modelProperties: { + resourceId: { + serializedName: "resourceId", + required: true, + type: { + name: "String" + } + }, + changeType: { + serializedName: "changeType", + required: true, + type: { + name: "Enum", + allowedValues: [ + "Create", + "Delete", + "Ignore", + "Deploy", + "NoChange", + "Modify", + "Unsupported" + ] + } + }, + unsupportedReason: { + serializedName: "unsupportedReason", + type: { + name: "String" + } + }, + before: { + serializedName: "before", + type: { + name: "Dictionary", + value: { type: { name: "any" } } + } + }, + after: { + serializedName: "after", + type: { + name: "Dictionary", + value: { type: { name: "any" } } + } + }, + delta: { + serializedName: "delta", + type: { + name: "Sequence", + element: { + type: { + name: "Composite", + className: "WhatIfPropertyChange" + } + } + } + } + } + } +}; +const WhatIfPropertyChange = { + type: { + name: "Composite", + className: "WhatIfPropertyChange", + modelProperties: { + path: { + serializedName: "path", + required: true, + type: { + name: "String" + } + }, + propertyChangeType: { + serializedName: "propertyChangeType", + required: true, + type: { + name: "Enum", + allowedValues: ["Create", "Delete", "Modify", "Array", "NoEffect"] + } + }, + before: { + serializedName: "before", + type: { + name: "Dictionary", + value: { type: { name: "any" } } + } + }, + after: { + serializedName: "after", + type: { + name: "Dictionary", + value: { type: { name: "any" } } + } + }, + children: { + serializedName: "children", + type: { + name: "Sequence", + element: { + type: { + name: "Composite", + className: "WhatIfPropertyChange" + } + } + } + } + } + } +}; +const DeploymentWhatIf = { + type: { + name: "Composite", + className: "DeploymentWhatIf", + modelProperties: { + location: { + serializedName: "location", + type: { + name: "String" + } + }, + properties: { + serializedName: "properties", + type: { + name: "Composite", + className: "DeploymentWhatIfProperties" + } + } + } + } +}; +const ProviderPermissionListResult = { + type: { + name: "Composite", + className: "ProviderPermissionListResult", + modelProperties: { + value: { + serializedName: "value", + type: { + name: "Sequence", + element: { + type: { + name: "Composite", + className: "ProviderPermission" + } + } + } + }, + nextLink: { + serializedName: "nextLink", + readOnly: true, + type: { + name: "String" + } + } + } + } +}; +const ProviderPermission = { + type: { + name: "Composite", + className: "ProviderPermission", + modelProperties: { + applicationId: { + serializedName: "applicationId", + type: { + name: "String" + } + }, + roleDefinition: { + serializedName: "roleDefinition", + type: { + name: "Composite", + className: "RoleDefinition" + } + }, + managedByRoleDefinition: { + serializedName: "managedByRoleDefinition", + type: { + name: "Composite", + className: "RoleDefinition" + } + }, + providerAuthorizationConsentState: { + serializedName: "providerAuthorizationConsentState", + type: { + name: "String" + } + } + } + } +}; +const RoleDefinition = { + type: { + name: "Composite", + className: "RoleDefinition", + modelProperties: { + id: { + serializedName: "id", + type: { + name: "String" + } + }, + name: { + serializedName: "name", + type: { + name: "String" + } + }, + isServiceRole: { + serializedName: "isServiceRole", + type: { + name: "Boolean" + } + }, + permissions: { + serializedName: "permissions", + type: { + name: "Sequence", + element: { + type: { + name: "Composite", + className: "Permission" + } + } + } + }, + scopes: { + serializedName: "scopes", + type: { + name: "Sequence", + element: { + type: { + name: "String" + } + } + } + } + } + } +}; +const Permission = { + type: { + name: "Composite", + className: "Permission", + modelProperties: { + actions: { + serializedName: "actions", + type: { + name: "Sequence", + element: { + type: { + name: "String" + } + } + } + }, + notActions: { + serializedName: "notActions", + type: { + name: "Sequence", + element: { + type: { + name: "String" + } + } + } + }, + dataActions: { + serializedName: "dataActions", + type: { + name: "Sequence", + element: { + type: { + name: "String" + } + } + } + }, + notDataActions: { + serializedName: "notDataActions", + type: { + name: "Sequence", + element: { + type: { + name: "String" + } + } + } + } + } + } +}; +const ProviderRegistrationRequest = { + type: { + name: "Composite", + className: "ProviderRegistrationRequest", + modelProperties: { + thirdPartyProviderConsent: { + serializedName: "thirdPartyProviderConsent", + type: { + name: "Composite", + className: "ProviderConsentDefinition" + } + } + } + } +}; +const ProviderConsentDefinition = { + type: { + name: "Composite", + className: "ProviderConsentDefinition", + modelProperties: { + consentToAuthorization: { + serializedName: "consentToAuthorization", + type: { + name: "Boolean" + } + } + } + } +}; +const ProviderListResult = { + type: { + name: "Composite", + className: "ProviderListResult", + modelProperties: { + value: { + serializedName: "value", + type: { + name: "Sequence", + element: { + type: { + name: "Composite", + className: "Provider" + } + } + } + }, + nextLink: { + serializedName: "nextLink", + readOnly: true, + type: { + name: "String" + } + } + } + } +}; +const ProviderResourceTypeListResult = { + type: { + name: "Composite", + className: "ProviderResourceTypeListResult", + modelProperties: { + value: { + serializedName: "value", + type: { + name: "Sequence", + element: { + type: { + name: "Composite", + className: "ProviderResourceType" + } + } + } + }, + nextLink: { + serializedName: "nextLink", + readOnly: true, + type: { + name: "String" + } + } + } + } +}; +const ResourceListResult = { + type: { + name: "Composite", + className: "ResourceListResult", + modelProperties: { + value: { + serializedName: "value", + type: { + name: "Sequence", + element: { + type: { + name: "Composite", + className: "GenericResourceExpanded" + } + } + } + }, + nextLink: { + serializedName: "nextLink", + readOnly: true, + type: { + name: "String" + } + } + } + } +}; +const Plan = { + type: { + name: "Composite", + className: "Plan", + modelProperties: { + name: { + serializedName: "name", + type: { + name: "String" + } + }, + publisher: { + serializedName: "publisher", + type: { + name: "String" + } + }, + product: { + serializedName: "product", + type: { + name: "String" + } + }, + promotionCode: { + serializedName: "promotionCode", + type: { + name: "String" + } + }, + version: { + serializedName: "version", + type: { + name: "String" + } + } + } + } +}; +const Sku = { + type: { + name: "Composite", + className: "Sku", + modelProperties: { + name: { + serializedName: "name", + type: { + name: "String" + } + }, + tier: { + serializedName: "tier", + type: { + name: "String" + } + }, + size: { + serializedName: "size", + type: { + name: "String" + } + }, + family: { + serializedName: "family", + type: { + name: "String" + } + }, + model: { + serializedName: "model", + type: { + name: "String" + } + }, + capacity: { + serializedName: "capacity", + type: { + name: "Number" + } + } + } + } +}; +const Identity = { + type: { + name: "Composite", + className: "Identity", + modelProperties: { + principalId: { + serializedName: "principalId", + readOnly: true, + type: { + name: "String" + } + }, + tenantId: { + serializedName: "tenantId", + readOnly: true, + type: { + name: "String" + } + }, + type: { + serializedName: "type", + type: { + name: "Enum", + allowedValues: [ + "SystemAssigned", + "UserAssigned", + "SystemAssigned, UserAssigned", + "None" + ] + } + }, + userAssignedIdentities: { + serializedName: "userAssignedIdentities", + type: { + name: "Dictionary", + value: { + type: { + name: "Composite", + className: "IdentityUserAssignedIdentitiesValue" + } + } + } + } + } + } +}; +const IdentityUserAssignedIdentitiesValue = { + type: { + name: "Composite", + className: "IdentityUserAssignedIdentitiesValue", + modelProperties: { + principalId: { + serializedName: "principalId", + readOnly: true, + type: { + name: "String" + } + }, + clientId: { + serializedName: "clientId", + readOnly: true, + type: { + name: "String" + } + } + } + } +}; +const Resource = { + type: { + name: "Composite", + className: "Resource", + modelProperties: { + id: { + serializedName: "id", + readOnly: true, + type: { + name: "String" + } + }, + name: { + serializedName: "name", + readOnly: true, + type: { + name: "String" + } + }, + type: { + serializedName: "type", + readOnly: true, + type: { + name: "String" + } + }, + location: { + serializedName: "location", + type: { + name: "String" + } + }, + extendedLocation: { + serializedName: "extendedLocation", + type: { + name: "Composite", + className: "ExtendedLocation" + } + }, + tags: { + serializedName: "tags", + type: { + name: "Dictionary", + value: { type: { name: "String" } } + } + } + } + } +}; +const ExtendedLocation = { + type: { + name: "Composite", + className: "ExtendedLocation", + modelProperties: { + type: { + serializedName: "type", + type: { + name: "String" + } + }, + name: { + serializedName: "name", + type: { + name: "String" + } + } + } + } +}; +const ResourceGroup = { + type: { + name: "Composite", + className: "ResourceGroup", + modelProperties: { + id: { + serializedName: "id", + readOnly: true, + type: { + name: "String" + } + }, + name: { + serializedName: "name", + readOnly: true, + type: { + name: "String" + } + }, + type: { + serializedName: "type", + readOnly: true, + type: { + name: "String" + } + }, + properties: { + serializedName: "properties", + type: { + name: "Composite", + className: "ResourceGroupProperties" + } + }, + location: { + serializedName: "location", + required: true, + type: { + name: "String" + } + }, + managedBy: { + serializedName: "managedBy", + type: { + name: "String" + } + }, + tags: { + serializedName: "tags", + type: { + name: "Dictionary", + value: { type: { name: "String" } } + } + } + } + } +}; +const ResourceGroupProperties = { + type: { + name: "Composite", + className: "ResourceGroupProperties", + modelProperties: { + provisioningState: { + serializedName: "provisioningState", + readOnly: true, + type: { + name: "String" + } + } + } + } +}; +const ResourceGroupPatchable = { + type: { + name: "Composite", + className: "ResourceGroupPatchable", + modelProperties: { + name: { + serializedName: "name", + type: { + name: "String" + } + }, + properties: { + serializedName: "properties", + type: { + name: "Composite", + className: "ResourceGroupProperties" + } + }, + managedBy: { + serializedName: "managedBy", + type: { + name: "String" + } + }, + tags: { + serializedName: "tags", + type: { + name: "Dictionary", + value: { type: { name: "String" } } + } + } + } + } +}; +const ExportTemplateRequest = { + type: { + name: "Composite", + className: "ExportTemplateRequest", + modelProperties: { + resources: { + serializedName: "resources", + type: { + name: "Sequence", + element: { + type: { + name: "String" + } + } + } + }, + options: { + serializedName: "options", + type: { + name: "String" + } + } + } + } +}; +const ResourceGroupExportResult = { + type: { + name: "Composite", + className: "ResourceGroupExportResult", + modelProperties: { + template: { + serializedName: "template", + type: { + name: "Dictionary", + value: { type: { name: "any" } } + } + }, + error: { + serializedName: "error", + type: { + name: "Composite", + className: "ErrorResponse" + } + } + } + } +}; +const ResourceGroupListResult = { + type: { + name: "Composite", + className: "ResourceGroupListResult", + modelProperties: { + value: { + serializedName: "value", + type: { + name: "Sequence", + element: { + type: { + name: "Composite", + className: "ResourceGroup" + } + } + } + }, + nextLink: { + serializedName: "nextLink", + readOnly: true, + type: { + name: "String" + } + } + } + } +}; +const ResourcesMoveInfo = { + type: { + name: "Composite", + className: "ResourcesMoveInfo", + modelProperties: { + resources: { + serializedName: "resources", + type: { + name: "Sequence", + element: { + type: { + name: "String" + } + } + } + }, + targetResourceGroup: { + serializedName: "targetResourceGroup", + type: { + name: "String" + } + } + } + } +}; +const TagValue = { + type: { + name: "Composite", + className: "TagValue", + modelProperties: { + id: { + serializedName: "id", + readOnly: true, + type: { + name: "String" + } + }, + tagValue: { + serializedName: "tagValue", + type: { + name: "String" + } + }, + count: { + serializedName: "count", + type: { + name: "Composite", + className: "TagCount" + } + } + } + } +}; +const TagCount = { + type: { + name: "Composite", + className: "TagCount", + modelProperties: { + type: { + serializedName: "type", + type: { + name: "String" + } + }, + value: { + serializedName: "value", + type: { + name: "Number" + } + } + } + } +}; +const TagDetails = { + type: { + name: "Composite", + className: "TagDetails", + modelProperties: { + id: { + serializedName: "id", + readOnly: true, + type: { + name: "String" + } + }, + tagName: { + serializedName: "tagName", + type: { + name: "String" + } + }, + count: { + serializedName: "count", + type: { + name: "Composite", + className: "TagCount" + } + }, + values: { + serializedName: "values", + type: { + name: "Sequence", + element: { + type: { + name: "Composite", + className: "TagValue" + } + } + } + } + } + } +}; +const TagsListResult = { + type: { + name: "Composite", + className: "TagsListResult", + modelProperties: { + value: { + serializedName: "value", + type: { + name: "Sequence", + element: { + type: { + name: "Composite", + className: "TagDetails" + } + } + } + }, + nextLink: { + serializedName: "nextLink", + readOnly: true, + type: { + name: "String" + } + } + } + } +}; +const DeploymentOperation = { + type: { + name: "Composite", + className: "DeploymentOperation", + modelProperties: { + id: { + serializedName: "id", + readOnly: true, + type: { + name: "String" + } + }, + operationId: { + serializedName: "operationId", + readOnly: true, + type: { + name: "String" + } + }, + properties: { + serializedName: "properties", + type: { + name: "Composite", + className: "DeploymentOperationProperties" + } + } + } + } +}; +const DeploymentOperationProperties = { + type: { + name: "Composite", + className: "DeploymentOperationProperties", + modelProperties: { + provisioningOperation: { + serializedName: "provisioningOperation", + readOnly: true, + type: { + name: "Enum", + allowedValues: [ + "NotSpecified", + "Create", + "Delete", + "Waiting", + "AzureAsyncOperationWaiting", + "ResourceCacheWaiting", + "Action", + "Read", + "EvaluateDeploymentOutput", + "DeploymentCleanup" + ] + } + }, + provisioningState: { + serializedName: "provisioningState", + readOnly: true, + type: { + name: "String" + } + }, + timestamp: { + serializedName: "timestamp", + readOnly: true, + type: { + name: "DateTime" + } + }, + duration: { + serializedName: "duration", + readOnly: true, + type: { + name: "String" + } + }, + serviceRequestId: { + serializedName: "serviceRequestId", + readOnly: true, + type: { + name: "String" + } + }, + statusCode: { + serializedName: "statusCode", + readOnly: true, + type: { + name: "String" + } + }, + statusMessage: { + serializedName: "statusMessage", + type: { + name: "Composite", + className: "StatusMessage" + } + }, + targetResource: { + serializedName: "targetResource", + type: { + name: "Composite", + className: "TargetResource" + } + }, + request: { + serializedName: "request", + type: { + name: "Composite", + className: "HttpMessage" + } + }, + response: { + serializedName: "response", + type: { + name: "Composite", + className: "HttpMessage" + } + } + } + } +}; +const StatusMessage = { + type: { + name: "Composite", + className: "StatusMessage", + modelProperties: { + status: { + serializedName: "status", + type: { + name: "String" + } + }, + error: { + serializedName: "error", + type: { + name: "Composite", + className: "ErrorResponse" + } + } + } + } +}; +const TargetResource = { + type: { + name: "Composite", + className: "TargetResource", + modelProperties: { + id: { + serializedName: "id", + type: { + name: "String" + } + }, + resourceName: { + serializedName: "resourceName", + type: { + name: "String" + } + }, + resourceType: { + serializedName: "resourceType", + type: { + name: "String" + } + } + } + } +}; +const HttpMessage = { + type: { + name: "Composite", + className: "HttpMessage", + modelProperties: { + content: { + serializedName: "content", + type: { + name: "Dictionary", + value: { type: { name: "any" } } + } + } + } + } +}; +const DeploymentOperationsListResult = { + type: { + name: "Composite", + className: "DeploymentOperationsListResult", + modelProperties: { + value: { + serializedName: "value", + type: { + name: "Sequence", + element: { + type: { + name: "Composite", + className: "DeploymentOperation" + } + } + } + }, + nextLink: { + serializedName: "nextLink", + readOnly: true, + type: { + name: "String" + } + } + } + } +}; +const TemplateHashResult = { + type: { + name: "Composite", + className: "TemplateHashResult", + modelProperties: { + minifiedTemplate: { + serializedName: "minifiedTemplate", + type: { + name: "String" + } + }, + templateHash: { + serializedName: "templateHash", + type: { + name: "String" + } + } + } + } +}; +const TagsResource = { + type: { + name: "Composite", + className: "TagsResource", + modelProperties: { + id: { + serializedName: "id", + readOnly: true, + type: { + name: "String" + } + }, + name: { + serializedName: "name", + readOnly: true, + type: { + name: "String" + } + }, + type: { + serializedName: "type", + readOnly: true, + type: { + name: "String" + } + }, + properties: { + serializedName: "properties", + type: { + name: "Composite", + className: "Tags" + } + } + } + } +}; +const Tags = { + type: { + name: "Composite", + className: "Tags", + modelProperties: { + tags: { + serializedName: "tags", + type: { + name: "Dictionary", + value: { type: { name: "String" } } + } + } + } + } +}; +const TagsPatchResource = { + type: { + name: "Composite", + className: "TagsPatchResource", + modelProperties: { + operation: { + serializedName: "operation", + type: { + name: "String" + } + }, + properties: { + serializedName: "properties", + type: { + name: "Composite", + className: "Tags" + } + } + } + } +}; +const DeploymentExtendedFilter = { + type: { + name: "Composite", + className: "DeploymentExtendedFilter", + modelProperties: { + provisioningState: { + serializedName: "provisioningState", + type: { + name: "String" + } + } + } + } +}; +const GenericResourceFilter = { + type: { + name: "Composite", + className: "GenericResourceFilter", + modelProperties: { + resourceType: { + serializedName: "resourceType", + type: { + name: "String" + } + }, + tagname: { + serializedName: "tagname", + type: { + name: "String" + } + }, + tagvalue: { + serializedName: "tagvalue", + type: { + name: "String" + } + } + } + } +}; +const ResourceGroupFilter = { + type: { + name: "Composite", + className: "ResourceGroupFilter", + modelProperties: { + tagName: { + serializedName: "tagName", + type: { + name: "String" + } + }, + tagValue: { + serializedName: "tagValue", + type: { + name: "String" + } + } + } + } +}; +const ResourceProviderOperationDisplayProperties = { + type: { + name: "Composite", + className: "ResourceProviderOperationDisplayProperties", + modelProperties: { + publisher: { + serializedName: "publisher", + type: { + name: "String" + } + }, + provider: { + serializedName: "provider", + type: { + name: "String" + } + }, + resource: { + serializedName: "resource", + type: { + name: "String" + } + }, + operation: { + serializedName: "operation", + type: { + name: "String" + } + }, + description: { + serializedName: "description", + type: { + name: "String" + } + } + } + } +}; +const SubResource = { + type: { + name: "Composite", + className: "SubResource", + modelProperties: { + id: { + serializedName: "id", + type: { + name: "String" + } + } + } + } +}; +const DeploymentWhatIfProperties = { + type: { + name: "Composite", + className: "DeploymentWhatIfProperties", + modelProperties: Object.assign(Object.assign({}, DeploymentProperties.type.modelProperties), { whatIfSettings: { + serializedName: "whatIfSettings", + type: { + name: "Composite", + className: "DeploymentWhatIfSettings" + } + } }) + } +}; +const GenericResource = { + type: { + name: "Composite", + className: "GenericResource", + modelProperties: Object.assign(Object.assign({}, Resource.type.modelProperties), { plan: { + serializedName: "plan", + type: { + name: "Composite", + className: "Plan" + } + }, properties: { + serializedName: "properties", + type: { + name: "Dictionary", + value: { type: { name: "any" } } + } + }, kind: { + constraints: { + Pattern: new RegExp("^[-\\w\\._,\\(\\)]+$") + }, + serializedName: "kind", + type: { + name: "String" + } + }, managedBy: { + serializedName: "managedBy", + type: { + name: "String" + } + }, sku: { + serializedName: "sku", + type: { + name: "Composite", + className: "Sku" + } + }, identity: { + serializedName: "identity", + type: { + name: "Composite", + className: "Identity" + } + } }) + } +}; +const GenericResourceExpanded = { + type: { + name: "Composite", + className: "GenericResourceExpanded", + modelProperties: Object.assign(Object.assign({}, GenericResource.type.modelProperties), { createdTime: { + serializedName: "createdTime", + readOnly: true, + type: { + name: "DateTime" + } + }, changedTime: { + serializedName: "changedTime", + readOnly: true, + type: { + name: "DateTime" + } + }, provisioningState: { + serializedName: "provisioningState", + readOnly: true, + type: { + name: "String" + } + } }) + } +}; +const DeploymentsWhatIfAtTenantScopeHeaders = { + type: { + name: "Composite", + className: "DeploymentsWhatIfAtTenantScopeHeaders", + modelProperties: { + location: { + serializedName: "location", + type: { + name: "String" + } + }, + retryAfter: { + serializedName: "retry-after", + type: { + name: "String" + } + } + } + } +}; +const DeploymentsWhatIfAtManagementGroupScopeHeaders = { + type: { + name: "Composite", + className: "DeploymentsWhatIfAtManagementGroupScopeHeaders", + modelProperties: { + location: { + serializedName: "location", + type: { + name: "String" + } + }, + retryAfter: { + serializedName: "retry-after", + type: { + name: "String" + } + } + } + } +}; +const DeploymentsWhatIfAtSubscriptionScopeHeaders = { + type: { + name: "Composite", + className: "DeploymentsWhatIfAtSubscriptionScopeHeaders", + modelProperties: { + location: { + serializedName: "location", + type: { + name: "String" + } + }, + retryAfter: { + serializedName: "retry-after", + type: { + name: "String" + } + } + } + } +}; +const DeploymentsWhatIfHeaders = { + type: { + name: "Composite", + className: "DeploymentsWhatIfHeaders", + modelProperties: { + location: { + serializedName: "location", + type: { + name: "String" + } + }, + retryAfter: { + serializedName: "retry-after", + type: { + name: "String" + } + } + } + } +}; + +var Mappers = /*#__PURE__*/Object.freeze({ + __proto__: null, + OperationListResult: OperationListResult, + Operation: Operation, + OperationDisplay: OperationDisplay, + CloudError: CloudError, + ErrorResponse: ErrorResponse, + ErrorAdditionalInfo: ErrorAdditionalInfo, + Deployment: Deployment, + DeploymentProperties: DeploymentProperties, + TemplateLink: TemplateLink, + ParametersLink: ParametersLink, + DebugSetting: DebugSetting, + OnErrorDeployment: OnErrorDeployment, + ExpressionEvaluationOptions: ExpressionEvaluationOptions, + DeploymentExtended: DeploymentExtended, + DeploymentPropertiesExtended: DeploymentPropertiesExtended, + Provider: Provider, + ProviderResourceType: ProviderResourceType, + ProviderExtendedLocation: ProviderExtendedLocation, + Alias: Alias, + AliasPath: AliasPath, + AliasPattern: AliasPattern, + AliasPathMetadata: AliasPathMetadata, + ZoneMapping: ZoneMapping, + ApiProfile: ApiProfile, + Dependency: Dependency, + BasicDependency: BasicDependency, + OnErrorDeploymentExtended: OnErrorDeploymentExtended, + ResourceReference: ResourceReference, + DeploymentValidateResult: DeploymentValidateResult, + DeploymentExportResult: DeploymentExportResult, + DeploymentListResult: DeploymentListResult, + ScopedDeployment: ScopedDeployment, + ScopedDeploymentWhatIf: ScopedDeploymentWhatIf, + DeploymentWhatIfSettings: DeploymentWhatIfSettings, + WhatIfOperationResult: WhatIfOperationResult, + WhatIfChange: WhatIfChange, + WhatIfPropertyChange: WhatIfPropertyChange, + DeploymentWhatIf: DeploymentWhatIf, + ProviderPermissionListResult: ProviderPermissionListResult, + ProviderPermission: ProviderPermission, + RoleDefinition: RoleDefinition, + Permission: Permission, + ProviderRegistrationRequest: ProviderRegistrationRequest, + ProviderConsentDefinition: ProviderConsentDefinition, + ProviderListResult: ProviderListResult, + ProviderResourceTypeListResult: ProviderResourceTypeListResult, + ResourceListResult: ResourceListResult, + Plan: Plan, + Sku: Sku, + Identity: Identity, + IdentityUserAssignedIdentitiesValue: IdentityUserAssignedIdentitiesValue, + Resource: Resource, + ExtendedLocation: ExtendedLocation, + ResourceGroup: ResourceGroup, + ResourceGroupProperties: ResourceGroupProperties, + ResourceGroupPatchable: ResourceGroupPatchable, + ExportTemplateRequest: ExportTemplateRequest, + ResourceGroupExportResult: ResourceGroupExportResult, + ResourceGroupListResult: ResourceGroupListResult, + ResourcesMoveInfo: ResourcesMoveInfo, + TagValue: TagValue, + TagCount: TagCount, + TagDetails: TagDetails, + TagsListResult: TagsListResult, + DeploymentOperation: DeploymentOperation, + DeploymentOperationProperties: DeploymentOperationProperties, + StatusMessage: StatusMessage, + TargetResource: TargetResource, + HttpMessage: HttpMessage, + DeploymentOperationsListResult: DeploymentOperationsListResult, + TemplateHashResult: TemplateHashResult, + TagsResource: TagsResource, + Tags: Tags, + TagsPatchResource: TagsPatchResource, + DeploymentExtendedFilter: DeploymentExtendedFilter, + GenericResourceFilter: GenericResourceFilter, + ResourceGroupFilter: ResourceGroupFilter, + ResourceProviderOperationDisplayProperties: ResourceProviderOperationDisplayProperties, + SubResource: SubResource, + DeploymentWhatIfProperties: DeploymentWhatIfProperties, + GenericResource: GenericResource, + GenericResourceExpanded: GenericResourceExpanded, + DeploymentsWhatIfAtTenantScopeHeaders: DeploymentsWhatIfAtTenantScopeHeaders, + DeploymentsWhatIfAtManagementGroupScopeHeaders: DeploymentsWhatIfAtManagementGroupScopeHeaders, + DeploymentsWhatIfAtSubscriptionScopeHeaders: DeploymentsWhatIfAtSubscriptionScopeHeaders, + DeploymentsWhatIfHeaders: DeploymentsWhatIfHeaders +}); + +/* + * Copyright (c) Microsoft Corporation. + * Licensed under the MIT License. + * + * Code generated by Microsoft (R) AutoRest Code Generator. + * Changes may cause incorrect behavior and will be lost if the code is regenerated. + */ +const accept = { + parameterPath: "accept", + mapper: { + defaultValue: "application/json", + isConstant: true, + serializedName: "Accept", + type: { + name: "String" + } + } +}; +const $host = { + parameterPath: "$host", + mapper: { + serializedName: "$host", + required: true, + type: { + name: "String" + } + }, + skipEncoding: true +}; +const apiVersion = { + parameterPath: "apiVersion", + mapper: { + defaultValue: "2021-04-01", + isConstant: true, + serializedName: "api-version", + type: { + name: "String" + } + } +}; +const nextLink = { + parameterPath: "nextLink", + mapper: { + serializedName: "nextLink", + required: true, + type: { + name: "String" + } + }, + skipEncoding: true +}; +const scope = { + parameterPath: "scope", + mapper: { + serializedName: "scope", + required: true, + type: { + name: "String" + } + }, + skipEncoding: true +}; +const deploymentName = { + parameterPath: "deploymentName", + mapper: { + constraints: { + Pattern: new RegExp("^[-\\w\\._\\(\\)]+$"), + MaxLength: 64, + MinLength: 1 + }, + serializedName: "deploymentName", + required: true, + type: { + name: "String" + } + } +}; +const contentType = { + parameterPath: ["options", "contentType"], + mapper: { + defaultValue: "application/json", + isConstant: true, + serializedName: "Content-Type", + type: { + name: "String" + } + } +}; +const parameters = { + parameterPath: "parameters", + mapper: Deployment +}; +const filter = { + parameterPath: ["options", "filter"], + mapper: { + serializedName: "$filter", + type: { + name: "String" + } + } +}; +const top = { + parameterPath: ["options", "top"], + mapper: { + serializedName: "$top", + type: { + name: "Number" + } + } +}; +const parameters1 = { + parameterPath: "parameters", + mapper: ScopedDeployment +}; +const parameters2 = { + parameterPath: "parameters", + mapper: ScopedDeploymentWhatIf +}; +const groupId = { + parameterPath: "groupId", + mapper: { + constraints: { + MaxLength: 90, + MinLength: 1 + }, + serializedName: "groupId", + required: true, + type: { + name: "String" + } + } +}; +const subscriptionId = { + parameterPath: "subscriptionId", + mapper: { + serializedName: "subscriptionId", + required: true, + type: { + name: "String" + } + } +}; +const parameters3 = { + parameterPath: "parameters", + mapper: DeploymentWhatIf +}; +const resourceGroupName = { + parameterPath: "resourceGroupName", + mapper: { + constraints: { + Pattern: new RegExp("^[-\\w\\._\\(\\)]+$"), + MaxLength: 90, + MinLength: 1 + }, + serializedName: "resourceGroupName", + required: true, + type: { + name: "String" + } + } +}; +const template = { + parameterPath: "template", + mapper: { + serializedName: "template", + required: true, + type: { + name: "Dictionary", + value: { type: { name: "any" } } + } + } +}; +const resourceProviderNamespace = { + parameterPath: "resourceProviderNamespace", + mapper: { + serializedName: "resourceProviderNamespace", + required: true, + type: { + name: "String" + } + } +}; +const properties = { + parameterPath: ["options", "properties"], + mapper: ProviderRegistrationRequest +}; +const expand = { + parameterPath: ["options", "expand"], + mapper: { + serializedName: "$expand", + type: { + name: "String" + } + } +}; +const parameters4 = { + parameterPath: "parameters", + mapper: ResourcesMoveInfo +}; +const sourceResourceGroupName = { + parameterPath: "sourceResourceGroupName", + mapper: { + constraints: { + Pattern: new RegExp("^[-\\w\\._\\(\\)]+$"), + MaxLength: 90, + MinLength: 1 + }, + serializedName: "sourceResourceGroupName", + required: true, + type: { + name: "String" + } + } +}; +const parentResourcePath = { + parameterPath: "parentResourcePath", + mapper: { + serializedName: "parentResourcePath", + required: true, + type: { + name: "String" + } + }, + skipEncoding: true +}; +const resourceType = { + parameterPath: "resourceType", + mapper: { + serializedName: "resourceType", + required: true, + type: { + name: "String" + } + }, + skipEncoding: true +}; +const resourceName = { + parameterPath: "resourceName", + mapper: { + serializedName: "resourceName", + required: true, + type: { + name: "String" + } + } +}; +const apiVersion1 = { + parameterPath: "apiVersion", + mapper: { + serializedName: "api-version", + required: true, + type: { + name: "String" + } + } +}; +const parameters5 = { + parameterPath: "parameters", + mapper: GenericResource +}; +const resourceId = { + parameterPath: "resourceId", + mapper: { + serializedName: "resourceId", + required: true, + type: { + name: "String" + } + }, + skipEncoding: true +}; +const parameters6 = { + parameterPath: "parameters", + mapper: ResourceGroup +}; +const forceDeletionTypes = { + parameterPath: ["options", "forceDeletionTypes"], + mapper: { + serializedName: "forceDeletionTypes", + type: { + name: "String" + } + } +}; +const parameters7 = { + parameterPath: "parameters", + mapper: ResourceGroupPatchable +}; +const parameters8 = { + parameterPath: "parameters", + mapper: ExportTemplateRequest +}; +const resourceGroupName1 = { + parameterPath: "resourceGroupName", + mapper: { + constraints: { + MaxLength: 90, + MinLength: 1 + }, + serializedName: "resourceGroupName", + required: true, + type: { + name: "String" + } + } +}; +const tagName = { + parameterPath: "tagName", + mapper: { + serializedName: "tagName", + required: true, + type: { + name: "String" + } + } +}; +const tagValue = { + parameterPath: "tagValue", + mapper: { + serializedName: "tagValue", + required: true, + type: { + name: "String" + } + } +}; +const parameters9 = { + parameterPath: "parameters", + mapper: TagsResource +}; +const parameters10 = { + parameterPath: "parameters", + mapper: TagsPatchResource +}; +const operationId = { + parameterPath: "operationId", + mapper: { + serializedName: "operationId", + required: true, + type: { + name: "String" + } + } +}; + +/* + * Copyright (c) Microsoft Corporation. + * Licensed under the MIT License. + * + * Code generated by Microsoft (R) AutoRest Code Generator. + * Changes may cause incorrect behavior and will be lost if the code is regenerated. + */ +/// +/** Class containing Operations operations. */ +class OperationsImpl { + /** + * Initialize a new instance of the class Operations class. + * @param client Reference to the service client + */ + constructor(client) { + this.client = client; + } + /** + * Lists all of the available Microsoft.Resources REST API operations. + * @param options The options parameters. + */ + list(options) { + const iter = this.listPagingAll(options); + return { + next() { + return iter.next(); + }, + [Symbol.asyncIterator]() { + return this; + }, + byPage: (settings) => { + if (settings === null || settings === void 0 ? void 0 : settings.maxPageSize) { + throw new Error("maxPageSize is not supported by this operation."); + } + return this.listPagingPage(options, settings); + } + }; + } + listPagingPage(options, settings) { + return tslib.__asyncGenerator(this, arguments, function* listPagingPage_1() { + let result; + let continuationToken = settings === null || settings === void 0 ? void 0 : settings.continuationToken; + if (!continuationToken) { + result = yield tslib.__await(this._list(options)); + let page = result.value || []; + continuationToken = result.nextLink; + setContinuationToken(page, continuationToken); + yield yield tslib.__await(page); + } + while (continuationToken) { + result = yield tslib.__await(this._listNext(continuationToken, options)); + continuationToken = result.nextLink; + let page = result.value || []; + setContinuationToken(page, continuationToken); + yield yield tslib.__await(page); + } + }); + } + listPagingAll(options) { + return tslib.__asyncGenerator(this, arguments, function* listPagingAll_1() { + var e_1, _a; + try { + for (var _b = tslib.__asyncValues(this.listPagingPage(options)), _c; _c = yield tslib.__await(_b.next()), !_c.done;) { + const page = _c.value; + yield tslib.__await(yield* tslib.__asyncDelegator(tslib.__asyncValues(page))); + } + } + catch (e_1_1) { e_1 = { error: e_1_1 }; } + finally { + try { + if (_c && !_c.done && (_a = _b.return)) yield tslib.__await(_a.call(_b)); + } + finally { if (e_1) throw e_1.error; } + } + }); + } + /** + * Lists all of the available Microsoft.Resources REST API operations. + * @param options The options parameters. + */ + _list(options) { + return this.client.sendOperationRequest({ options }, listOperationSpec$6); + } + /** + * ListNext + * @param nextLink The nextLink from the previous successful call to the List method. + * @param options The options parameters. + */ + _listNext(nextLink, options) { + return this.client.sendOperationRequest({ nextLink, options }, listNextOperationSpec$5); + } +} +// Operation Specifications +const serializer$7 = coreClient__namespace.createSerializer(Mappers, /* isXml */ false); +const listOperationSpec$6 = { + path: "/providers/Microsoft.Resources/operations", + httpMethod: "GET", + responses: { + 200: { + bodyMapper: OperationListResult + }, + default: { + bodyMapper: CloudError + } + }, + queryParameters: [apiVersion], + urlParameters: [$host], + headerParameters: [accept], + serializer: serializer$7 +}; +const listNextOperationSpec$5 = { + path: "{nextLink}", + httpMethod: "GET", + responses: { + 200: { + bodyMapper: OperationListResult + }, + default: { + bodyMapper: CloudError + } + }, + urlParameters: [$host, nextLink], + headerParameters: [accept], + serializer: serializer$7 +}; + +/* + * Copyright (c) Microsoft Corporation. + * Licensed under the MIT License. + * + * Code generated by Microsoft (R) AutoRest Code Generator. + * Changes may cause incorrect behavior and will be lost if the code is regenerated. + */ +function createLroSpec(inputs) { + const { args, spec, sendOperationFn } = inputs; + return { + requestMethod: spec.httpMethod, + requestPath: spec.path, + sendInitialRequest: () => sendOperationFn(args, spec), + sendPollRequest: (path, options) => { + const restSpec = tslib.__rest(spec, ["requestBody"]); + return sendOperationFn(args, Object.assign(Object.assign({}, restSpec), { httpMethod: "GET", path, abortSignal: options === null || options === void 0 ? void 0 : options.abortSignal })); + } + }; +} + +/* + * Copyright (c) Microsoft Corporation. + * Licensed under the MIT License. + * + * Code generated by Microsoft (R) AutoRest Code Generator. + * Changes may cause incorrect behavior and will be lost if the code is regenerated. + */ +/// +/** Class containing Deployments operations. */ +class DeploymentsImpl { + /** + * Initialize a new instance of the class Deployments class. + * @param client Reference to the service client + */ + constructor(client) { + this.client = client; + } + /** + * Get all the deployments at the given scope. + * @param scope The resource scope. + * @param options The options parameters. + */ + listAtScope(scope, options) { + const iter = this.listAtScopePagingAll(scope, options); + return { + next() { + return iter.next(); + }, + [Symbol.asyncIterator]() { + return this; + }, + byPage: (settings) => { + if (settings === null || settings === void 0 ? void 0 : settings.maxPageSize) { + throw new Error("maxPageSize is not supported by this operation."); + } + return this.listAtScopePagingPage(scope, options, settings); + } + }; + } + listAtScopePagingPage(scope, options, settings) { + return tslib.__asyncGenerator(this, arguments, function* listAtScopePagingPage_1() { + let result; + let continuationToken = settings === null || settings === void 0 ? void 0 : settings.continuationToken; + if (!continuationToken) { + result = yield tslib.__await(this._listAtScope(scope, options)); + let page = result.value || []; + continuationToken = result.nextLink; + setContinuationToken(page, continuationToken); + yield yield tslib.__await(page); + } + while (continuationToken) { + result = yield tslib.__await(this._listAtScopeNext(scope, continuationToken, options)); + continuationToken = result.nextLink; + let page = result.value || []; + setContinuationToken(page, continuationToken); + yield yield tslib.__await(page); + } + }); + } + listAtScopePagingAll(scope, options) { + return tslib.__asyncGenerator(this, arguments, function* listAtScopePagingAll_1() { + var e_1, _a; + try { + for (var _b = tslib.__asyncValues(this.listAtScopePagingPage(scope, options)), _c; _c = yield tslib.__await(_b.next()), !_c.done;) { + const page = _c.value; + yield tslib.__await(yield* tslib.__asyncDelegator(tslib.__asyncValues(page))); + } + } + catch (e_1_1) { e_1 = { error: e_1_1 }; } + finally { + try { + if (_c && !_c.done && (_a = _b.return)) yield tslib.__await(_a.call(_b)); + } + finally { if (e_1) throw e_1.error; } + } + }); + } + /** + * Get all the deployments at the tenant scope. + * @param options The options parameters. + */ + listAtTenantScope(options) { + const iter = this.listAtTenantScopePagingAll(options); + return { + next() { + return iter.next(); + }, + [Symbol.asyncIterator]() { + return this; + }, + byPage: (settings) => { + if (settings === null || settings === void 0 ? void 0 : settings.maxPageSize) { + throw new Error("maxPageSize is not supported by this operation."); + } + return this.listAtTenantScopePagingPage(options, settings); + } + }; + } + listAtTenantScopePagingPage(options, settings) { + return tslib.__asyncGenerator(this, arguments, function* listAtTenantScopePagingPage_1() { + let result; + let continuationToken = settings === null || settings === void 0 ? void 0 : settings.continuationToken; + if (!continuationToken) { + result = yield tslib.__await(this._listAtTenantScope(options)); + let page = result.value || []; + continuationToken = result.nextLink; + setContinuationToken(page, continuationToken); + yield yield tslib.__await(page); + } + while (continuationToken) { + result = yield tslib.__await(this._listAtTenantScopeNext(continuationToken, options)); + continuationToken = result.nextLink; + let page = result.value || []; + setContinuationToken(page, continuationToken); + yield yield tslib.__await(page); + } + }); + } + listAtTenantScopePagingAll(options) { + return tslib.__asyncGenerator(this, arguments, function* listAtTenantScopePagingAll_1() { + var e_2, _a; + try { + for (var _b = tslib.__asyncValues(this.listAtTenantScopePagingPage(options)), _c; _c = yield tslib.__await(_b.next()), !_c.done;) { + const page = _c.value; + yield tslib.__await(yield* tslib.__asyncDelegator(tslib.__asyncValues(page))); + } + } + catch (e_2_1) { e_2 = { error: e_2_1 }; } + finally { + try { + if (_c && !_c.done && (_a = _b.return)) yield tslib.__await(_a.call(_b)); + } + finally { if (e_2) throw e_2.error; } + } + }); + } + /** + * Get all the deployments for a management group. + * @param groupId The management group ID. + * @param options The options parameters. + */ + listAtManagementGroupScope(groupId, options) { + const iter = this.listAtManagementGroupScopePagingAll(groupId, options); + return { + next() { + return iter.next(); + }, + [Symbol.asyncIterator]() { + return this; + }, + byPage: (settings) => { + if (settings === null || settings === void 0 ? void 0 : settings.maxPageSize) { + throw new Error("maxPageSize is not supported by this operation."); + } + return this.listAtManagementGroupScopePagingPage(groupId, options, settings); + } + }; + } + listAtManagementGroupScopePagingPage(groupId, options, settings) { + return tslib.__asyncGenerator(this, arguments, function* listAtManagementGroupScopePagingPage_1() { + let result; + let continuationToken = settings === null || settings === void 0 ? void 0 : settings.continuationToken; + if (!continuationToken) { + result = yield tslib.__await(this._listAtManagementGroupScope(groupId, options)); + let page = result.value || []; + continuationToken = result.nextLink; + setContinuationToken(page, continuationToken); + yield yield tslib.__await(page); + } + while (continuationToken) { + result = yield tslib.__await(this._listAtManagementGroupScopeNext(groupId, continuationToken, options)); + continuationToken = result.nextLink; + let page = result.value || []; + setContinuationToken(page, continuationToken); + yield yield tslib.__await(page); + } + }); + } + listAtManagementGroupScopePagingAll(groupId, options) { + return tslib.__asyncGenerator(this, arguments, function* listAtManagementGroupScopePagingAll_1() { + var e_3, _a; + try { + for (var _b = tslib.__asyncValues(this.listAtManagementGroupScopePagingPage(groupId, options)), _c; _c = yield tslib.__await(_b.next()), !_c.done;) { + const page = _c.value; + yield tslib.__await(yield* tslib.__asyncDelegator(tslib.__asyncValues(page))); + } + } + catch (e_3_1) { e_3 = { error: e_3_1 }; } + finally { + try { + if (_c && !_c.done && (_a = _b.return)) yield tslib.__await(_a.call(_b)); + } + finally { if (e_3) throw e_3.error; } + } + }); + } + /** + * Get all the deployments for a subscription. + * @param options The options parameters. + */ + listAtSubscriptionScope(options) { + const iter = this.listAtSubscriptionScopePagingAll(options); + return { + next() { + return iter.next(); + }, + [Symbol.asyncIterator]() { + return this; + }, + byPage: (settings) => { + if (settings === null || settings === void 0 ? void 0 : settings.maxPageSize) { + throw new Error("maxPageSize is not supported by this operation."); + } + return this.listAtSubscriptionScopePagingPage(options, settings); + } + }; + } + listAtSubscriptionScopePagingPage(options, settings) { + return tslib.__asyncGenerator(this, arguments, function* listAtSubscriptionScopePagingPage_1() { + let result; + let continuationToken = settings === null || settings === void 0 ? void 0 : settings.continuationToken; + if (!continuationToken) { + result = yield tslib.__await(this._listAtSubscriptionScope(options)); + let page = result.value || []; + continuationToken = result.nextLink; + setContinuationToken(page, continuationToken); + yield yield tslib.__await(page); + } + while (continuationToken) { + result = yield tslib.__await(this._listAtSubscriptionScopeNext(continuationToken, options)); + continuationToken = result.nextLink; + let page = result.value || []; + setContinuationToken(page, continuationToken); + yield yield tslib.__await(page); + } + }); + } + listAtSubscriptionScopePagingAll(options) { + return tslib.__asyncGenerator(this, arguments, function* listAtSubscriptionScopePagingAll_1() { + var e_4, _a; + try { + for (var _b = tslib.__asyncValues(this.listAtSubscriptionScopePagingPage(options)), _c; _c = yield tslib.__await(_b.next()), !_c.done;) { + const page = _c.value; + yield tslib.__await(yield* tslib.__asyncDelegator(tslib.__asyncValues(page))); + } + } + catch (e_4_1) { e_4 = { error: e_4_1 }; } + finally { + try { + if (_c && !_c.done && (_a = _b.return)) yield tslib.__await(_a.call(_b)); + } + finally { if (e_4) throw e_4.error; } + } + }); + } + /** + * Get all the deployments for a resource group. + * @param resourceGroupName The name of the resource group with the deployments to get. The name is + * case insensitive. + * @param options The options parameters. + */ + listByResourceGroup(resourceGroupName, options) { + const iter = this.listByResourceGroupPagingAll(resourceGroupName, options); + return { + next() { + return iter.next(); + }, + [Symbol.asyncIterator]() { + return this; + }, + byPage: (settings) => { + if (settings === null || settings === void 0 ? void 0 : settings.maxPageSize) { + throw new Error("maxPageSize is not supported by this operation."); + } + return this.listByResourceGroupPagingPage(resourceGroupName, options, settings); + } + }; + } + listByResourceGroupPagingPage(resourceGroupName, options, settings) { + return tslib.__asyncGenerator(this, arguments, function* listByResourceGroupPagingPage_1() { + let result; + let continuationToken = settings === null || settings === void 0 ? void 0 : settings.continuationToken; + if (!continuationToken) { + result = yield tslib.__await(this._listByResourceGroup(resourceGroupName, options)); + let page = result.value || []; + continuationToken = result.nextLink; + setContinuationToken(page, continuationToken); + yield yield tslib.__await(page); + } + while (continuationToken) { + result = yield tslib.__await(this._listByResourceGroupNext(resourceGroupName, continuationToken, options)); + continuationToken = result.nextLink; + let page = result.value || []; + setContinuationToken(page, continuationToken); + yield yield tslib.__await(page); + } + }); + } + listByResourceGroupPagingAll(resourceGroupName, options) { + return tslib.__asyncGenerator(this, arguments, function* listByResourceGroupPagingAll_1() { + var e_5, _a; + try { + for (var _b = tslib.__asyncValues(this.listByResourceGroupPagingPage(resourceGroupName, options)), _c; _c = yield tslib.__await(_b.next()), !_c.done;) { + const page = _c.value; + yield tslib.__await(yield* tslib.__asyncDelegator(tslib.__asyncValues(page))); + } + } + catch (e_5_1) { e_5 = { error: e_5_1 }; } + finally { + try { + if (_c && !_c.done && (_a = _b.return)) yield tslib.__await(_a.call(_b)); + } + finally { if (e_5) throw e_5.error; } + } + }); + } + /** + * A template deployment that is currently running cannot be deleted. Deleting a template deployment + * removes the associated deployment operations. This is an asynchronous operation that returns a + * status of 202 until the template deployment is successfully deleted. The Location response header + * contains the URI that is used to obtain the status of the process. While the process is running, a + * call to the URI in the Location header returns a status of 202. When the process finishes, the URI + * in the Location header returns a status of 204 on success. If the asynchronous request failed, the + * URI in the Location header returns an error-level status code. + * @param scope The resource scope. + * @param deploymentName The name of the deployment. + * @param options The options parameters. + */ + beginDeleteAtScope(scope, deploymentName, options) { + return tslib.__awaiter(this, void 0, void 0, function* () { + const directSendOperation = (args, spec) => tslib.__awaiter(this, void 0, void 0, function* () { + return this.client.sendOperationRequest(args, spec); + }); + const sendOperationFn = (args, spec) => tslib.__awaiter(this, void 0, void 0, function* () { + var _a; + let currentRawResponse = undefined; + const providedCallback = (_a = args.options) === null || _a === void 0 ? void 0 : _a.onResponse; + const callback = (rawResponse, flatResponse) => { + currentRawResponse = rawResponse; + providedCallback === null || providedCallback === void 0 ? void 0 : providedCallback(rawResponse, flatResponse); + }; + const updatedArgs = Object.assign(Object.assign({}, args), { options: Object.assign(Object.assign({}, args.options), { onResponse: callback }) }); + const flatResponse = yield directSendOperation(updatedArgs, spec); + return { + flatResponse, + rawResponse: { + statusCode: currentRawResponse.status, + body: currentRawResponse.parsedBody, + headers: currentRawResponse.headers.toJSON() + } + }; + }); + const lro = createLroSpec({ + sendOperationFn, + args: { scope, deploymentName, options }, + spec: deleteAtScopeOperationSpec$1 + }); + const poller = yield coreLro.createHttpPoller(lro, { + restoreFrom: options === null || options === void 0 ? void 0 : options.resumeFrom, + intervalInMs: options === null || options === void 0 ? void 0 : options.updateIntervalInMs + }); + yield poller.poll(); + return poller; + }); + } + /** + * A template deployment that is currently running cannot be deleted. Deleting a template deployment + * removes the associated deployment operations. This is an asynchronous operation that returns a + * status of 202 until the template deployment is successfully deleted. The Location response header + * contains the URI that is used to obtain the status of the process. While the process is running, a + * call to the URI in the Location header returns a status of 202. When the process finishes, the URI + * in the Location header returns a status of 204 on success. If the asynchronous request failed, the + * URI in the Location header returns an error-level status code. + * @param scope The resource scope. + * @param deploymentName The name of the deployment. + * @param options The options parameters. + */ + beginDeleteAtScopeAndWait(scope, deploymentName, options) { + return tslib.__awaiter(this, void 0, void 0, function* () { + const poller = yield this.beginDeleteAtScope(scope, deploymentName, options); + return poller.pollUntilDone(); + }); + } + /** + * Checks whether the deployment exists. + * @param scope The resource scope. + * @param deploymentName The name of the deployment. + * @param options The options parameters. + */ + checkExistenceAtScope(scope, deploymentName, options) { + return this.client.sendOperationRequest({ scope, deploymentName, options }, checkExistenceAtScopeOperationSpec); + } + /** + * You can provide the template and parameters directly in the request or link to JSON files. + * @param scope The resource scope. + * @param deploymentName The name of the deployment. + * @param parameters Additional parameters supplied to the operation. + * @param options The options parameters. + */ + beginCreateOrUpdateAtScope(scope, deploymentName, parameters, options) { + return tslib.__awaiter(this, void 0, void 0, function* () { + const directSendOperation = (args, spec) => tslib.__awaiter(this, void 0, void 0, function* () { + return this.client.sendOperationRequest(args, spec); + }); + const sendOperationFn = (args, spec) => tslib.__awaiter(this, void 0, void 0, function* () { + var _a; + let currentRawResponse = undefined; + const providedCallback = (_a = args.options) === null || _a === void 0 ? void 0 : _a.onResponse; + const callback = (rawResponse, flatResponse) => { + currentRawResponse = rawResponse; + providedCallback === null || providedCallback === void 0 ? void 0 : providedCallback(rawResponse, flatResponse); + }; + const updatedArgs = Object.assign(Object.assign({}, args), { options: Object.assign(Object.assign({}, args.options), { onResponse: callback }) }); + const flatResponse = yield directSendOperation(updatedArgs, spec); + return { + flatResponse, + rawResponse: { + statusCode: currentRawResponse.status, + body: currentRawResponse.parsedBody, + headers: currentRawResponse.headers.toJSON() + } + }; + }); + const lro = createLroSpec({ + sendOperationFn, + args: { scope, deploymentName, parameters, options }, + spec: createOrUpdateAtScopeOperationSpec$1 + }); + const poller = yield coreLro.createHttpPoller(lro, { + restoreFrom: options === null || options === void 0 ? void 0 : options.resumeFrom, + intervalInMs: options === null || options === void 0 ? void 0 : options.updateIntervalInMs + }); + yield poller.poll(); + return poller; + }); + } + /** + * You can provide the template and parameters directly in the request or link to JSON files. + * @param scope The resource scope. + * @param deploymentName The name of the deployment. + * @param parameters Additional parameters supplied to the operation. + * @param options The options parameters. + */ + beginCreateOrUpdateAtScopeAndWait(scope, deploymentName, parameters, options) { + return tslib.__awaiter(this, void 0, void 0, function* () { + const poller = yield this.beginCreateOrUpdateAtScope(scope, deploymentName, parameters, options); + return poller.pollUntilDone(); + }); + } + /** + * Gets a deployment. + * @param scope The resource scope. + * @param deploymentName The name of the deployment. + * @param options The options parameters. + */ + getAtScope(scope, deploymentName, options) { + return this.client.sendOperationRequest({ scope, deploymentName, options }, getAtScopeOperationSpec$2); + } + /** + * You can cancel a deployment only if the provisioningState is Accepted or Running. After the + * deployment is canceled, the provisioningState is set to Canceled. Canceling a template deployment + * stops the currently running template deployment and leaves the resources partially deployed. + * @param scope The resource scope. + * @param deploymentName The name of the deployment. + * @param options The options parameters. + */ + cancelAtScope(scope, deploymentName, options) { + return this.client.sendOperationRequest({ scope, deploymentName, options }, cancelAtScopeOperationSpec); + } + /** + * Validates whether the specified template is syntactically correct and will be accepted by Azure + * Resource Manager.. + * @param scope The resource scope. + * @param deploymentName The name of the deployment. + * @param parameters Parameters to validate. + * @param options The options parameters. + */ + beginValidateAtScope(scope, deploymentName, parameters, options) { + return tslib.__awaiter(this, void 0, void 0, function* () { + const directSendOperation = (args, spec) => tslib.__awaiter(this, void 0, void 0, function* () { + return this.client.sendOperationRequest(args, spec); + }); + const sendOperationFn = (args, spec) => tslib.__awaiter(this, void 0, void 0, function* () { + var _a; + let currentRawResponse = undefined; + const providedCallback = (_a = args.options) === null || _a === void 0 ? void 0 : _a.onResponse; + const callback = (rawResponse, flatResponse) => { + currentRawResponse = rawResponse; + providedCallback === null || providedCallback === void 0 ? void 0 : providedCallback(rawResponse, flatResponse); + }; + const updatedArgs = Object.assign(Object.assign({}, args), { options: Object.assign(Object.assign({}, args.options), { onResponse: callback }) }); + const flatResponse = yield directSendOperation(updatedArgs, spec); + return { + flatResponse, + rawResponse: { + statusCode: currentRawResponse.status, + body: currentRawResponse.parsedBody, + headers: currentRawResponse.headers.toJSON() + } + }; + }); + const lro = createLroSpec({ + sendOperationFn, + args: { scope, deploymentName, parameters, options }, + spec: validateAtScopeOperationSpec + }); + const poller = yield coreLro.createHttpPoller(lro, { + restoreFrom: options === null || options === void 0 ? void 0 : options.resumeFrom, + intervalInMs: options === null || options === void 0 ? void 0 : options.updateIntervalInMs + }); + yield poller.poll(); + return poller; + }); + } + /** + * Validates whether the specified template is syntactically correct and will be accepted by Azure + * Resource Manager.. + * @param scope The resource scope. + * @param deploymentName The name of the deployment. + * @param parameters Parameters to validate. + * @param options The options parameters. + */ + beginValidateAtScopeAndWait(scope, deploymentName, parameters, options) { + return tslib.__awaiter(this, void 0, void 0, function* () { + const poller = yield this.beginValidateAtScope(scope, deploymentName, parameters, options); + return poller.pollUntilDone(); + }); + } + /** + * Exports the template used for specified deployment. + * @param scope The resource scope. + * @param deploymentName The name of the deployment. + * @param options The options parameters. + */ + exportTemplateAtScope(scope, deploymentName, options) { + return this.client.sendOperationRequest({ scope, deploymentName, options }, exportTemplateAtScopeOperationSpec); + } + /** + * Get all the deployments at the given scope. + * @param scope The resource scope. + * @param options The options parameters. + */ + _listAtScope(scope, options) { + return this.client.sendOperationRequest({ scope, options }, listAtScopeOperationSpec$1); + } + /** + * A template deployment that is currently running cannot be deleted. Deleting a template deployment + * removes the associated deployment operations. This is an asynchronous operation that returns a + * status of 202 until the template deployment is successfully deleted. The Location response header + * contains the URI that is used to obtain the status of the process. While the process is running, a + * call to the URI in the Location header returns a status of 202. When the process finishes, the URI + * in the Location header returns a status of 204 on success. If the asynchronous request failed, the + * URI in the Location header returns an error-level status code. + * @param deploymentName The name of the deployment. + * @param options The options parameters. + */ + beginDeleteAtTenantScope(deploymentName, options) { + return tslib.__awaiter(this, void 0, void 0, function* () { + const directSendOperation = (args, spec) => tslib.__awaiter(this, void 0, void 0, function* () { + return this.client.sendOperationRequest(args, spec); + }); + const sendOperationFn = (args, spec) => tslib.__awaiter(this, void 0, void 0, function* () { + var _a; + let currentRawResponse = undefined; + const providedCallback = (_a = args.options) === null || _a === void 0 ? void 0 : _a.onResponse; + const callback = (rawResponse, flatResponse) => { + currentRawResponse = rawResponse; + providedCallback === null || providedCallback === void 0 ? void 0 : providedCallback(rawResponse, flatResponse); + }; + const updatedArgs = Object.assign(Object.assign({}, args), { options: Object.assign(Object.assign({}, args.options), { onResponse: callback }) }); + const flatResponse = yield directSendOperation(updatedArgs, spec); + return { + flatResponse, + rawResponse: { + statusCode: currentRawResponse.status, + body: currentRawResponse.parsedBody, + headers: currentRawResponse.headers.toJSON() + } + }; + }); + const lro = createLroSpec({ + sendOperationFn, + args: { deploymentName, options }, + spec: deleteAtTenantScopeOperationSpec + }); + const poller = yield coreLro.createHttpPoller(lro, { + restoreFrom: options === null || options === void 0 ? void 0 : options.resumeFrom, + intervalInMs: options === null || options === void 0 ? void 0 : options.updateIntervalInMs + }); + yield poller.poll(); + return poller; + }); + } + /** + * A template deployment that is currently running cannot be deleted. Deleting a template deployment + * removes the associated deployment operations. This is an asynchronous operation that returns a + * status of 202 until the template deployment is successfully deleted. The Location response header + * contains the URI that is used to obtain the status of the process. While the process is running, a + * call to the URI in the Location header returns a status of 202. When the process finishes, the URI + * in the Location header returns a status of 204 on success. If the asynchronous request failed, the + * URI in the Location header returns an error-level status code. + * @param deploymentName The name of the deployment. + * @param options The options parameters. + */ + beginDeleteAtTenantScopeAndWait(deploymentName, options) { + return tslib.__awaiter(this, void 0, void 0, function* () { + const poller = yield this.beginDeleteAtTenantScope(deploymentName, options); + return poller.pollUntilDone(); + }); + } + /** + * Checks whether the deployment exists. + * @param deploymentName The name of the deployment. + * @param options The options parameters. + */ + checkExistenceAtTenantScope(deploymentName, options) { + return this.client.sendOperationRequest({ deploymentName, options }, checkExistenceAtTenantScopeOperationSpec); + } + /** + * You can provide the template and parameters directly in the request or link to JSON files. + * @param deploymentName The name of the deployment. + * @param parameters Additional parameters supplied to the operation. + * @param options The options parameters. + */ + beginCreateOrUpdateAtTenantScope(deploymentName, parameters, options) { + return tslib.__awaiter(this, void 0, void 0, function* () { + const directSendOperation = (args, spec) => tslib.__awaiter(this, void 0, void 0, function* () { + return this.client.sendOperationRequest(args, spec); + }); + const sendOperationFn = (args, spec) => tslib.__awaiter(this, void 0, void 0, function* () { + var _a; + let currentRawResponse = undefined; + const providedCallback = (_a = args.options) === null || _a === void 0 ? void 0 : _a.onResponse; + const callback = (rawResponse, flatResponse) => { + currentRawResponse = rawResponse; + providedCallback === null || providedCallback === void 0 ? void 0 : providedCallback(rawResponse, flatResponse); + }; + const updatedArgs = Object.assign(Object.assign({}, args), { options: Object.assign(Object.assign({}, args.options), { onResponse: callback }) }); + const flatResponse = yield directSendOperation(updatedArgs, spec); + return { + flatResponse, + rawResponse: { + statusCode: currentRawResponse.status, + body: currentRawResponse.parsedBody, + headers: currentRawResponse.headers.toJSON() + } + }; + }); + const lro = createLroSpec({ + sendOperationFn, + args: { deploymentName, parameters, options }, + spec: createOrUpdateAtTenantScopeOperationSpec + }); + const poller = yield coreLro.createHttpPoller(lro, { + restoreFrom: options === null || options === void 0 ? void 0 : options.resumeFrom, + intervalInMs: options === null || options === void 0 ? void 0 : options.updateIntervalInMs + }); + yield poller.poll(); + return poller; + }); + } + /** + * You can provide the template and parameters directly in the request or link to JSON files. + * @param deploymentName The name of the deployment. + * @param parameters Additional parameters supplied to the operation. + * @param options The options parameters. + */ + beginCreateOrUpdateAtTenantScopeAndWait(deploymentName, parameters, options) { + return tslib.__awaiter(this, void 0, void 0, function* () { + const poller = yield this.beginCreateOrUpdateAtTenantScope(deploymentName, parameters, options); + return poller.pollUntilDone(); + }); + } + /** + * Gets a deployment. + * @param deploymentName The name of the deployment. + * @param options The options parameters. + */ + getAtTenantScope(deploymentName, options) { + return this.client.sendOperationRequest({ deploymentName, options }, getAtTenantScopeOperationSpec$2); + } + /** + * You can cancel a deployment only if the provisioningState is Accepted or Running. After the + * deployment is canceled, the provisioningState is set to Canceled. Canceling a template deployment + * stops the currently running template deployment and leaves the resources partially deployed. + * @param deploymentName The name of the deployment. + * @param options The options parameters. + */ + cancelAtTenantScope(deploymentName, options) { + return this.client.sendOperationRequest({ deploymentName, options }, cancelAtTenantScopeOperationSpec); + } + /** + * Validates whether the specified template is syntactically correct and will be accepted by Azure + * Resource Manager.. + * @param deploymentName The name of the deployment. + * @param parameters Parameters to validate. + * @param options The options parameters. + */ + beginValidateAtTenantScope(deploymentName, parameters, options) { + return tslib.__awaiter(this, void 0, void 0, function* () { + const directSendOperation = (args, spec) => tslib.__awaiter(this, void 0, void 0, function* () { + return this.client.sendOperationRequest(args, spec); + }); + const sendOperationFn = (args, spec) => tslib.__awaiter(this, void 0, void 0, function* () { + var _a; + let currentRawResponse = undefined; + const providedCallback = (_a = args.options) === null || _a === void 0 ? void 0 : _a.onResponse; + const callback = (rawResponse, flatResponse) => { + currentRawResponse = rawResponse; + providedCallback === null || providedCallback === void 0 ? void 0 : providedCallback(rawResponse, flatResponse); + }; + const updatedArgs = Object.assign(Object.assign({}, args), { options: Object.assign(Object.assign({}, args.options), { onResponse: callback }) }); + const flatResponse = yield directSendOperation(updatedArgs, spec); + return { + flatResponse, + rawResponse: { + statusCode: currentRawResponse.status, + body: currentRawResponse.parsedBody, + headers: currentRawResponse.headers.toJSON() + } + }; + }); + const lro = createLroSpec({ + sendOperationFn, + args: { deploymentName, parameters, options }, + spec: validateAtTenantScopeOperationSpec + }); + const poller = yield coreLro.createHttpPoller(lro, { + restoreFrom: options === null || options === void 0 ? void 0 : options.resumeFrom, + intervalInMs: options === null || options === void 0 ? void 0 : options.updateIntervalInMs + }); + yield poller.poll(); + return poller; + }); + } + /** + * Validates whether the specified template is syntactically correct and will be accepted by Azure + * Resource Manager.. + * @param deploymentName The name of the deployment. + * @param parameters Parameters to validate. + * @param options The options parameters. + */ + beginValidateAtTenantScopeAndWait(deploymentName, parameters, options) { + return tslib.__awaiter(this, void 0, void 0, function* () { + const poller = yield this.beginValidateAtTenantScope(deploymentName, parameters, options); + return poller.pollUntilDone(); + }); + } + /** + * Returns changes that will be made by the deployment if executed at the scope of the tenant group. + * @param deploymentName The name of the deployment. + * @param parameters Parameters to validate. + * @param options The options parameters. + */ + beginWhatIfAtTenantScope(deploymentName, parameters, options) { + return tslib.__awaiter(this, void 0, void 0, function* () { + const directSendOperation = (args, spec) => tslib.__awaiter(this, void 0, void 0, function* () { + return this.client.sendOperationRequest(args, spec); + }); + const sendOperationFn = (args, spec) => tslib.__awaiter(this, void 0, void 0, function* () { + var _a; + let currentRawResponse = undefined; + const providedCallback = (_a = args.options) === null || _a === void 0 ? void 0 : _a.onResponse; + const callback = (rawResponse, flatResponse) => { + currentRawResponse = rawResponse; + providedCallback === null || providedCallback === void 0 ? void 0 : providedCallback(rawResponse, flatResponse); + }; + const updatedArgs = Object.assign(Object.assign({}, args), { options: Object.assign(Object.assign({}, args.options), { onResponse: callback }) }); + const flatResponse = yield directSendOperation(updatedArgs, spec); + return { + flatResponse, + rawResponse: { + statusCode: currentRawResponse.status, + body: currentRawResponse.parsedBody, + headers: currentRawResponse.headers.toJSON() + } + }; + }); + const lro = createLroSpec({ + sendOperationFn, + args: { deploymentName, parameters, options }, + spec: whatIfAtTenantScopeOperationSpec + }); + const poller = yield coreLro.createHttpPoller(lro, { + restoreFrom: options === null || options === void 0 ? void 0 : options.resumeFrom, + intervalInMs: options === null || options === void 0 ? void 0 : options.updateIntervalInMs, + resourceLocationConfig: "location" + }); + yield poller.poll(); + return poller; + }); + } + /** + * Returns changes that will be made by the deployment if executed at the scope of the tenant group. + * @param deploymentName The name of the deployment. + * @param parameters Parameters to validate. + * @param options The options parameters. + */ + beginWhatIfAtTenantScopeAndWait(deploymentName, parameters, options) { + return tslib.__awaiter(this, void 0, void 0, function* () { + const poller = yield this.beginWhatIfAtTenantScope(deploymentName, parameters, options); + return poller.pollUntilDone(); + }); + } + /** + * Exports the template used for specified deployment. + * @param deploymentName The name of the deployment. + * @param options The options parameters. + */ + exportTemplateAtTenantScope(deploymentName, options) { + return this.client.sendOperationRequest({ deploymentName, options }, exportTemplateAtTenantScopeOperationSpec); + } + /** + * Get all the deployments at the tenant scope. + * @param options The options parameters. + */ + _listAtTenantScope(options) { + return this.client.sendOperationRequest({ options }, listAtTenantScopeOperationSpec$2); + } + /** + * A template deployment that is currently running cannot be deleted. Deleting a template deployment + * removes the associated deployment operations. This is an asynchronous operation that returns a + * status of 202 until the template deployment is successfully deleted. The Location response header + * contains the URI that is used to obtain the status of the process. While the process is running, a + * call to the URI in the Location header returns a status of 202. When the process finishes, the URI + * in the Location header returns a status of 204 on success. If the asynchronous request failed, the + * URI in the Location header returns an error-level status code. + * @param groupId The management group ID. + * @param deploymentName The name of the deployment. + * @param options The options parameters. + */ + beginDeleteAtManagementGroupScope(groupId, deploymentName, options) { + return tslib.__awaiter(this, void 0, void 0, function* () { + const directSendOperation = (args, spec) => tslib.__awaiter(this, void 0, void 0, function* () { + return this.client.sendOperationRequest(args, spec); + }); + const sendOperationFn = (args, spec) => tslib.__awaiter(this, void 0, void 0, function* () { + var _a; + let currentRawResponse = undefined; + const providedCallback = (_a = args.options) === null || _a === void 0 ? void 0 : _a.onResponse; + const callback = (rawResponse, flatResponse) => { + currentRawResponse = rawResponse; + providedCallback === null || providedCallback === void 0 ? void 0 : providedCallback(rawResponse, flatResponse); + }; + const updatedArgs = Object.assign(Object.assign({}, args), { options: Object.assign(Object.assign({}, args.options), { onResponse: callback }) }); + const flatResponse = yield directSendOperation(updatedArgs, spec); + return { + flatResponse, + rawResponse: { + statusCode: currentRawResponse.status, + body: currentRawResponse.parsedBody, + headers: currentRawResponse.headers.toJSON() + } + }; + }); + const lro = createLroSpec({ + sendOperationFn, + args: { groupId, deploymentName, options }, + spec: deleteAtManagementGroupScopeOperationSpec + }); + const poller = yield coreLro.createHttpPoller(lro, { + restoreFrom: options === null || options === void 0 ? void 0 : options.resumeFrom, + intervalInMs: options === null || options === void 0 ? void 0 : options.updateIntervalInMs + }); + yield poller.poll(); + return poller; + }); + } + /** + * A template deployment that is currently running cannot be deleted. Deleting a template deployment + * removes the associated deployment operations. This is an asynchronous operation that returns a + * status of 202 until the template deployment is successfully deleted. The Location response header + * contains the URI that is used to obtain the status of the process. While the process is running, a + * call to the URI in the Location header returns a status of 202. When the process finishes, the URI + * in the Location header returns a status of 204 on success. If the asynchronous request failed, the + * URI in the Location header returns an error-level status code. + * @param groupId The management group ID. + * @param deploymentName The name of the deployment. + * @param options The options parameters. + */ + beginDeleteAtManagementGroupScopeAndWait(groupId, deploymentName, options) { + return tslib.__awaiter(this, void 0, void 0, function* () { + const poller = yield this.beginDeleteAtManagementGroupScope(groupId, deploymentName, options); + return poller.pollUntilDone(); + }); + } + /** + * Checks whether the deployment exists. + * @param groupId The management group ID. + * @param deploymentName The name of the deployment. + * @param options The options parameters. + */ + checkExistenceAtManagementGroupScope(groupId, deploymentName, options) { + return this.client.sendOperationRequest({ groupId, deploymentName, options }, checkExistenceAtManagementGroupScopeOperationSpec); + } + /** + * You can provide the template and parameters directly in the request or link to JSON files. + * @param groupId The management group ID. + * @param deploymentName The name of the deployment. + * @param parameters Additional parameters supplied to the operation. + * @param options The options parameters. + */ + beginCreateOrUpdateAtManagementGroupScope(groupId, deploymentName, parameters, options) { + return tslib.__awaiter(this, void 0, void 0, function* () { + const directSendOperation = (args, spec) => tslib.__awaiter(this, void 0, void 0, function* () { + return this.client.sendOperationRequest(args, spec); + }); + const sendOperationFn = (args, spec) => tslib.__awaiter(this, void 0, void 0, function* () { + var _a; + let currentRawResponse = undefined; + const providedCallback = (_a = args.options) === null || _a === void 0 ? void 0 : _a.onResponse; + const callback = (rawResponse, flatResponse) => { + currentRawResponse = rawResponse; + providedCallback === null || providedCallback === void 0 ? void 0 : providedCallback(rawResponse, flatResponse); + }; + const updatedArgs = Object.assign(Object.assign({}, args), { options: Object.assign(Object.assign({}, args.options), { onResponse: callback }) }); + const flatResponse = yield directSendOperation(updatedArgs, spec); + return { + flatResponse, + rawResponse: { + statusCode: currentRawResponse.status, + body: currentRawResponse.parsedBody, + headers: currentRawResponse.headers.toJSON() + } + }; + }); + const lro = createLroSpec({ + sendOperationFn, + args: { groupId, deploymentName, parameters, options }, + spec: createOrUpdateAtManagementGroupScopeOperationSpec + }); + const poller = yield coreLro.createHttpPoller(lro, { + restoreFrom: options === null || options === void 0 ? void 0 : options.resumeFrom, + intervalInMs: options === null || options === void 0 ? void 0 : options.updateIntervalInMs + }); + yield poller.poll(); + return poller; + }); + } + /** + * You can provide the template and parameters directly in the request or link to JSON files. + * @param groupId The management group ID. + * @param deploymentName The name of the deployment. + * @param parameters Additional parameters supplied to the operation. + * @param options The options parameters. + */ + beginCreateOrUpdateAtManagementGroupScopeAndWait(groupId, deploymentName, parameters, options) { + return tslib.__awaiter(this, void 0, void 0, function* () { + const poller = yield this.beginCreateOrUpdateAtManagementGroupScope(groupId, deploymentName, parameters, options); + return poller.pollUntilDone(); + }); + } + /** + * Gets a deployment. + * @param groupId The management group ID. + * @param deploymentName The name of the deployment. + * @param options The options parameters. + */ + getAtManagementGroupScope(groupId, deploymentName, options) { + return this.client.sendOperationRequest({ groupId, deploymentName, options }, getAtManagementGroupScopeOperationSpec$1); + } + /** + * You can cancel a deployment only if the provisioningState is Accepted or Running. After the + * deployment is canceled, the provisioningState is set to Canceled. Canceling a template deployment + * stops the currently running template deployment and leaves the resources partially deployed. + * @param groupId The management group ID. + * @param deploymentName The name of the deployment. + * @param options The options parameters. + */ + cancelAtManagementGroupScope(groupId, deploymentName, options) { + return this.client.sendOperationRequest({ groupId, deploymentName, options }, cancelAtManagementGroupScopeOperationSpec); + } + /** + * Validates whether the specified template is syntactically correct and will be accepted by Azure + * Resource Manager.. + * @param groupId The management group ID. + * @param deploymentName The name of the deployment. + * @param parameters Parameters to validate. + * @param options The options parameters. + */ + beginValidateAtManagementGroupScope(groupId, deploymentName, parameters, options) { + return tslib.__awaiter(this, void 0, void 0, function* () { + const directSendOperation = (args, spec) => tslib.__awaiter(this, void 0, void 0, function* () { + return this.client.sendOperationRequest(args, spec); + }); + const sendOperationFn = (args, spec) => tslib.__awaiter(this, void 0, void 0, function* () { + var _a; + let currentRawResponse = undefined; + const providedCallback = (_a = args.options) === null || _a === void 0 ? void 0 : _a.onResponse; + const callback = (rawResponse, flatResponse) => { + currentRawResponse = rawResponse; + providedCallback === null || providedCallback === void 0 ? void 0 : providedCallback(rawResponse, flatResponse); + }; + const updatedArgs = Object.assign(Object.assign({}, args), { options: Object.assign(Object.assign({}, args.options), { onResponse: callback }) }); + const flatResponse = yield directSendOperation(updatedArgs, spec); + return { + flatResponse, + rawResponse: { + statusCode: currentRawResponse.status, + body: currentRawResponse.parsedBody, + headers: currentRawResponse.headers.toJSON() + } + }; + }); + const lro = createLroSpec({ + sendOperationFn, + args: { groupId, deploymentName, parameters, options }, + spec: validateAtManagementGroupScopeOperationSpec + }); + const poller = yield coreLro.createHttpPoller(lro, { + restoreFrom: options === null || options === void 0 ? void 0 : options.resumeFrom, + intervalInMs: options === null || options === void 0 ? void 0 : options.updateIntervalInMs + }); + yield poller.poll(); + return poller; + }); + } + /** + * Validates whether the specified template is syntactically correct and will be accepted by Azure + * Resource Manager.. + * @param groupId The management group ID. + * @param deploymentName The name of the deployment. + * @param parameters Parameters to validate. + * @param options The options parameters. + */ + beginValidateAtManagementGroupScopeAndWait(groupId, deploymentName, parameters, options) { + return tslib.__awaiter(this, void 0, void 0, function* () { + const poller = yield this.beginValidateAtManagementGroupScope(groupId, deploymentName, parameters, options); + return poller.pollUntilDone(); + }); + } + /** + * Returns changes that will be made by the deployment if executed at the scope of the management + * group. + * @param groupId The management group ID. + * @param deploymentName The name of the deployment. + * @param parameters Parameters to validate. + * @param options The options parameters. + */ + beginWhatIfAtManagementGroupScope(groupId, deploymentName, parameters, options) { + return tslib.__awaiter(this, void 0, void 0, function* () { + const directSendOperation = (args, spec) => tslib.__awaiter(this, void 0, void 0, function* () { + return this.client.sendOperationRequest(args, spec); + }); + const sendOperationFn = (args, spec) => tslib.__awaiter(this, void 0, void 0, function* () { + var _a; + let currentRawResponse = undefined; + const providedCallback = (_a = args.options) === null || _a === void 0 ? void 0 : _a.onResponse; + const callback = (rawResponse, flatResponse) => { + currentRawResponse = rawResponse; + providedCallback === null || providedCallback === void 0 ? void 0 : providedCallback(rawResponse, flatResponse); + }; + const updatedArgs = Object.assign(Object.assign({}, args), { options: Object.assign(Object.assign({}, args.options), { onResponse: callback }) }); + const flatResponse = yield directSendOperation(updatedArgs, spec); + return { + flatResponse, + rawResponse: { + statusCode: currentRawResponse.status, + body: currentRawResponse.parsedBody, + headers: currentRawResponse.headers.toJSON() + } + }; + }); + const lro = createLroSpec({ + sendOperationFn, + args: { groupId, deploymentName, parameters, options }, + spec: whatIfAtManagementGroupScopeOperationSpec + }); + const poller = yield coreLro.createHttpPoller(lro, { + restoreFrom: options === null || options === void 0 ? void 0 : options.resumeFrom, + intervalInMs: options === null || options === void 0 ? void 0 : options.updateIntervalInMs, + resourceLocationConfig: "location" + }); + yield poller.poll(); + return poller; + }); + } + /** + * Returns changes that will be made by the deployment if executed at the scope of the management + * group. + * @param groupId The management group ID. + * @param deploymentName The name of the deployment. + * @param parameters Parameters to validate. + * @param options The options parameters. + */ + beginWhatIfAtManagementGroupScopeAndWait(groupId, deploymentName, parameters, options) { + return tslib.__awaiter(this, void 0, void 0, function* () { + const poller = yield this.beginWhatIfAtManagementGroupScope(groupId, deploymentName, parameters, options); + return poller.pollUntilDone(); + }); + } + /** + * Exports the template used for specified deployment. + * @param groupId The management group ID. + * @param deploymentName The name of the deployment. + * @param options The options parameters. + */ + exportTemplateAtManagementGroupScope(groupId, deploymentName, options) { + return this.client.sendOperationRequest({ groupId, deploymentName, options }, exportTemplateAtManagementGroupScopeOperationSpec); + } + /** + * Get all the deployments for a management group. + * @param groupId The management group ID. + * @param options The options parameters. + */ + _listAtManagementGroupScope(groupId, options) { + return this.client.sendOperationRequest({ groupId, options }, listAtManagementGroupScopeOperationSpec$1); + } + /** + * A template deployment that is currently running cannot be deleted. Deleting a template deployment + * removes the associated deployment operations. This is an asynchronous operation that returns a + * status of 202 until the template deployment is successfully deleted. The Location response header + * contains the URI that is used to obtain the status of the process. While the process is running, a + * call to the URI in the Location header returns a status of 202. When the process finishes, the URI + * in the Location header returns a status of 204 on success. If the asynchronous request failed, the + * URI in the Location header returns an error-level status code. + * @param deploymentName The name of the deployment. + * @param options The options parameters. + */ + beginDeleteAtSubscriptionScope(deploymentName, options) { + return tslib.__awaiter(this, void 0, void 0, function* () { + const directSendOperation = (args, spec) => tslib.__awaiter(this, void 0, void 0, function* () { + return this.client.sendOperationRequest(args, spec); + }); + const sendOperationFn = (args, spec) => tslib.__awaiter(this, void 0, void 0, function* () { + var _a; + let currentRawResponse = undefined; + const providedCallback = (_a = args.options) === null || _a === void 0 ? void 0 : _a.onResponse; + const callback = (rawResponse, flatResponse) => { + currentRawResponse = rawResponse; + providedCallback === null || providedCallback === void 0 ? void 0 : providedCallback(rawResponse, flatResponse); + }; + const updatedArgs = Object.assign(Object.assign({}, args), { options: Object.assign(Object.assign({}, args.options), { onResponse: callback }) }); + const flatResponse = yield directSendOperation(updatedArgs, spec); + return { + flatResponse, + rawResponse: { + statusCode: currentRawResponse.status, + body: currentRawResponse.parsedBody, + headers: currentRawResponse.headers.toJSON() + } + }; + }); + const lro = createLroSpec({ + sendOperationFn, + args: { deploymentName, options }, + spec: deleteAtSubscriptionScopeOperationSpec + }); + const poller = yield coreLro.createHttpPoller(lro, { + restoreFrom: options === null || options === void 0 ? void 0 : options.resumeFrom, + intervalInMs: options === null || options === void 0 ? void 0 : options.updateIntervalInMs + }); + yield poller.poll(); + return poller; + }); + } + /** + * A template deployment that is currently running cannot be deleted. Deleting a template deployment + * removes the associated deployment operations. This is an asynchronous operation that returns a + * status of 202 until the template deployment is successfully deleted. The Location response header + * contains the URI that is used to obtain the status of the process. While the process is running, a + * call to the URI in the Location header returns a status of 202. When the process finishes, the URI + * in the Location header returns a status of 204 on success. If the asynchronous request failed, the + * URI in the Location header returns an error-level status code. + * @param deploymentName The name of the deployment. + * @param options The options parameters. + */ + beginDeleteAtSubscriptionScopeAndWait(deploymentName, options) { + return tslib.__awaiter(this, void 0, void 0, function* () { + const poller = yield this.beginDeleteAtSubscriptionScope(deploymentName, options); + return poller.pollUntilDone(); + }); + } + /** + * Checks whether the deployment exists. + * @param deploymentName The name of the deployment. + * @param options The options parameters. + */ + checkExistenceAtSubscriptionScope(deploymentName, options) { + return this.client.sendOperationRequest({ deploymentName, options }, checkExistenceAtSubscriptionScopeOperationSpec); + } + /** + * You can provide the template and parameters directly in the request or link to JSON files. + * @param deploymentName The name of the deployment. + * @param parameters Additional parameters supplied to the operation. + * @param options The options parameters. + */ + beginCreateOrUpdateAtSubscriptionScope(deploymentName, parameters, options) { + return tslib.__awaiter(this, void 0, void 0, function* () { + const directSendOperation = (args, spec) => tslib.__awaiter(this, void 0, void 0, function* () { + return this.client.sendOperationRequest(args, spec); + }); + const sendOperationFn = (args, spec) => tslib.__awaiter(this, void 0, void 0, function* () { + var _a; + let currentRawResponse = undefined; + const providedCallback = (_a = args.options) === null || _a === void 0 ? void 0 : _a.onResponse; + const callback = (rawResponse, flatResponse) => { + currentRawResponse = rawResponse; + providedCallback === null || providedCallback === void 0 ? void 0 : providedCallback(rawResponse, flatResponse); + }; + const updatedArgs = Object.assign(Object.assign({}, args), { options: Object.assign(Object.assign({}, args.options), { onResponse: callback }) }); + const flatResponse = yield directSendOperation(updatedArgs, spec); + return { + flatResponse, + rawResponse: { + statusCode: currentRawResponse.status, + body: currentRawResponse.parsedBody, + headers: currentRawResponse.headers.toJSON() + } + }; + }); + const lro = createLroSpec({ + sendOperationFn, + args: { deploymentName, parameters, options }, + spec: createOrUpdateAtSubscriptionScopeOperationSpec + }); + const poller = yield coreLro.createHttpPoller(lro, { + restoreFrom: options === null || options === void 0 ? void 0 : options.resumeFrom, + intervalInMs: options === null || options === void 0 ? void 0 : options.updateIntervalInMs + }); + yield poller.poll(); + return poller; + }); + } + /** + * You can provide the template and parameters directly in the request or link to JSON files. + * @param deploymentName The name of the deployment. + * @param parameters Additional parameters supplied to the operation. + * @param options The options parameters. + */ + beginCreateOrUpdateAtSubscriptionScopeAndWait(deploymentName, parameters, options) { + return tslib.__awaiter(this, void 0, void 0, function* () { + const poller = yield this.beginCreateOrUpdateAtSubscriptionScope(deploymentName, parameters, options); + return poller.pollUntilDone(); + }); + } + /** + * Gets a deployment. + * @param deploymentName The name of the deployment. + * @param options The options parameters. + */ + getAtSubscriptionScope(deploymentName, options) { + return this.client.sendOperationRequest({ deploymentName, options }, getAtSubscriptionScopeOperationSpec$1); + } + /** + * You can cancel a deployment only if the provisioningState is Accepted or Running. After the + * deployment is canceled, the provisioningState is set to Canceled. Canceling a template deployment + * stops the currently running template deployment and leaves the resources partially deployed. + * @param deploymentName The name of the deployment. + * @param options The options parameters. + */ + cancelAtSubscriptionScope(deploymentName, options) { + return this.client.sendOperationRequest({ deploymentName, options }, cancelAtSubscriptionScopeOperationSpec); + } + /** + * Validates whether the specified template is syntactically correct and will be accepted by Azure + * Resource Manager.. + * @param deploymentName The name of the deployment. + * @param parameters Parameters to validate. + * @param options The options parameters. + */ + beginValidateAtSubscriptionScope(deploymentName, parameters, options) { + return tslib.__awaiter(this, void 0, void 0, function* () { + const directSendOperation = (args, spec) => tslib.__awaiter(this, void 0, void 0, function* () { + return this.client.sendOperationRequest(args, spec); + }); + const sendOperationFn = (args, spec) => tslib.__awaiter(this, void 0, void 0, function* () { + var _a; + let currentRawResponse = undefined; + const providedCallback = (_a = args.options) === null || _a === void 0 ? void 0 : _a.onResponse; + const callback = (rawResponse, flatResponse) => { + currentRawResponse = rawResponse; + providedCallback === null || providedCallback === void 0 ? void 0 : providedCallback(rawResponse, flatResponse); + }; + const updatedArgs = Object.assign(Object.assign({}, args), { options: Object.assign(Object.assign({}, args.options), { onResponse: callback }) }); + const flatResponse = yield directSendOperation(updatedArgs, spec); + return { + flatResponse, + rawResponse: { + statusCode: currentRawResponse.status, + body: currentRawResponse.parsedBody, + headers: currentRawResponse.headers.toJSON() + } + }; + }); + const lro = createLroSpec({ + sendOperationFn, + args: { deploymentName, parameters, options }, + spec: validateAtSubscriptionScopeOperationSpec + }); + const poller = yield coreLro.createHttpPoller(lro, { + restoreFrom: options === null || options === void 0 ? void 0 : options.resumeFrom, + intervalInMs: options === null || options === void 0 ? void 0 : options.updateIntervalInMs + }); + yield poller.poll(); + return poller; + }); + } + /** + * Validates whether the specified template is syntactically correct and will be accepted by Azure + * Resource Manager.. + * @param deploymentName The name of the deployment. + * @param parameters Parameters to validate. + * @param options The options parameters. + */ + beginValidateAtSubscriptionScopeAndWait(deploymentName, parameters, options) { + return tslib.__awaiter(this, void 0, void 0, function* () { + const poller = yield this.beginValidateAtSubscriptionScope(deploymentName, parameters, options); + return poller.pollUntilDone(); + }); + } + /** + * Returns changes that will be made by the deployment if executed at the scope of the subscription. + * @param deploymentName The name of the deployment. + * @param parameters Parameters to What If. + * @param options The options parameters. + */ + beginWhatIfAtSubscriptionScope(deploymentName, parameters, options) { + return tslib.__awaiter(this, void 0, void 0, function* () { + const directSendOperation = (args, spec) => tslib.__awaiter(this, void 0, void 0, function* () { + return this.client.sendOperationRequest(args, spec); + }); + const sendOperationFn = (args, spec) => tslib.__awaiter(this, void 0, void 0, function* () { + var _a; + let currentRawResponse = undefined; + const providedCallback = (_a = args.options) === null || _a === void 0 ? void 0 : _a.onResponse; + const callback = (rawResponse, flatResponse) => { + currentRawResponse = rawResponse; + providedCallback === null || providedCallback === void 0 ? void 0 : providedCallback(rawResponse, flatResponse); + }; + const updatedArgs = Object.assign(Object.assign({}, args), { options: Object.assign(Object.assign({}, args.options), { onResponse: callback }) }); + const flatResponse = yield directSendOperation(updatedArgs, spec); + return { + flatResponse, + rawResponse: { + statusCode: currentRawResponse.status, + body: currentRawResponse.parsedBody, + headers: currentRawResponse.headers.toJSON() + } + }; + }); + const lro = createLroSpec({ + sendOperationFn, + args: { deploymentName, parameters, options }, + spec: whatIfAtSubscriptionScopeOperationSpec + }); + const poller = yield coreLro.createHttpPoller(lro, { + restoreFrom: options === null || options === void 0 ? void 0 : options.resumeFrom, + intervalInMs: options === null || options === void 0 ? void 0 : options.updateIntervalInMs, + resourceLocationConfig: "location" + }); + yield poller.poll(); + return poller; + }); + } + /** + * Returns changes that will be made by the deployment if executed at the scope of the subscription. + * @param deploymentName The name of the deployment. + * @param parameters Parameters to What If. + * @param options The options parameters. + */ + beginWhatIfAtSubscriptionScopeAndWait(deploymentName, parameters, options) { + return tslib.__awaiter(this, void 0, void 0, function* () { + const poller = yield this.beginWhatIfAtSubscriptionScope(deploymentName, parameters, options); + return poller.pollUntilDone(); + }); + } + /** + * Exports the template used for specified deployment. + * @param deploymentName The name of the deployment. + * @param options The options parameters. + */ + exportTemplateAtSubscriptionScope(deploymentName, options) { + return this.client.sendOperationRequest({ deploymentName, options }, exportTemplateAtSubscriptionScopeOperationSpec); + } + /** + * Get all the deployments for a subscription. + * @param options The options parameters. + */ + _listAtSubscriptionScope(options) { + return this.client.sendOperationRequest({ options }, listAtSubscriptionScopeOperationSpec$1); + } + /** + * A template deployment that is currently running cannot be deleted. Deleting a template deployment + * removes the associated deployment operations. Deleting a template deployment does not affect the + * state of the resource group. This is an asynchronous operation that returns a status of 202 until + * the template deployment is successfully deleted. The Location response header contains the URI that + * is used to obtain the status of the process. While the process is running, a call to the URI in the + * Location header returns a status of 202. When the process finishes, the URI in the Location header + * returns a status of 204 on success. If the asynchronous request failed, the URI in the Location + * header returns an error-level status code. + * @param resourceGroupName The name of the resource group with the deployment to delete. The name is + * case insensitive. + * @param deploymentName The name of the deployment. + * @param options The options parameters. + */ + beginDelete(resourceGroupName, deploymentName, options) { + return tslib.__awaiter(this, void 0, void 0, function* () { + const directSendOperation = (args, spec) => tslib.__awaiter(this, void 0, void 0, function* () { + return this.client.sendOperationRequest(args, spec); + }); + const sendOperationFn = (args, spec) => tslib.__awaiter(this, void 0, void 0, function* () { + var _a; + let currentRawResponse = undefined; + const providedCallback = (_a = args.options) === null || _a === void 0 ? void 0 : _a.onResponse; + const callback = (rawResponse, flatResponse) => { + currentRawResponse = rawResponse; + providedCallback === null || providedCallback === void 0 ? void 0 : providedCallback(rawResponse, flatResponse); + }; + const updatedArgs = Object.assign(Object.assign({}, args), { options: Object.assign(Object.assign({}, args.options), { onResponse: callback }) }); + const flatResponse = yield directSendOperation(updatedArgs, spec); + return { + flatResponse, + rawResponse: { + statusCode: currentRawResponse.status, + body: currentRawResponse.parsedBody, + headers: currentRawResponse.headers.toJSON() + } + }; + }); + const lro = createLroSpec({ + sendOperationFn, + args: { resourceGroupName, deploymentName, options }, + spec: deleteOperationSpec$3 + }); + const poller = yield coreLro.createHttpPoller(lro, { + restoreFrom: options === null || options === void 0 ? void 0 : options.resumeFrom, + intervalInMs: options === null || options === void 0 ? void 0 : options.updateIntervalInMs + }); + yield poller.poll(); + return poller; + }); + } + /** + * A template deployment that is currently running cannot be deleted. Deleting a template deployment + * removes the associated deployment operations. Deleting a template deployment does not affect the + * state of the resource group. This is an asynchronous operation that returns a status of 202 until + * the template deployment is successfully deleted. The Location response header contains the URI that + * is used to obtain the status of the process. While the process is running, a call to the URI in the + * Location header returns a status of 202. When the process finishes, the URI in the Location header + * returns a status of 204 on success. If the asynchronous request failed, the URI in the Location + * header returns an error-level status code. + * @param resourceGroupName The name of the resource group with the deployment to delete. The name is + * case insensitive. + * @param deploymentName The name of the deployment. + * @param options The options parameters. + */ + beginDeleteAndWait(resourceGroupName, deploymentName, options) { + return tslib.__awaiter(this, void 0, void 0, function* () { + const poller = yield this.beginDelete(resourceGroupName, deploymentName, options); + return poller.pollUntilDone(); + }); + } + /** + * Checks whether the deployment exists. + * @param resourceGroupName The name of the resource group with the deployment to check. The name is + * case insensitive. + * @param deploymentName The name of the deployment. + * @param options The options parameters. + */ + checkExistence(resourceGroupName, deploymentName, options) { + return this.client.sendOperationRequest({ resourceGroupName, deploymentName, options }, checkExistenceOperationSpec$2); + } + /** + * You can provide the template and parameters directly in the request or link to JSON files. + * @param resourceGroupName The name of the resource group to deploy the resources to. The name is case + * insensitive. The resource group must already exist. + * @param deploymentName The name of the deployment. + * @param parameters Additional parameters supplied to the operation. + * @param options The options parameters. + */ + beginCreateOrUpdate(resourceGroupName, deploymentName, parameters, options) { + return tslib.__awaiter(this, void 0, void 0, function* () { + const directSendOperation = (args, spec) => tslib.__awaiter(this, void 0, void 0, function* () { + return this.client.sendOperationRequest(args, spec); + }); + const sendOperationFn = (args, spec) => tslib.__awaiter(this, void 0, void 0, function* () { + var _a; + let currentRawResponse = undefined; + const providedCallback = (_a = args.options) === null || _a === void 0 ? void 0 : _a.onResponse; + const callback = (rawResponse, flatResponse) => { + currentRawResponse = rawResponse; + providedCallback === null || providedCallback === void 0 ? void 0 : providedCallback(rawResponse, flatResponse); + }; + const updatedArgs = Object.assign(Object.assign({}, args), { options: Object.assign(Object.assign({}, args.options), { onResponse: callback }) }); + const flatResponse = yield directSendOperation(updatedArgs, spec); + return { + flatResponse, + rawResponse: { + statusCode: currentRawResponse.status, + body: currentRawResponse.parsedBody, + headers: currentRawResponse.headers.toJSON() + } + }; + }); + const lro = createLroSpec({ + sendOperationFn, + args: { resourceGroupName, deploymentName, parameters, options }, + spec: createOrUpdateOperationSpec$3 + }); + const poller = yield coreLro.createHttpPoller(lro, { + restoreFrom: options === null || options === void 0 ? void 0 : options.resumeFrom, + intervalInMs: options === null || options === void 0 ? void 0 : options.updateIntervalInMs + }); + yield poller.poll(); + return poller; + }); + } + /** + * You can provide the template and parameters directly in the request or link to JSON files. + * @param resourceGroupName The name of the resource group to deploy the resources to. The name is case + * insensitive. The resource group must already exist. + * @param deploymentName The name of the deployment. + * @param parameters Additional parameters supplied to the operation. + * @param options The options parameters. + */ + beginCreateOrUpdateAndWait(resourceGroupName, deploymentName, parameters, options) { + return tslib.__awaiter(this, void 0, void 0, function* () { + const poller = yield this.beginCreateOrUpdate(resourceGroupName, deploymentName, parameters, options); + return poller.pollUntilDone(); + }); + } + /** + * Gets a deployment. + * @param resourceGroupName The name of the resource group. The name is case insensitive. + * @param deploymentName The name of the deployment. + * @param options The options parameters. + */ + get(resourceGroupName, deploymentName, options) { + return this.client.sendOperationRequest({ resourceGroupName, deploymentName, options }, getOperationSpec$4); + } + /** + * You can cancel a deployment only if the provisioningState is Accepted or Running. After the + * deployment is canceled, the provisioningState is set to Canceled. Canceling a template deployment + * stops the currently running template deployment and leaves the resource group partially deployed. + * @param resourceGroupName The name of the resource group. The name is case insensitive. + * @param deploymentName The name of the deployment. + * @param options The options parameters. + */ + cancel(resourceGroupName, deploymentName, options) { + return this.client.sendOperationRequest({ resourceGroupName, deploymentName, options }, cancelOperationSpec); + } + /** + * Validates whether the specified template is syntactically correct and will be accepted by Azure + * Resource Manager.. + * @param resourceGroupName The name of the resource group the template will be deployed to. The name + * is case insensitive. + * @param deploymentName The name of the deployment. + * @param parameters Parameters to validate. + * @param options The options parameters. + */ + beginValidate(resourceGroupName, deploymentName, parameters, options) { + return tslib.__awaiter(this, void 0, void 0, function* () { + const directSendOperation = (args, spec) => tslib.__awaiter(this, void 0, void 0, function* () { + return this.client.sendOperationRequest(args, spec); + }); + const sendOperationFn = (args, spec) => tslib.__awaiter(this, void 0, void 0, function* () { + var _a; + let currentRawResponse = undefined; + const providedCallback = (_a = args.options) === null || _a === void 0 ? void 0 : _a.onResponse; + const callback = (rawResponse, flatResponse) => { + currentRawResponse = rawResponse; + providedCallback === null || providedCallback === void 0 ? void 0 : providedCallback(rawResponse, flatResponse); + }; + const updatedArgs = Object.assign(Object.assign({}, args), { options: Object.assign(Object.assign({}, args.options), { onResponse: callback }) }); + const flatResponse = yield directSendOperation(updatedArgs, spec); + return { + flatResponse, + rawResponse: { + statusCode: currentRawResponse.status, + body: currentRawResponse.parsedBody, + headers: currentRawResponse.headers.toJSON() + } + }; + }); + const lro = createLroSpec({ + sendOperationFn, + args: { resourceGroupName, deploymentName, parameters, options }, + spec: validateOperationSpec + }); + const poller = yield coreLro.createHttpPoller(lro, { + restoreFrom: options === null || options === void 0 ? void 0 : options.resumeFrom, + intervalInMs: options === null || options === void 0 ? void 0 : options.updateIntervalInMs + }); + yield poller.poll(); + return poller; + }); + } + /** + * Validates whether the specified template is syntactically correct and will be accepted by Azure + * Resource Manager.. + * @param resourceGroupName The name of the resource group the template will be deployed to. The name + * is case insensitive. + * @param deploymentName The name of the deployment. + * @param parameters Parameters to validate. + * @param options The options parameters. + */ + beginValidateAndWait(resourceGroupName, deploymentName, parameters, options) { + return tslib.__awaiter(this, void 0, void 0, function* () { + const poller = yield this.beginValidate(resourceGroupName, deploymentName, parameters, options); + return poller.pollUntilDone(); + }); + } + /** + * Returns changes that will be made by the deployment if executed at the scope of the resource group. + * @param resourceGroupName The name of the resource group the template will be deployed to. The name + * is case insensitive. + * @param deploymentName The name of the deployment. + * @param parameters Parameters to validate. + * @param options The options parameters. + */ + beginWhatIf(resourceGroupName, deploymentName, parameters, options) { + return tslib.__awaiter(this, void 0, void 0, function* () { + const directSendOperation = (args, spec) => tslib.__awaiter(this, void 0, void 0, function* () { + return this.client.sendOperationRequest(args, spec); + }); + const sendOperationFn = (args, spec) => tslib.__awaiter(this, void 0, void 0, function* () { + var _a; + let currentRawResponse = undefined; + const providedCallback = (_a = args.options) === null || _a === void 0 ? void 0 : _a.onResponse; + const callback = (rawResponse, flatResponse) => { + currentRawResponse = rawResponse; + providedCallback === null || providedCallback === void 0 ? void 0 : providedCallback(rawResponse, flatResponse); + }; + const updatedArgs = Object.assign(Object.assign({}, args), { options: Object.assign(Object.assign({}, args.options), { onResponse: callback }) }); + const flatResponse = yield directSendOperation(updatedArgs, spec); + return { + flatResponse, + rawResponse: { + statusCode: currentRawResponse.status, + body: currentRawResponse.parsedBody, + headers: currentRawResponse.headers.toJSON() + } + }; + }); + const lro = createLroSpec({ + sendOperationFn, + args: { resourceGroupName, deploymentName, parameters, options }, + spec: whatIfOperationSpec + }); + const poller = yield coreLro.createHttpPoller(lro, { + restoreFrom: options === null || options === void 0 ? void 0 : options.resumeFrom, + intervalInMs: options === null || options === void 0 ? void 0 : options.updateIntervalInMs, + resourceLocationConfig: "location" + }); + yield poller.poll(); + return poller; + }); + } + /** + * Returns changes that will be made by the deployment if executed at the scope of the resource group. + * @param resourceGroupName The name of the resource group the template will be deployed to. The name + * is case insensitive. + * @param deploymentName The name of the deployment. + * @param parameters Parameters to validate. + * @param options The options parameters. + */ + beginWhatIfAndWait(resourceGroupName, deploymentName, parameters, options) { + return tslib.__awaiter(this, void 0, void 0, function* () { + const poller = yield this.beginWhatIf(resourceGroupName, deploymentName, parameters, options); + return poller.pollUntilDone(); + }); + } + /** + * Exports the template used for specified deployment. + * @param resourceGroupName The name of the resource group. The name is case insensitive. + * @param deploymentName The name of the deployment. + * @param options The options parameters. + */ + exportTemplate(resourceGroupName, deploymentName, options) { + return this.client.sendOperationRequest({ resourceGroupName, deploymentName, options }, exportTemplateOperationSpec$1); + } + /** + * Get all the deployments for a resource group. + * @param resourceGroupName The name of the resource group with the deployments to get. The name is + * case insensitive. + * @param options The options parameters. + */ + _listByResourceGroup(resourceGroupName, options) { + return this.client.sendOperationRequest({ resourceGroupName, options }, listByResourceGroupOperationSpec$1); + } + /** + * Calculate the hash of the given template. + * @param template The template provided to calculate hash. + * @param options The options parameters. + */ + calculateTemplateHash(template, options) { + return this.client.sendOperationRequest({ template, options }, calculateTemplateHashOperationSpec); + } + /** + * ListAtScopeNext + * @param scope The resource scope. + * @param nextLink The nextLink from the previous successful call to the ListAtScope method. + * @param options The options parameters. + */ + _listAtScopeNext(scope, nextLink, options) { + return this.client.sendOperationRequest({ scope, nextLink, options }, listAtScopeNextOperationSpec$1); + } + /** + * ListAtTenantScopeNext + * @param nextLink The nextLink from the previous successful call to the ListAtTenantScope method. + * @param options The options parameters. + */ + _listAtTenantScopeNext(nextLink, options) { + return this.client.sendOperationRequest({ nextLink, options }, listAtTenantScopeNextOperationSpec$2); + } + /** + * ListAtManagementGroupScopeNext + * @param groupId The management group ID. + * @param nextLink The nextLink from the previous successful call to the ListAtManagementGroupScope + * method. + * @param options The options parameters. + */ + _listAtManagementGroupScopeNext(groupId, nextLink, options) { + return this.client.sendOperationRequest({ groupId, nextLink, options }, listAtManagementGroupScopeNextOperationSpec$1); + } + /** + * ListAtSubscriptionScopeNext + * @param nextLink The nextLink from the previous successful call to the ListAtSubscriptionScope + * method. + * @param options The options parameters. + */ + _listAtSubscriptionScopeNext(nextLink, options) { + return this.client.sendOperationRequest({ nextLink, options }, listAtSubscriptionScopeNextOperationSpec$1); + } + /** + * ListByResourceGroupNext + * @param resourceGroupName The name of the resource group with the deployments to get. The name is + * case insensitive. + * @param nextLink The nextLink from the previous successful call to the ListByResourceGroup method. + * @param options The options parameters. + */ + _listByResourceGroupNext(resourceGroupName, nextLink, options) { + return this.client.sendOperationRequest({ resourceGroupName, nextLink, options }, listByResourceGroupNextOperationSpec$1); + } +} +// Operation Specifications +const serializer$6 = coreClient__namespace.createSerializer(Mappers, /* isXml */ false); +const deleteAtScopeOperationSpec$1 = { + path: "/{scope}/providers/Microsoft.Resources/deployments/{deploymentName}", + httpMethod: "DELETE", + responses: { + 200: {}, + 201: {}, + 202: {}, + 204: {}, + default: { + bodyMapper: CloudError + } + }, + queryParameters: [apiVersion], + urlParameters: [ + $host, + scope, + deploymentName + ], + headerParameters: [accept], + serializer: serializer$6 +}; +const checkExistenceAtScopeOperationSpec = { + path: "/{scope}/providers/Microsoft.Resources/deployments/{deploymentName}", + httpMethod: "HEAD", + responses: { + 204: {}, + 404: {}, + default: { + bodyMapper: CloudError + } + }, + queryParameters: [apiVersion], + urlParameters: [ + $host, + scope, + deploymentName + ], + headerParameters: [accept], + serializer: serializer$6 +}; +const createOrUpdateAtScopeOperationSpec$1 = { + path: "/{scope}/providers/Microsoft.Resources/deployments/{deploymentName}", + httpMethod: "PUT", + responses: { + 200: { + bodyMapper: DeploymentExtended + }, + 201: { + bodyMapper: DeploymentExtended + }, + 202: { + bodyMapper: DeploymentExtended + }, + 204: { + bodyMapper: DeploymentExtended + }, + default: { + bodyMapper: CloudError + } + }, + requestBody: parameters, + queryParameters: [apiVersion], + urlParameters: [ + $host, + scope, + deploymentName + ], + headerParameters: [accept, contentType], + mediaType: "json", + serializer: serializer$6 +}; +const getAtScopeOperationSpec$2 = { + path: "/{scope}/providers/Microsoft.Resources/deployments/{deploymentName}", + httpMethod: "GET", + responses: { + 200: { + bodyMapper: DeploymentExtended + }, + default: { + bodyMapper: CloudError + } + }, + queryParameters: [apiVersion], + urlParameters: [ + $host, + scope, + deploymentName + ], + headerParameters: [accept], + serializer: serializer$6 +}; +const cancelAtScopeOperationSpec = { + path: "/{scope}/providers/Microsoft.Resources/deployments/{deploymentName}/cancel", + httpMethod: "POST", + responses: { + 204: {}, + default: { + bodyMapper: CloudError + } + }, + queryParameters: [apiVersion], + urlParameters: [ + $host, + scope, + deploymentName + ], + headerParameters: [accept], + serializer: serializer$6 +}; +const validateAtScopeOperationSpec = { + path: "/{scope}/providers/Microsoft.Resources/deployments/{deploymentName}/validate", + httpMethod: "POST", + responses: { + 200: { + bodyMapper: DeploymentValidateResult + }, + 201: { + bodyMapper: DeploymentValidateResult + }, + 202: { + bodyMapper: DeploymentValidateResult + }, + 204: { + bodyMapper: DeploymentValidateResult + }, + default: { + bodyMapper: CloudError + } + }, + requestBody: parameters, + queryParameters: [apiVersion], + urlParameters: [ + $host, + scope, + deploymentName + ], + headerParameters: [accept, contentType], + mediaType: "json", + serializer: serializer$6 +}; +const exportTemplateAtScopeOperationSpec = { + path: "/{scope}/providers/Microsoft.Resources/deployments/{deploymentName}/exportTemplate", + httpMethod: "POST", + responses: { + 200: { + bodyMapper: DeploymentExportResult + }, + default: { + bodyMapper: CloudError + } + }, + queryParameters: [apiVersion], + urlParameters: [ + $host, + scope, + deploymentName + ], + headerParameters: [accept], + serializer: serializer$6 +}; +const listAtScopeOperationSpec$1 = { + path: "/{scope}/providers/Microsoft.Resources/deployments/", + httpMethod: "GET", + responses: { + 200: { + bodyMapper: DeploymentListResult + }, + default: { + bodyMapper: CloudError + } + }, + queryParameters: [apiVersion, filter, top], + urlParameters: [$host, scope], + headerParameters: [accept], + serializer: serializer$6 +}; +const deleteAtTenantScopeOperationSpec = { + path: "/providers/Microsoft.Resources/deployments/{deploymentName}", + httpMethod: "DELETE", + responses: { + 200: {}, + 201: {}, + 202: {}, + 204: {}, + default: { + bodyMapper: CloudError + } + }, + queryParameters: [apiVersion], + urlParameters: [$host, deploymentName], + headerParameters: [accept], + serializer: serializer$6 +}; +const checkExistenceAtTenantScopeOperationSpec = { + path: "/providers/Microsoft.Resources/deployments/{deploymentName}", + httpMethod: "HEAD", + responses: { + 204: {}, + 404: {}, + default: { + bodyMapper: CloudError + } + }, + queryParameters: [apiVersion], + urlParameters: [$host, deploymentName], + headerParameters: [accept], + serializer: serializer$6 +}; +const createOrUpdateAtTenantScopeOperationSpec = { + path: "/providers/Microsoft.Resources/deployments/{deploymentName}", + httpMethod: "PUT", + responses: { + 200: { + bodyMapper: DeploymentExtended + }, + 201: { + bodyMapper: DeploymentExtended + }, + 202: { + bodyMapper: DeploymentExtended + }, + 204: { + bodyMapper: DeploymentExtended + }, + default: { + bodyMapper: CloudError + } + }, + requestBody: parameters1, + queryParameters: [apiVersion], + urlParameters: [$host, deploymentName], + headerParameters: [accept, contentType], + mediaType: "json", + serializer: serializer$6 +}; +const getAtTenantScopeOperationSpec$2 = { + path: "/providers/Microsoft.Resources/deployments/{deploymentName}", + httpMethod: "GET", + responses: { + 200: { + bodyMapper: DeploymentExtended + }, + default: { + bodyMapper: CloudError + } + }, + queryParameters: [apiVersion], + urlParameters: [$host, deploymentName], + headerParameters: [accept], + serializer: serializer$6 +}; +const cancelAtTenantScopeOperationSpec = { + path: "/providers/Microsoft.Resources/deployments/{deploymentName}/cancel", + httpMethod: "POST", + responses: { + 204: {}, + default: { + bodyMapper: CloudError + } + }, + queryParameters: [apiVersion], + urlParameters: [$host, deploymentName], + headerParameters: [accept], + serializer: serializer$6 +}; +const validateAtTenantScopeOperationSpec = { + path: "/providers/Microsoft.Resources/deployments/{deploymentName}/validate", + httpMethod: "POST", + responses: { + 200: { + bodyMapper: DeploymentValidateResult + }, + 201: { + bodyMapper: DeploymentValidateResult + }, + 202: { + bodyMapper: DeploymentValidateResult + }, + 204: { + bodyMapper: DeploymentValidateResult + }, + default: { + bodyMapper: CloudError + } + }, + requestBody: parameters1, + queryParameters: [apiVersion], + urlParameters: [$host, deploymentName], + headerParameters: [accept, contentType], + mediaType: "json", + serializer: serializer$6 +}; +const whatIfAtTenantScopeOperationSpec = { + path: "/providers/Microsoft.Resources/deployments/{deploymentName}/whatIf", + httpMethod: "POST", + responses: { + 200: { + bodyMapper: WhatIfOperationResult + }, + 201: { + bodyMapper: WhatIfOperationResult + }, + 202: { + bodyMapper: WhatIfOperationResult + }, + 204: { + bodyMapper: WhatIfOperationResult + }, + default: { + bodyMapper: CloudError + } + }, + requestBody: parameters2, + queryParameters: [apiVersion], + urlParameters: [$host, deploymentName], + headerParameters: [accept, contentType], + mediaType: "json", + serializer: serializer$6 +}; +const exportTemplateAtTenantScopeOperationSpec = { + path: "/providers/Microsoft.Resources/deployments/{deploymentName}/exportTemplate", + httpMethod: "POST", + responses: { + 200: { + bodyMapper: DeploymentExportResult + }, + default: { + bodyMapper: CloudError + } + }, + queryParameters: [apiVersion], + urlParameters: [$host, deploymentName], + headerParameters: [accept], + serializer: serializer$6 +}; +const listAtTenantScopeOperationSpec$2 = { + path: "/providers/Microsoft.Resources/deployments/", + httpMethod: "GET", + responses: { + 200: { + bodyMapper: DeploymentListResult + }, + default: { + bodyMapper: CloudError + } + }, + queryParameters: [apiVersion, filter, top], + urlParameters: [$host], + headerParameters: [accept], + serializer: serializer$6 +}; +const deleteAtManagementGroupScopeOperationSpec = { + path: "/providers/Microsoft.Management/managementGroups/{groupId}/providers/Microsoft.Resources/deployments/{deploymentName}", + httpMethod: "DELETE", + responses: { + 200: {}, + 201: {}, + 202: {}, + 204: {}, + default: { + bodyMapper: CloudError + } + }, + queryParameters: [apiVersion], + urlParameters: [ + $host, + deploymentName, + groupId + ], + headerParameters: [accept], + serializer: serializer$6 +}; +const checkExistenceAtManagementGroupScopeOperationSpec = { + path: "/providers/Microsoft.Management/managementGroups/{groupId}/providers/Microsoft.Resources/deployments/{deploymentName}", + httpMethod: "HEAD", + responses: { + 204: {}, + 404: {}, + default: { + bodyMapper: CloudError + } + }, + queryParameters: [apiVersion], + urlParameters: [ + $host, + deploymentName, + groupId + ], + headerParameters: [accept], + serializer: serializer$6 +}; +const createOrUpdateAtManagementGroupScopeOperationSpec = { + path: "/providers/Microsoft.Management/managementGroups/{groupId}/providers/Microsoft.Resources/deployments/{deploymentName}", + httpMethod: "PUT", + responses: { + 200: { + bodyMapper: DeploymentExtended + }, + 201: { + bodyMapper: DeploymentExtended + }, + 202: { + bodyMapper: DeploymentExtended + }, + 204: { + bodyMapper: DeploymentExtended + }, + default: { + bodyMapper: CloudError + } + }, + requestBody: parameters1, + queryParameters: [apiVersion], + urlParameters: [ + $host, + deploymentName, + groupId + ], + headerParameters: [accept, contentType], + mediaType: "json", + serializer: serializer$6 +}; +const getAtManagementGroupScopeOperationSpec$1 = { + path: "/providers/Microsoft.Management/managementGroups/{groupId}/providers/Microsoft.Resources/deployments/{deploymentName}", + httpMethod: "GET", + responses: { + 200: { + bodyMapper: DeploymentExtended + }, + default: { + bodyMapper: CloudError + } + }, + queryParameters: [apiVersion], + urlParameters: [ + $host, + deploymentName, + groupId + ], + headerParameters: [accept], + serializer: serializer$6 +}; +const cancelAtManagementGroupScopeOperationSpec = { + path: "/providers/Microsoft.Management/managementGroups/{groupId}/providers/Microsoft.Resources/deployments/{deploymentName}/cancel", + httpMethod: "POST", + responses: { + 204: {}, + default: { + bodyMapper: CloudError + } + }, + queryParameters: [apiVersion], + urlParameters: [ + $host, + deploymentName, + groupId + ], + headerParameters: [accept], + serializer: serializer$6 +}; +const validateAtManagementGroupScopeOperationSpec = { + path: "/providers/Microsoft.Management/managementGroups/{groupId}/providers/Microsoft.Resources/deployments/{deploymentName}/validate", + httpMethod: "POST", + responses: { + 200: { + bodyMapper: DeploymentValidateResult + }, + 201: { + bodyMapper: DeploymentValidateResult + }, + 202: { + bodyMapper: DeploymentValidateResult + }, + 204: { + bodyMapper: DeploymentValidateResult + }, + default: { + bodyMapper: CloudError + } + }, + requestBody: parameters1, + queryParameters: [apiVersion], + urlParameters: [ + $host, + deploymentName, + groupId + ], + headerParameters: [accept, contentType], + mediaType: "json", + serializer: serializer$6 +}; +const whatIfAtManagementGroupScopeOperationSpec = { + path: "/providers/Microsoft.Management/managementGroups/{groupId}/providers/Microsoft.Resources/deployments/{deploymentName}/whatIf", + httpMethod: "POST", + responses: { + 200: { + bodyMapper: WhatIfOperationResult + }, + 201: { + bodyMapper: WhatIfOperationResult + }, + 202: { + bodyMapper: WhatIfOperationResult + }, + 204: { + bodyMapper: WhatIfOperationResult + }, + default: { + bodyMapper: CloudError + } + }, + requestBody: parameters2, + queryParameters: [apiVersion], + urlParameters: [ + $host, + deploymentName, + groupId + ], + headerParameters: [accept, contentType], + mediaType: "json", + serializer: serializer$6 +}; +const exportTemplateAtManagementGroupScopeOperationSpec = { + path: "/providers/Microsoft.Management/managementGroups/{groupId}/providers/Microsoft.Resources/deployments/{deploymentName}/exportTemplate", + httpMethod: "POST", + responses: { + 200: { + bodyMapper: DeploymentExportResult + }, + default: { + bodyMapper: CloudError + } + }, + queryParameters: [apiVersion], + urlParameters: [ + $host, + deploymentName, + groupId + ], + headerParameters: [accept], + serializer: serializer$6 +}; +const listAtManagementGroupScopeOperationSpec$1 = { + path: "/providers/Microsoft.Management/managementGroups/{groupId}/providers/Microsoft.Resources/deployments/", + httpMethod: "GET", + responses: { + 200: { + bodyMapper: DeploymentListResult + }, + default: { + bodyMapper: CloudError + } + }, + queryParameters: [apiVersion, filter, top], + urlParameters: [$host, groupId], + headerParameters: [accept], + serializer: serializer$6 +}; +const deleteAtSubscriptionScopeOperationSpec = { + path: "/subscriptions/{subscriptionId}/providers/Microsoft.Resources/deployments/{deploymentName}", + httpMethod: "DELETE", + responses: { + 200: {}, + 201: {}, + 202: {}, + 204: {}, + default: { + bodyMapper: CloudError + } + }, + queryParameters: [apiVersion], + urlParameters: [ + $host, + deploymentName, + subscriptionId + ], + headerParameters: [accept], + serializer: serializer$6 +}; +const checkExistenceAtSubscriptionScopeOperationSpec = { + path: "/subscriptions/{subscriptionId}/providers/Microsoft.Resources/deployments/{deploymentName}", + httpMethod: "HEAD", + responses: { + 204: {}, + 404: {}, + default: { + bodyMapper: CloudError + } + }, + queryParameters: [apiVersion], + urlParameters: [ + $host, + deploymentName, + subscriptionId + ], + headerParameters: [accept], + serializer: serializer$6 +}; +const createOrUpdateAtSubscriptionScopeOperationSpec = { + path: "/subscriptions/{subscriptionId}/providers/Microsoft.Resources/deployments/{deploymentName}", + httpMethod: "PUT", + responses: { + 200: { + bodyMapper: DeploymentExtended + }, + 201: { + bodyMapper: DeploymentExtended + }, + 202: { + bodyMapper: DeploymentExtended + }, + 204: { + bodyMapper: DeploymentExtended + }, + default: { + bodyMapper: CloudError + } + }, + requestBody: parameters, + queryParameters: [apiVersion], + urlParameters: [ + $host, + deploymentName, + subscriptionId + ], + headerParameters: [accept, contentType], + mediaType: "json", + serializer: serializer$6 +}; +const getAtSubscriptionScopeOperationSpec$1 = { + path: "/subscriptions/{subscriptionId}/providers/Microsoft.Resources/deployments/{deploymentName}", + httpMethod: "GET", + responses: { + 200: { + bodyMapper: DeploymentExtended + }, + default: { + bodyMapper: CloudError + } + }, + queryParameters: [apiVersion], + urlParameters: [ + $host, + deploymentName, + subscriptionId + ], + headerParameters: [accept], + serializer: serializer$6 +}; +const cancelAtSubscriptionScopeOperationSpec = { + path: "/subscriptions/{subscriptionId}/providers/Microsoft.Resources/deployments/{deploymentName}/cancel", + httpMethod: "POST", + responses: { + 204: {}, + default: { + bodyMapper: CloudError + } + }, + queryParameters: [apiVersion], + urlParameters: [ + $host, + deploymentName, + subscriptionId + ], + headerParameters: [accept], + serializer: serializer$6 +}; +const validateAtSubscriptionScopeOperationSpec = { + path: "/subscriptions/{subscriptionId}/providers/Microsoft.Resources/deployments/{deploymentName}/validate", + httpMethod: "POST", + responses: { + 200: { + bodyMapper: DeploymentValidateResult + }, + 201: { + bodyMapper: DeploymentValidateResult + }, + 202: { + bodyMapper: DeploymentValidateResult + }, + 204: { + bodyMapper: DeploymentValidateResult + }, + default: { + bodyMapper: CloudError + } + }, + requestBody: parameters, + queryParameters: [apiVersion], + urlParameters: [ + $host, + deploymentName, + subscriptionId + ], + headerParameters: [accept, contentType], + mediaType: "json", + serializer: serializer$6 +}; +const whatIfAtSubscriptionScopeOperationSpec = { + path: "/subscriptions/{subscriptionId}/providers/Microsoft.Resources/deployments/{deploymentName}/whatIf", + httpMethod: "POST", + responses: { + 200: { + bodyMapper: WhatIfOperationResult + }, + 201: { + bodyMapper: WhatIfOperationResult + }, + 202: { + bodyMapper: WhatIfOperationResult + }, + 204: { + bodyMapper: WhatIfOperationResult + }, + default: { + bodyMapper: CloudError + } + }, + requestBody: parameters3, + queryParameters: [apiVersion], + urlParameters: [ + $host, + deploymentName, + subscriptionId + ], + headerParameters: [accept, contentType], + mediaType: "json", + serializer: serializer$6 +}; +const exportTemplateAtSubscriptionScopeOperationSpec = { + path: "/subscriptions/{subscriptionId}/providers/Microsoft.Resources/deployments/{deploymentName}/exportTemplate", + httpMethod: "POST", + responses: { + 200: { + bodyMapper: DeploymentExportResult + }, + default: { + bodyMapper: CloudError + } + }, + queryParameters: [apiVersion], + urlParameters: [ + $host, + deploymentName, + subscriptionId + ], + headerParameters: [accept], + serializer: serializer$6 +}; +const listAtSubscriptionScopeOperationSpec$1 = { + path: "/subscriptions/{subscriptionId}/providers/Microsoft.Resources/deployments/", + httpMethod: "GET", + responses: { + 200: { + bodyMapper: DeploymentListResult + }, + default: { + bodyMapper: CloudError + } + }, + queryParameters: [apiVersion, filter, top], + urlParameters: [$host, subscriptionId], + headerParameters: [accept], + serializer: serializer$6 +}; +const deleteOperationSpec$3 = { + path: "/subscriptions/{subscriptionId}/resourcegroups/{resourceGroupName}/providers/Microsoft.Resources/deployments/{deploymentName}", + httpMethod: "DELETE", + responses: { + 200: {}, + 201: {}, + 202: {}, + 204: {}, + default: { + bodyMapper: CloudError + } + }, + queryParameters: [apiVersion], + urlParameters: [ + $host, + deploymentName, + subscriptionId, + resourceGroupName + ], + headerParameters: [accept], + serializer: serializer$6 +}; +const checkExistenceOperationSpec$2 = { + path: "/subscriptions/{subscriptionId}/resourcegroups/{resourceGroupName}/providers/Microsoft.Resources/deployments/{deploymentName}", + httpMethod: "HEAD", + responses: { + 204: {}, + 404: {}, + default: { + bodyMapper: CloudError + } + }, + queryParameters: [apiVersion], + urlParameters: [ + $host, + deploymentName, + subscriptionId, + resourceGroupName + ], + headerParameters: [accept], + serializer: serializer$6 +}; +const createOrUpdateOperationSpec$3 = { + path: "/subscriptions/{subscriptionId}/resourcegroups/{resourceGroupName}/providers/Microsoft.Resources/deployments/{deploymentName}", + httpMethod: "PUT", + responses: { + 200: { + bodyMapper: DeploymentExtended + }, + 201: { + bodyMapper: DeploymentExtended + }, + 202: { + bodyMapper: DeploymentExtended + }, + 204: { + bodyMapper: DeploymentExtended + }, + default: { + bodyMapper: CloudError + } + }, + requestBody: parameters, + queryParameters: [apiVersion], + urlParameters: [ + $host, + deploymentName, + subscriptionId, + resourceGroupName + ], + headerParameters: [accept, contentType], + mediaType: "json", + serializer: serializer$6 +}; +const getOperationSpec$4 = { + path: "/subscriptions/{subscriptionId}/resourcegroups/{resourceGroupName}/providers/Microsoft.Resources/deployments/{deploymentName}", + httpMethod: "GET", + responses: { + 200: { + bodyMapper: DeploymentExtended + }, + default: { + bodyMapper: CloudError + } + }, + queryParameters: [apiVersion], + urlParameters: [ + $host, + deploymentName, + subscriptionId, + resourceGroupName + ], + headerParameters: [accept], + serializer: serializer$6 +}; +const cancelOperationSpec = { + path: "/subscriptions/{subscriptionId}/resourcegroups/{resourceGroupName}/providers/Microsoft.Resources/deployments/{deploymentName}/cancel", + httpMethod: "POST", + responses: { + 204: {}, + default: { + bodyMapper: CloudError + } + }, + queryParameters: [apiVersion], + urlParameters: [ + $host, + deploymentName, + subscriptionId, + resourceGroupName + ], + headerParameters: [accept], + serializer: serializer$6 +}; +const validateOperationSpec = { + path: "/subscriptions/{subscriptionId}/resourcegroups/{resourceGroupName}/providers/Microsoft.Resources/deployments/{deploymentName}/validate", + httpMethod: "POST", + responses: { + 200: { + bodyMapper: DeploymentValidateResult + }, + 201: { + bodyMapper: DeploymentValidateResult + }, + 202: { + bodyMapper: DeploymentValidateResult + }, + 204: { + bodyMapper: DeploymentValidateResult + }, + default: { + bodyMapper: CloudError + } + }, + requestBody: parameters, + queryParameters: [apiVersion], + urlParameters: [ + $host, + deploymentName, + subscriptionId, + resourceGroupName + ], + headerParameters: [accept, contentType], + mediaType: "json", + serializer: serializer$6 +}; +const whatIfOperationSpec = { + path: "/subscriptions/{subscriptionId}/resourcegroups/{resourceGroupName}/providers/Microsoft.Resources/deployments/{deploymentName}/whatIf", + httpMethod: "POST", + responses: { + 200: { + bodyMapper: WhatIfOperationResult + }, + 201: { + bodyMapper: WhatIfOperationResult + }, + 202: { + bodyMapper: WhatIfOperationResult + }, + 204: { + bodyMapper: WhatIfOperationResult + }, + default: { + bodyMapper: CloudError + } + }, + requestBody: parameters3, + queryParameters: [apiVersion], + urlParameters: [ + $host, + deploymentName, + subscriptionId, + resourceGroupName + ], + headerParameters: [accept, contentType], + mediaType: "json", + serializer: serializer$6 +}; +const exportTemplateOperationSpec$1 = { + path: "/subscriptions/{subscriptionId}/resourcegroups/{resourceGroupName}/providers/Microsoft.Resources/deployments/{deploymentName}/exportTemplate", + httpMethod: "POST", + responses: { + 200: { + bodyMapper: DeploymentExportResult + }, + default: { + bodyMapper: CloudError + } + }, + queryParameters: [apiVersion], + urlParameters: [ + $host, + deploymentName, + subscriptionId, + resourceGroupName + ], + headerParameters: [accept], + serializer: serializer$6 +}; +const listByResourceGroupOperationSpec$1 = { + path: "/subscriptions/{subscriptionId}/resourcegroups/{resourceGroupName}/providers/Microsoft.Resources/deployments/", + httpMethod: "GET", + responses: { + 200: { + bodyMapper: DeploymentListResult + }, + default: { + bodyMapper: CloudError + } + }, + queryParameters: [apiVersion, filter, top], + urlParameters: [ + $host, + subscriptionId, + resourceGroupName + ], + headerParameters: [accept], + serializer: serializer$6 +}; +const calculateTemplateHashOperationSpec = { + path: "/providers/Microsoft.Resources/calculateTemplateHash", + httpMethod: "POST", + responses: { + 200: { + bodyMapper: TemplateHashResult + }, + default: { + bodyMapper: CloudError + } + }, + requestBody: template, + queryParameters: [apiVersion], + urlParameters: [$host], + headerParameters: [accept, contentType], + mediaType: "json", + serializer: serializer$6 +}; +const listAtScopeNextOperationSpec$1 = { + path: "{nextLink}", + httpMethod: "GET", + responses: { + 200: { + bodyMapper: DeploymentListResult + }, + default: { + bodyMapper: CloudError + } + }, + urlParameters: [$host, nextLink, scope], + headerParameters: [accept], + serializer: serializer$6 +}; +const listAtTenantScopeNextOperationSpec$2 = { + path: "{nextLink}", + httpMethod: "GET", + responses: { + 200: { + bodyMapper: DeploymentListResult + }, + default: { + bodyMapper: CloudError + } + }, + urlParameters: [$host, nextLink], + headerParameters: [accept], + serializer: serializer$6 +}; +const listAtManagementGroupScopeNextOperationSpec$1 = { + path: "{nextLink}", + httpMethod: "GET", + responses: { + 200: { + bodyMapper: DeploymentListResult + }, + default: { + bodyMapper: CloudError + } + }, + urlParameters: [$host, nextLink, groupId], + headerParameters: [accept], + serializer: serializer$6 +}; +const listAtSubscriptionScopeNextOperationSpec$1 = { + path: "{nextLink}", + httpMethod: "GET", + responses: { + 200: { + bodyMapper: DeploymentListResult + }, + default: { + bodyMapper: CloudError + } + }, + urlParameters: [ + $host, + nextLink, + subscriptionId + ], + headerParameters: [accept], + serializer: serializer$6 +}; +const listByResourceGroupNextOperationSpec$1 = { + path: "{nextLink}", + httpMethod: "GET", + responses: { + 200: { + bodyMapper: DeploymentListResult + }, + default: { + bodyMapper: CloudError + } + }, + urlParameters: [ + $host, + nextLink, + subscriptionId, + resourceGroupName + ], + headerParameters: [accept], + serializer: serializer$6 +}; + +/* + * Copyright (c) Microsoft Corporation. + * Licensed under the MIT License. + * + * Code generated by Microsoft (R) AutoRest Code Generator. + * Changes may cause incorrect behavior and will be lost if the code is regenerated. + */ +/// +/** Class containing Providers operations. */ +class ProvidersImpl { + /** + * Initialize a new instance of the class Providers class. + * @param client Reference to the service client + */ + constructor(client) { + this.client = client; + } + /** + * Gets all resource providers for a subscription. + * @param options The options parameters. + */ + list(options) { + const iter = this.listPagingAll(options); + return { + next() { + return iter.next(); + }, + [Symbol.asyncIterator]() { + return this; + }, + byPage: (settings) => { + if (settings === null || settings === void 0 ? void 0 : settings.maxPageSize) { + throw new Error("maxPageSize is not supported by this operation."); + } + return this.listPagingPage(options, settings); + } + }; + } + listPagingPage(options, settings) { + return tslib.__asyncGenerator(this, arguments, function* listPagingPage_1() { + let result; + let continuationToken = settings === null || settings === void 0 ? void 0 : settings.continuationToken; + if (!continuationToken) { + result = yield tslib.__await(this._list(options)); + let page = result.value || []; + continuationToken = result.nextLink; + setContinuationToken(page, continuationToken); + yield yield tslib.__await(page); + } + while (continuationToken) { + result = yield tslib.__await(this._listNext(continuationToken, options)); + continuationToken = result.nextLink; + let page = result.value || []; + setContinuationToken(page, continuationToken); + yield yield tslib.__await(page); + } + }); + } + listPagingAll(options) { + return tslib.__asyncGenerator(this, arguments, function* listPagingAll_1() { + var e_1, _a; + try { + for (var _b = tslib.__asyncValues(this.listPagingPage(options)), _c; _c = yield tslib.__await(_b.next()), !_c.done;) { + const page = _c.value; + yield tslib.__await(yield* tslib.__asyncDelegator(tslib.__asyncValues(page))); + } + } + catch (e_1_1) { e_1 = { error: e_1_1 }; } + finally { + try { + if (_c && !_c.done && (_a = _b.return)) yield tslib.__await(_a.call(_b)); + } + finally { if (e_1) throw e_1.error; } + } + }); + } + /** + * Gets all resource providers for the tenant. + * @param options The options parameters. + */ + listAtTenantScope(options) { + const iter = this.listAtTenantScopePagingAll(options); + return { + next() { + return iter.next(); + }, + [Symbol.asyncIterator]() { + return this; + }, + byPage: (settings) => { + if (settings === null || settings === void 0 ? void 0 : settings.maxPageSize) { + throw new Error("maxPageSize is not supported by this operation."); + } + return this.listAtTenantScopePagingPage(options, settings); + } + }; + } + listAtTenantScopePagingPage(options, settings) { + return tslib.__asyncGenerator(this, arguments, function* listAtTenantScopePagingPage_1() { + let result; + let continuationToken = settings === null || settings === void 0 ? void 0 : settings.continuationToken; + if (!continuationToken) { + result = yield tslib.__await(this._listAtTenantScope(options)); + let page = result.value || []; + continuationToken = result.nextLink; + setContinuationToken(page, continuationToken); + yield yield tslib.__await(page); + } + while (continuationToken) { + result = yield tslib.__await(this._listAtTenantScopeNext(continuationToken, options)); + continuationToken = result.nextLink; + let page = result.value || []; + setContinuationToken(page, continuationToken); + yield yield tslib.__await(page); + } + }); + } + listAtTenantScopePagingAll(options) { + return tslib.__asyncGenerator(this, arguments, function* listAtTenantScopePagingAll_1() { + var e_2, _a; + try { + for (var _b = tslib.__asyncValues(this.listAtTenantScopePagingPage(options)), _c; _c = yield tslib.__await(_b.next()), !_c.done;) { + const page = _c.value; + yield tslib.__await(yield* tslib.__asyncDelegator(tslib.__asyncValues(page))); + } + } + catch (e_2_1) { e_2 = { error: e_2_1 }; } + finally { + try { + if (_c && !_c.done && (_a = _b.return)) yield tslib.__await(_a.call(_b)); + } + finally { if (e_2) throw e_2.error; } + } + }); + } + /** + * Unregisters a subscription from a resource provider. + * @param resourceProviderNamespace The namespace of the resource provider to unregister. + * @param options The options parameters. + */ + unregister(resourceProviderNamespace, options) { + return this.client.sendOperationRequest({ resourceProviderNamespace, options }, unregisterOperationSpec); + } + /** + * Registers a management group with a resource provider. + * @param resourceProviderNamespace The namespace of the resource provider to register. + * @param groupId The management group ID. + * @param options The options parameters. + */ + registerAtManagementGroupScope(resourceProviderNamespace, groupId, options) { + return this.client.sendOperationRequest({ resourceProviderNamespace, groupId, options }, registerAtManagementGroupScopeOperationSpec); + } + /** + * Get the provider permissions. + * @param resourceProviderNamespace The namespace of the resource provider. + * @param options The options parameters. + */ + providerPermissions(resourceProviderNamespace, options) { + return this.client.sendOperationRequest({ resourceProviderNamespace, options }, providerPermissionsOperationSpec); + } + /** + * Registers a subscription with a resource provider. + * @param resourceProviderNamespace The namespace of the resource provider to register. + * @param options The options parameters. + */ + register(resourceProviderNamespace, options) { + return this.client.sendOperationRequest({ resourceProviderNamespace, options }, registerOperationSpec); + } + /** + * Gets all resource providers for a subscription. + * @param options The options parameters. + */ + _list(options) { + return this.client.sendOperationRequest({ options }, listOperationSpec$5); + } + /** + * Gets all resource providers for the tenant. + * @param options The options parameters. + */ + _listAtTenantScope(options) { + return this.client.sendOperationRequest({ options }, listAtTenantScopeOperationSpec$1); + } + /** + * Gets the specified resource provider. + * @param resourceProviderNamespace The namespace of the resource provider. + * @param options The options parameters. + */ + get(resourceProviderNamespace, options) { + return this.client.sendOperationRequest({ resourceProviderNamespace, options }, getOperationSpec$3); + } + /** + * Gets the specified resource provider at the tenant level. + * @param resourceProviderNamespace The namespace of the resource provider. + * @param options The options parameters. + */ + getAtTenantScope(resourceProviderNamespace, options) { + return this.client.sendOperationRequest({ resourceProviderNamespace, options }, getAtTenantScopeOperationSpec$1); + } + /** + * ListNext + * @param nextLink The nextLink from the previous successful call to the List method. + * @param options The options parameters. + */ + _listNext(nextLink, options) { + return this.client.sendOperationRequest({ nextLink, options }, listNextOperationSpec$4); + } + /** + * ListAtTenantScopeNext + * @param nextLink The nextLink from the previous successful call to the ListAtTenantScope method. + * @param options The options parameters. + */ + _listAtTenantScopeNext(nextLink, options) { + return this.client.sendOperationRequest({ nextLink, options }, listAtTenantScopeNextOperationSpec$1); + } +} +// Operation Specifications +const serializer$5 = coreClient__namespace.createSerializer(Mappers, /* isXml */ false); +const unregisterOperationSpec = { + path: "/subscriptions/{subscriptionId}/providers/{resourceProviderNamespace}/unregister", + httpMethod: "POST", + responses: { + 200: { + bodyMapper: Provider + }, + default: { + bodyMapper: CloudError + } + }, + queryParameters: [apiVersion], + urlParameters: [ + $host, + subscriptionId, + resourceProviderNamespace + ], + headerParameters: [accept], + serializer: serializer$5 +}; +const registerAtManagementGroupScopeOperationSpec = { + path: "/providers/Microsoft.Management/managementGroups/{groupId}/providers/{resourceProviderNamespace}/register", + httpMethod: "POST", + responses: { + 200: {}, + default: { + bodyMapper: CloudError + } + }, + queryParameters: [apiVersion], + urlParameters: [ + $host, + groupId, + resourceProviderNamespace + ], + headerParameters: [accept], + serializer: serializer$5 +}; +const providerPermissionsOperationSpec = { + path: "/subscriptions/{subscriptionId}/providers/{resourceProviderNamespace}/providerPermissions", + httpMethod: "GET", + responses: { + 200: { + bodyMapper: ProviderPermissionListResult + }, + default: { + bodyMapper: CloudError + } + }, + queryParameters: [apiVersion], + urlParameters: [ + $host, + subscriptionId, + resourceProviderNamespace + ], + headerParameters: [accept], + serializer: serializer$5 +}; +const registerOperationSpec = { + path: "/subscriptions/{subscriptionId}/providers/{resourceProviderNamespace}/register", + httpMethod: "POST", + responses: { + 200: { + bodyMapper: Provider + }, + default: { + bodyMapper: CloudError + } + }, + requestBody: properties, + queryParameters: [apiVersion], + urlParameters: [ + $host, + subscriptionId, + resourceProviderNamespace + ], + headerParameters: [accept, contentType], + mediaType: "json", + serializer: serializer$5 +}; +const listOperationSpec$5 = { + path: "/subscriptions/{subscriptionId}/providers", + httpMethod: "GET", + responses: { + 200: { + bodyMapper: ProviderListResult + }, + default: { + bodyMapper: CloudError + } + }, + queryParameters: [apiVersion, expand], + urlParameters: [$host, subscriptionId], + headerParameters: [accept], + serializer: serializer$5 +}; +const listAtTenantScopeOperationSpec$1 = { + path: "/providers", + httpMethod: "GET", + responses: { + 200: { + bodyMapper: ProviderListResult + }, + default: { + bodyMapper: CloudError + } + }, + queryParameters: [apiVersion, expand], + urlParameters: [$host], + headerParameters: [accept], + serializer: serializer$5 +}; +const getOperationSpec$3 = { + path: "/subscriptions/{subscriptionId}/providers/{resourceProviderNamespace}", + httpMethod: "GET", + responses: { + 200: { + bodyMapper: Provider + }, + default: { + bodyMapper: CloudError + } + }, + queryParameters: [apiVersion, expand], + urlParameters: [ + $host, + subscriptionId, + resourceProviderNamespace + ], + headerParameters: [accept], + serializer: serializer$5 +}; +const getAtTenantScopeOperationSpec$1 = { + path: "/providers/{resourceProviderNamespace}", + httpMethod: "GET", + responses: { + 200: { + bodyMapper: Provider + }, + default: { + bodyMapper: CloudError + } + }, + queryParameters: [apiVersion, expand], + urlParameters: [$host, resourceProviderNamespace], + headerParameters: [accept], + serializer: serializer$5 +}; +const listNextOperationSpec$4 = { + path: "{nextLink}", + httpMethod: "GET", + responses: { + 200: { + bodyMapper: ProviderListResult + }, + default: { + bodyMapper: CloudError + } + }, + urlParameters: [ + $host, + nextLink, + subscriptionId + ], + headerParameters: [accept], + serializer: serializer$5 +}; +const listAtTenantScopeNextOperationSpec$1 = { + path: "{nextLink}", + httpMethod: "GET", + responses: { + 200: { + bodyMapper: ProviderListResult + }, + default: { + bodyMapper: CloudError + } + }, + urlParameters: [$host, nextLink], + headerParameters: [accept], + serializer: serializer$5 +}; + +/* + * Copyright (c) Microsoft Corporation. + * Licensed under the MIT License. + * + * Code generated by Microsoft (R) AutoRest Code Generator. + * Changes may cause incorrect behavior and will be lost if the code is regenerated. + */ +/** Class containing ProviderResourceTypes operations. */ +class ProviderResourceTypesImpl { + /** + * Initialize a new instance of the class ProviderResourceTypes class. + * @param client Reference to the service client + */ + constructor(client) { + this.client = client; + } + /** + * List the resource types for a specified resource provider. + * @param resourceProviderNamespace The namespace of the resource provider. + * @param options The options parameters. + */ + list(resourceProviderNamespace, options) { + return this.client.sendOperationRequest({ resourceProviderNamespace, options }, listOperationSpec$4); + } +} +// Operation Specifications +const serializer$4 = coreClient__namespace.createSerializer(Mappers, /* isXml */ false); +const listOperationSpec$4 = { + path: "/subscriptions/{subscriptionId}/providers/{resourceProviderNamespace}/resourceTypes", + httpMethod: "GET", + responses: { + 200: { + bodyMapper: ProviderResourceTypeListResult + }, + default: { + bodyMapper: CloudError + } + }, + queryParameters: [apiVersion, expand], + urlParameters: [ + $host, + subscriptionId, + resourceProviderNamespace + ], + headerParameters: [accept], + serializer: serializer$4 +}; + +/* + * Copyright (c) Microsoft Corporation. + * Licensed under the MIT License. + * + * Code generated by Microsoft (R) AutoRest Code Generator. + * Changes may cause incorrect behavior and will be lost if the code is regenerated. + */ +/// +/** Class containing Resources operations. */ +class ResourcesImpl { + /** + * Initialize a new instance of the class Resources class. + * @param client Reference to the service client + */ + constructor(client) { + this.client = client; + } + /** + * Get all the resources for a resource group. + * @param resourceGroupName The resource group with the resources to get. + * @param options The options parameters. + */ + listByResourceGroup(resourceGroupName, options) { + const iter = this.listByResourceGroupPagingAll(resourceGroupName, options); + return { + next() { + return iter.next(); + }, + [Symbol.asyncIterator]() { + return this; + }, + byPage: (settings) => { + if (settings === null || settings === void 0 ? void 0 : settings.maxPageSize) { + throw new Error("maxPageSize is not supported by this operation."); + } + return this.listByResourceGroupPagingPage(resourceGroupName, options, settings); + } + }; + } + listByResourceGroupPagingPage(resourceGroupName, options, settings) { + return tslib.__asyncGenerator(this, arguments, function* listByResourceGroupPagingPage_1() { + let result; + let continuationToken = settings === null || settings === void 0 ? void 0 : settings.continuationToken; + if (!continuationToken) { + result = yield tslib.__await(this._listByResourceGroup(resourceGroupName, options)); + let page = result.value || []; + continuationToken = result.nextLink; + setContinuationToken(page, continuationToken); + yield yield tslib.__await(page); + } + while (continuationToken) { + result = yield tslib.__await(this._listByResourceGroupNext(resourceGroupName, continuationToken, options)); + continuationToken = result.nextLink; + let page = result.value || []; + setContinuationToken(page, continuationToken); + yield yield tslib.__await(page); + } + }); + } + listByResourceGroupPagingAll(resourceGroupName, options) { + return tslib.__asyncGenerator(this, arguments, function* listByResourceGroupPagingAll_1() { + var e_1, _a; + try { + for (var _b = tslib.__asyncValues(this.listByResourceGroupPagingPage(resourceGroupName, options)), _c; _c = yield tslib.__await(_b.next()), !_c.done;) { + const page = _c.value; + yield tslib.__await(yield* tslib.__asyncDelegator(tslib.__asyncValues(page))); + } + } + catch (e_1_1) { e_1 = { error: e_1_1 }; } + finally { + try { + if (_c && !_c.done && (_a = _b.return)) yield tslib.__await(_a.call(_b)); + } + finally { if (e_1) throw e_1.error; } + } + }); + } + /** + * Get all the resources in a subscription. + * @param options The options parameters. + */ + list(options) { + const iter = this.listPagingAll(options); + return { + next() { + return iter.next(); + }, + [Symbol.asyncIterator]() { + return this; + }, + byPage: (settings) => { + if (settings === null || settings === void 0 ? void 0 : settings.maxPageSize) { + throw new Error("maxPageSize is not supported by this operation."); + } + return this.listPagingPage(options, settings); + } + }; + } + listPagingPage(options, settings) { + return tslib.__asyncGenerator(this, arguments, function* listPagingPage_1() { + let result; + let continuationToken = settings === null || settings === void 0 ? void 0 : settings.continuationToken; + if (!continuationToken) { + result = yield tslib.__await(this._list(options)); + let page = result.value || []; + continuationToken = result.nextLink; + setContinuationToken(page, continuationToken); + yield yield tslib.__await(page); + } + while (continuationToken) { + result = yield tslib.__await(this._listNext(continuationToken, options)); + continuationToken = result.nextLink; + let page = result.value || []; + setContinuationToken(page, continuationToken); + yield yield tslib.__await(page); + } + }); + } + listPagingAll(options) { + return tslib.__asyncGenerator(this, arguments, function* listPagingAll_1() { + var e_2, _a; + try { + for (var _b = tslib.__asyncValues(this.listPagingPage(options)), _c; _c = yield tslib.__await(_b.next()), !_c.done;) { + const page = _c.value; + yield tslib.__await(yield* tslib.__asyncDelegator(tslib.__asyncValues(page))); + } + } + catch (e_2_1) { e_2 = { error: e_2_1 }; } + finally { + try { + if (_c && !_c.done && (_a = _b.return)) yield tslib.__await(_a.call(_b)); + } + finally { if (e_2) throw e_2.error; } + } + }); + } + /** + * Get all the resources for a resource group. + * @param resourceGroupName The resource group with the resources to get. + * @param options The options parameters. + */ + _listByResourceGroup(resourceGroupName, options) { + return this.client.sendOperationRequest({ resourceGroupName, options }, listByResourceGroupOperationSpec); + } + /** + * The resources to be moved must be in the same source resource group in the source subscription being + * used. The target resource group may be in a different subscription. When moving resources, both the + * source group and the target group are locked for the duration of the operation. Write and delete + * operations are blocked on the groups until the move completes. + * @param sourceResourceGroupName The name of the resource group from the source subscription + * containing the resources to be moved. + * @param parameters Parameters for moving resources. + * @param options The options parameters. + */ + beginMoveResources(sourceResourceGroupName, parameters, options) { + return tslib.__awaiter(this, void 0, void 0, function* () { + const directSendOperation = (args, spec) => tslib.__awaiter(this, void 0, void 0, function* () { + return this.client.sendOperationRequest(args, spec); + }); + const sendOperationFn = (args, spec) => tslib.__awaiter(this, void 0, void 0, function* () { + var _a; + let currentRawResponse = undefined; + const providedCallback = (_a = args.options) === null || _a === void 0 ? void 0 : _a.onResponse; + const callback = (rawResponse, flatResponse) => { + currentRawResponse = rawResponse; + providedCallback === null || providedCallback === void 0 ? void 0 : providedCallback(rawResponse, flatResponse); + }; + const updatedArgs = Object.assign(Object.assign({}, args), { options: Object.assign(Object.assign({}, args.options), { onResponse: callback }) }); + const flatResponse = yield directSendOperation(updatedArgs, spec); + return { + flatResponse, + rawResponse: { + statusCode: currentRawResponse.status, + body: currentRawResponse.parsedBody, + headers: currentRawResponse.headers.toJSON() + } + }; + }); + const lro = createLroSpec({ + sendOperationFn, + args: { sourceResourceGroupName, parameters, options }, + spec: moveResourcesOperationSpec + }); + const poller = yield coreLro.createHttpPoller(lro, { + restoreFrom: options === null || options === void 0 ? void 0 : options.resumeFrom, + intervalInMs: options === null || options === void 0 ? void 0 : options.updateIntervalInMs + }); + yield poller.poll(); + return poller; + }); + } + /** + * The resources to be moved must be in the same source resource group in the source subscription being + * used. The target resource group may be in a different subscription. When moving resources, both the + * source group and the target group are locked for the duration of the operation. Write and delete + * operations are blocked on the groups until the move completes. + * @param sourceResourceGroupName The name of the resource group from the source subscription + * containing the resources to be moved. + * @param parameters Parameters for moving resources. + * @param options The options parameters. + */ + beginMoveResourcesAndWait(sourceResourceGroupName, parameters, options) { + return tslib.__awaiter(this, void 0, void 0, function* () { + const poller = yield this.beginMoveResources(sourceResourceGroupName, parameters, options); + return poller.pollUntilDone(); + }); + } + /** + * This operation checks whether the specified resources can be moved to the target. The resources to + * be moved must be in the same source resource group in the source subscription being used. The target + * resource group may be in a different subscription. If validation succeeds, it returns HTTP response + * code 204 (no content). If validation fails, it returns HTTP response code 409 (Conflict) with an + * error message. Retrieve the URL in the Location header value to check the result of the long-running + * operation. + * @param sourceResourceGroupName The name of the resource group from the source subscription + * containing the resources to be validated for move. + * @param parameters Parameters for moving resources. + * @param options The options parameters. + */ + beginValidateMoveResources(sourceResourceGroupName, parameters, options) { + return tslib.__awaiter(this, void 0, void 0, function* () { + const directSendOperation = (args, spec) => tslib.__awaiter(this, void 0, void 0, function* () { + return this.client.sendOperationRequest(args, spec); + }); + const sendOperationFn = (args, spec) => tslib.__awaiter(this, void 0, void 0, function* () { + var _a; + let currentRawResponse = undefined; + const providedCallback = (_a = args.options) === null || _a === void 0 ? void 0 : _a.onResponse; + const callback = (rawResponse, flatResponse) => { + currentRawResponse = rawResponse; + providedCallback === null || providedCallback === void 0 ? void 0 : providedCallback(rawResponse, flatResponse); + }; + const updatedArgs = Object.assign(Object.assign({}, args), { options: Object.assign(Object.assign({}, args.options), { onResponse: callback }) }); + const flatResponse = yield directSendOperation(updatedArgs, spec); + return { + flatResponse, + rawResponse: { + statusCode: currentRawResponse.status, + body: currentRawResponse.parsedBody, + headers: currentRawResponse.headers.toJSON() + } + }; + }); + const lro = createLroSpec({ + sendOperationFn, + args: { sourceResourceGroupName, parameters, options }, + spec: validateMoveResourcesOperationSpec + }); + const poller = yield coreLro.createHttpPoller(lro, { + restoreFrom: options === null || options === void 0 ? void 0 : options.resumeFrom, + intervalInMs: options === null || options === void 0 ? void 0 : options.updateIntervalInMs + }); + yield poller.poll(); + return poller; + }); + } + /** + * This operation checks whether the specified resources can be moved to the target. The resources to + * be moved must be in the same source resource group in the source subscription being used. The target + * resource group may be in a different subscription. If validation succeeds, it returns HTTP response + * code 204 (no content). If validation fails, it returns HTTP response code 409 (Conflict) with an + * error message. Retrieve the URL in the Location header value to check the result of the long-running + * operation. + * @param sourceResourceGroupName The name of the resource group from the source subscription + * containing the resources to be validated for move. + * @param parameters Parameters for moving resources. + * @param options The options parameters. + */ + beginValidateMoveResourcesAndWait(sourceResourceGroupName, parameters, options) { + return tslib.__awaiter(this, void 0, void 0, function* () { + const poller = yield this.beginValidateMoveResources(sourceResourceGroupName, parameters, options); + return poller.pollUntilDone(); + }); + } + /** + * Get all the resources in a subscription. + * @param options The options parameters. + */ + _list(options) { + return this.client.sendOperationRequest({ options }, listOperationSpec$3); + } + /** + * Checks whether a resource exists. + * @param resourceGroupName The name of the resource group containing the resource to check. The name + * is case insensitive. + * @param resourceProviderNamespace The resource provider of the resource to check. + * @param parentResourcePath The parent resource identity. + * @param resourceType The resource type. + * @param resourceName The name of the resource to check whether it exists. + * @param apiVersion The API version to use for the operation. + * @param options The options parameters. + */ + checkExistence(resourceGroupName, resourceProviderNamespace, parentResourcePath, resourceType, resourceName, apiVersion, options) { + return this.client.sendOperationRequest({ + resourceGroupName, + resourceProviderNamespace, + parentResourcePath, + resourceType, + resourceName, + apiVersion, + options + }, checkExistenceOperationSpec$1); + } + /** + * Deletes a resource. + * @param resourceGroupName The name of the resource group that contains the resource to delete. The + * name is case insensitive. + * @param resourceProviderNamespace The namespace of the resource provider. + * @param parentResourcePath The parent resource identity. + * @param resourceType The resource type. + * @param resourceName The name of the resource to delete. + * @param apiVersion The API version to use for the operation. + * @param options The options parameters. + */ + beginDelete(resourceGroupName, resourceProviderNamespace, parentResourcePath, resourceType, resourceName, apiVersion, options) { + return tslib.__awaiter(this, void 0, void 0, function* () { + const directSendOperation = (args, spec) => tslib.__awaiter(this, void 0, void 0, function* () { + return this.client.sendOperationRequest(args, spec); + }); + const sendOperationFn = (args, spec) => tslib.__awaiter(this, void 0, void 0, function* () { + var _a; + let currentRawResponse = undefined; + const providedCallback = (_a = args.options) === null || _a === void 0 ? void 0 : _a.onResponse; + const callback = (rawResponse, flatResponse) => { + currentRawResponse = rawResponse; + providedCallback === null || providedCallback === void 0 ? void 0 : providedCallback(rawResponse, flatResponse); + }; + const updatedArgs = Object.assign(Object.assign({}, args), { options: Object.assign(Object.assign({}, args.options), { onResponse: callback }) }); + const flatResponse = yield directSendOperation(updatedArgs, spec); + return { + flatResponse, + rawResponse: { + statusCode: currentRawResponse.status, + body: currentRawResponse.parsedBody, + headers: currentRawResponse.headers.toJSON() + } + }; + }); + const lro = createLroSpec({ + sendOperationFn, + args: { + resourceGroupName, + resourceProviderNamespace, + parentResourcePath, + resourceType, + resourceName, + apiVersion, + options + }, + spec: deleteOperationSpec$2 + }); + const poller = yield coreLro.createHttpPoller(lro, { + restoreFrom: options === null || options === void 0 ? void 0 : options.resumeFrom, + intervalInMs: options === null || options === void 0 ? void 0 : options.updateIntervalInMs + }); + yield poller.poll(); + return poller; + }); + } + /** + * Deletes a resource. + * @param resourceGroupName The name of the resource group that contains the resource to delete. The + * name is case insensitive. + * @param resourceProviderNamespace The namespace of the resource provider. + * @param parentResourcePath The parent resource identity. + * @param resourceType The resource type. + * @param resourceName The name of the resource to delete. + * @param apiVersion The API version to use for the operation. + * @param options The options parameters. + */ + beginDeleteAndWait(resourceGroupName, resourceProviderNamespace, parentResourcePath, resourceType, resourceName, apiVersion, options) { + return tslib.__awaiter(this, void 0, void 0, function* () { + const poller = yield this.beginDelete(resourceGroupName, resourceProviderNamespace, parentResourcePath, resourceType, resourceName, apiVersion, options); + return poller.pollUntilDone(); + }); + } + /** + * Creates a resource. + * @param resourceGroupName The name of the resource group for the resource. The name is case + * insensitive. + * @param resourceProviderNamespace The namespace of the resource provider. + * @param parentResourcePath The parent resource identity. + * @param resourceType The resource type of the resource to create. + * @param resourceName The name of the resource to create. + * @param apiVersion The API version to use for the operation. + * @param parameters Parameters for creating or updating the resource. + * @param options The options parameters. + */ + beginCreateOrUpdate(resourceGroupName, resourceProviderNamespace, parentResourcePath, resourceType, resourceName, apiVersion, parameters, options) { + return tslib.__awaiter(this, void 0, void 0, function* () { + const directSendOperation = (args, spec) => tslib.__awaiter(this, void 0, void 0, function* () { + return this.client.sendOperationRequest(args, spec); + }); + const sendOperationFn = (args, spec) => tslib.__awaiter(this, void 0, void 0, function* () { + var _a; + let currentRawResponse = undefined; + const providedCallback = (_a = args.options) === null || _a === void 0 ? void 0 : _a.onResponse; + const callback = (rawResponse, flatResponse) => { + currentRawResponse = rawResponse; + providedCallback === null || providedCallback === void 0 ? void 0 : providedCallback(rawResponse, flatResponse); + }; + const updatedArgs = Object.assign(Object.assign({}, args), { options: Object.assign(Object.assign({}, args.options), { onResponse: callback }) }); + const flatResponse = yield directSendOperation(updatedArgs, spec); + return { + flatResponse, + rawResponse: { + statusCode: currentRawResponse.status, + body: currentRawResponse.parsedBody, + headers: currentRawResponse.headers.toJSON() + } + }; + }); + const lro = createLroSpec({ + sendOperationFn, + args: { + resourceGroupName, + resourceProviderNamespace, + parentResourcePath, + resourceType, + resourceName, + apiVersion, + parameters, + options + }, + spec: createOrUpdateOperationSpec$2 + }); + const poller = yield coreLro.createHttpPoller(lro, { + restoreFrom: options === null || options === void 0 ? void 0 : options.resumeFrom, + intervalInMs: options === null || options === void 0 ? void 0 : options.updateIntervalInMs + }); + yield poller.poll(); + return poller; + }); + } + /** + * Creates a resource. + * @param resourceGroupName The name of the resource group for the resource. The name is case + * insensitive. + * @param resourceProviderNamespace The namespace of the resource provider. + * @param parentResourcePath The parent resource identity. + * @param resourceType The resource type of the resource to create. + * @param resourceName The name of the resource to create. + * @param apiVersion The API version to use for the operation. + * @param parameters Parameters for creating or updating the resource. + * @param options The options parameters. + */ + beginCreateOrUpdateAndWait(resourceGroupName, resourceProviderNamespace, parentResourcePath, resourceType, resourceName, apiVersion, parameters, options) { + return tslib.__awaiter(this, void 0, void 0, function* () { + const poller = yield this.beginCreateOrUpdate(resourceGroupName, resourceProviderNamespace, parentResourcePath, resourceType, resourceName, apiVersion, parameters, options); + return poller.pollUntilDone(); + }); + } + /** + * Updates a resource. + * @param resourceGroupName The name of the resource group for the resource. The name is case + * insensitive. + * @param resourceProviderNamespace The namespace of the resource provider. + * @param parentResourcePath The parent resource identity. + * @param resourceType The resource type of the resource to update. + * @param resourceName The name of the resource to update. + * @param apiVersion The API version to use for the operation. + * @param parameters Parameters for updating the resource. + * @param options The options parameters. + */ + beginUpdate(resourceGroupName, resourceProviderNamespace, parentResourcePath, resourceType, resourceName, apiVersion, parameters, options) { + return tslib.__awaiter(this, void 0, void 0, function* () { + const directSendOperation = (args, spec) => tslib.__awaiter(this, void 0, void 0, function* () { + return this.client.sendOperationRequest(args, spec); + }); + const sendOperationFn = (args, spec) => tslib.__awaiter(this, void 0, void 0, function* () { + var _a; + let currentRawResponse = undefined; + const providedCallback = (_a = args.options) === null || _a === void 0 ? void 0 : _a.onResponse; + const callback = (rawResponse, flatResponse) => { + currentRawResponse = rawResponse; + providedCallback === null || providedCallback === void 0 ? void 0 : providedCallback(rawResponse, flatResponse); + }; + const updatedArgs = Object.assign(Object.assign({}, args), { options: Object.assign(Object.assign({}, args.options), { onResponse: callback }) }); + const flatResponse = yield directSendOperation(updatedArgs, spec); + return { + flatResponse, + rawResponse: { + statusCode: currentRawResponse.status, + body: currentRawResponse.parsedBody, + headers: currentRawResponse.headers.toJSON() + } + }; + }); + const lro = createLroSpec({ + sendOperationFn, + args: { + resourceGroupName, + resourceProviderNamespace, + parentResourcePath, + resourceType, + resourceName, + apiVersion, + parameters, + options + }, + spec: updateOperationSpec$1 + }); + const poller = yield coreLro.createHttpPoller(lro, { + restoreFrom: options === null || options === void 0 ? void 0 : options.resumeFrom, + intervalInMs: options === null || options === void 0 ? void 0 : options.updateIntervalInMs + }); + yield poller.poll(); + return poller; + }); + } + /** + * Updates a resource. + * @param resourceGroupName The name of the resource group for the resource. The name is case + * insensitive. + * @param resourceProviderNamespace The namespace of the resource provider. + * @param parentResourcePath The parent resource identity. + * @param resourceType The resource type of the resource to update. + * @param resourceName The name of the resource to update. + * @param apiVersion The API version to use for the operation. + * @param parameters Parameters for updating the resource. + * @param options The options parameters. + */ + beginUpdateAndWait(resourceGroupName, resourceProviderNamespace, parentResourcePath, resourceType, resourceName, apiVersion, parameters, options) { + return tslib.__awaiter(this, void 0, void 0, function* () { + const poller = yield this.beginUpdate(resourceGroupName, resourceProviderNamespace, parentResourcePath, resourceType, resourceName, apiVersion, parameters, options); + return poller.pollUntilDone(); + }); + } + /** + * Gets a resource. + * @param resourceGroupName The name of the resource group containing the resource to get. The name is + * case insensitive. + * @param resourceProviderNamespace The namespace of the resource provider. + * @param parentResourcePath The parent resource identity. + * @param resourceType The resource type of the resource. + * @param resourceName The name of the resource to get. + * @param apiVersion The API version to use for the operation. + * @param options The options parameters. + */ + get(resourceGroupName, resourceProviderNamespace, parentResourcePath, resourceType, resourceName, apiVersion, options) { + return this.client.sendOperationRequest({ + resourceGroupName, + resourceProviderNamespace, + parentResourcePath, + resourceType, + resourceName, + apiVersion, + options + }, getOperationSpec$2); + } + /** + * Checks by ID whether a resource exists. + * @param resourceId The fully qualified ID of the resource, including the resource name and resource + * type. Use the format, + * /subscriptions/{guid}/resourceGroups/{resource-group-name}/{resource-provider-namespace}/{resource-type}/{resource-name} + * @param apiVersion The API version to use for the operation. + * @param options The options parameters. + */ + checkExistenceById(resourceId, apiVersion, options) { + return this.client.sendOperationRequest({ resourceId, apiVersion, options }, checkExistenceByIdOperationSpec); + } + /** + * Deletes a resource by ID. + * @param resourceId The fully qualified ID of the resource, including the resource name and resource + * type. Use the format, + * /subscriptions/{guid}/resourceGroups/{resource-group-name}/{resource-provider-namespace}/{resource-type}/{resource-name} + * @param apiVersion The API version to use for the operation. + * @param options The options parameters. + */ + beginDeleteById(resourceId, apiVersion, options) { + return tslib.__awaiter(this, void 0, void 0, function* () { + const directSendOperation = (args, spec) => tslib.__awaiter(this, void 0, void 0, function* () { + return this.client.sendOperationRequest(args, spec); + }); + const sendOperationFn = (args, spec) => tslib.__awaiter(this, void 0, void 0, function* () { + var _a; + let currentRawResponse = undefined; + const providedCallback = (_a = args.options) === null || _a === void 0 ? void 0 : _a.onResponse; + const callback = (rawResponse, flatResponse) => { + currentRawResponse = rawResponse; + providedCallback === null || providedCallback === void 0 ? void 0 : providedCallback(rawResponse, flatResponse); + }; + const updatedArgs = Object.assign(Object.assign({}, args), { options: Object.assign(Object.assign({}, args.options), { onResponse: callback }) }); + const flatResponse = yield directSendOperation(updatedArgs, spec); + return { + flatResponse, + rawResponse: { + statusCode: currentRawResponse.status, + body: currentRawResponse.parsedBody, + headers: currentRawResponse.headers.toJSON() + } + }; + }); + const lro = createLroSpec({ + sendOperationFn, + args: { resourceId, apiVersion, options }, + spec: deleteByIdOperationSpec + }); + const poller = yield coreLro.createHttpPoller(lro, { + restoreFrom: options === null || options === void 0 ? void 0 : options.resumeFrom, + intervalInMs: options === null || options === void 0 ? void 0 : options.updateIntervalInMs + }); + yield poller.poll(); + return poller; + }); + } + /** + * Deletes a resource by ID. + * @param resourceId The fully qualified ID of the resource, including the resource name and resource + * type. Use the format, + * /subscriptions/{guid}/resourceGroups/{resource-group-name}/{resource-provider-namespace}/{resource-type}/{resource-name} + * @param apiVersion The API version to use for the operation. + * @param options The options parameters. + */ + beginDeleteByIdAndWait(resourceId, apiVersion, options) { + return tslib.__awaiter(this, void 0, void 0, function* () { + const poller = yield this.beginDeleteById(resourceId, apiVersion, options); + return poller.pollUntilDone(); + }); + } + /** + * Create a resource by ID. + * @param resourceId The fully qualified ID of the resource, including the resource name and resource + * type. Use the format, + * /subscriptions/{guid}/resourceGroups/{resource-group-name}/{resource-provider-namespace}/{resource-type}/{resource-name} + * @param apiVersion The API version to use for the operation. + * @param parameters Create or update resource parameters. + * @param options The options parameters. + */ + beginCreateOrUpdateById(resourceId, apiVersion, parameters, options) { + return tslib.__awaiter(this, void 0, void 0, function* () { + const directSendOperation = (args, spec) => tslib.__awaiter(this, void 0, void 0, function* () { + return this.client.sendOperationRequest(args, spec); + }); + const sendOperationFn = (args, spec) => tslib.__awaiter(this, void 0, void 0, function* () { + var _a; + let currentRawResponse = undefined; + const providedCallback = (_a = args.options) === null || _a === void 0 ? void 0 : _a.onResponse; + const callback = (rawResponse, flatResponse) => { + currentRawResponse = rawResponse; + providedCallback === null || providedCallback === void 0 ? void 0 : providedCallback(rawResponse, flatResponse); + }; + const updatedArgs = Object.assign(Object.assign({}, args), { options: Object.assign(Object.assign({}, args.options), { onResponse: callback }) }); + const flatResponse = yield directSendOperation(updatedArgs, spec); + return { + flatResponse, + rawResponse: { + statusCode: currentRawResponse.status, + body: currentRawResponse.parsedBody, + headers: currentRawResponse.headers.toJSON() + } + }; + }); + const lro = createLroSpec({ + sendOperationFn, + args: { resourceId, apiVersion, parameters, options }, + spec: createOrUpdateByIdOperationSpec + }); + const poller = yield coreLro.createHttpPoller(lro, { + restoreFrom: options === null || options === void 0 ? void 0 : options.resumeFrom, + intervalInMs: options === null || options === void 0 ? void 0 : options.updateIntervalInMs + }); + yield poller.poll(); + return poller; + }); + } + /** + * Create a resource by ID. + * @param resourceId The fully qualified ID of the resource, including the resource name and resource + * type. Use the format, + * /subscriptions/{guid}/resourceGroups/{resource-group-name}/{resource-provider-namespace}/{resource-type}/{resource-name} + * @param apiVersion The API version to use for the operation. + * @param parameters Create or update resource parameters. + * @param options The options parameters. + */ + beginCreateOrUpdateByIdAndWait(resourceId, apiVersion, parameters, options) { + return tslib.__awaiter(this, void 0, void 0, function* () { + const poller = yield this.beginCreateOrUpdateById(resourceId, apiVersion, parameters, options); + return poller.pollUntilDone(); + }); + } + /** + * Updates a resource by ID. + * @param resourceId The fully qualified ID of the resource, including the resource name and resource + * type. Use the format, + * /subscriptions/{guid}/resourceGroups/{resource-group-name}/{resource-provider-namespace}/{resource-type}/{resource-name} + * @param apiVersion The API version to use for the operation. + * @param parameters Update resource parameters. + * @param options The options parameters. + */ + beginUpdateById(resourceId, apiVersion, parameters, options) { + return tslib.__awaiter(this, void 0, void 0, function* () { + const directSendOperation = (args, spec) => tslib.__awaiter(this, void 0, void 0, function* () { + return this.client.sendOperationRequest(args, spec); + }); + const sendOperationFn = (args, spec) => tslib.__awaiter(this, void 0, void 0, function* () { + var _a; + let currentRawResponse = undefined; + const providedCallback = (_a = args.options) === null || _a === void 0 ? void 0 : _a.onResponse; + const callback = (rawResponse, flatResponse) => { + currentRawResponse = rawResponse; + providedCallback === null || providedCallback === void 0 ? void 0 : providedCallback(rawResponse, flatResponse); + }; + const updatedArgs = Object.assign(Object.assign({}, args), { options: Object.assign(Object.assign({}, args.options), { onResponse: callback }) }); + const flatResponse = yield directSendOperation(updatedArgs, spec); + return { + flatResponse, + rawResponse: { + statusCode: currentRawResponse.status, + body: currentRawResponse.parsedBody, + headers: currentRawResponse.headers.toJSON() + } + }; + }); + const lro = createLroSpec({ + sendOperationFn, + args: { resourceId, apiVersion, parameters, options }, + spec: updateByIdOperationSpec + }); + const poller = yield coreLro.createHttpPoller(lro, { + restoreFrom: options === null || options === void 0 ? void 0 : options.resumeFrom, + intervalInMs: options === null || options === void 0 ? void 0 : options.updateIntervalInMs + }); + yield poller.poll(); + return poller; + }); + } + /** + * Updates a resource by ID. + * @param resourceId The fully qualified ID of the resource, including the resource name and resource + * type. Use the format, + * /subscriptions/{guid}/resourceGroups/{resource-group-name}/{resource-provider-namespace}/{resource-type}/{resource-name} + * @param apiVersion The API version to use for the operation. + * @param parameters Update resource parameters. + * @param options The options parameters. + */ + beginUpdateByIdAndWait(resourceId, apiVersion, parameters, options) { + return tslib.__awaiter(this, void 0, void 0, function* () { + const poller = yield this.beginUpdateById(resourceId, apiVersion, parameters, options); + return poller.pollUntilDone(); + }); + } + /** + * Gets a resource by ID. + * @param resourceId The fully qualified ID of the resource, including the resource name and resource + * type. Use the format, + * /subscriptions/{guid}/resourceGroups/{resource-group-name}/{resource-provider-namespace}/{resource-type}/{resource-name} + * @param apiVersion The API version to use for the operation. + * @param options The options parameters. + */ + getById(resourceId, apiVersion, options) { + return this.client.sendOperationRequest({ resourceId, apiVersion, options }, getByIdOperationSpec); + } + /** + * ListByResourceGroupNext + * @param resourceGroupName The resource group with the resources to get. + * @param nextLink The nextLink from the previous successful call to the ListByResourceGroup method. + * @param options The options parameters. + */ + _listByResourceGroupNext(resourceGroupName, nextLink, options) { + return this.client.sendOperationRequest({ resourceGroupName, nextLink, options }, listByResourceGroupNextOperationSpec); + } + /** + * ListNext + * @param nextLink The nextLink from the previous successful call to the List method. + * @param options The options parameters. + */ + _listNext(nextLink, options) { + return this.client.sendOperationRequest({ nextLink, options }, listNextOperationSpec$3); + } +} +// Operation Specifications +const serializer$3 = coreClient__namespace.createSerializer(Mappers, /* isXml */ false); +const listByResourceGroupOperationSpec = { + path: "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/resources", + httpMethod: "GET", + responses: { + 200: { + bodyMapper: ResourceListResult + }, + default: { + bodyMapper: CloudError + } + }, + queryParameters: [ + apiVersion, + filter, + top, + expand + ], + urlParameters: [ + $host, + subscriptionId, + resourceGroupName + ], + headerParameters: [accept], + serializer: serializer$3 +}; +const moveResourcesOperationSpec = { + path: "/subscriptions/{subscriptionId}/resourceGroups/{sourceResourceGroupName}/moveResources", + httpMethod: "POST", + responses: { + 200: {}, + 201: {}, + 202: {}, + 204: {}, + default: { + bodyMapper: CloudError + } + }, + requestBody: parameters4, + queryParameters: [apiVersion], + urlParameters: [ + $host, + subscriptionId, + sourceResourceGroupName + ], + headerParameters: [accept, contentType], + mediaType: "json", + serializer: serializer$3 +}; +const validateMoveResourcesOperationSpec = { + path: "/subscriptions/{subscriptionId}/resourceGroups/{sourceResourceGroupName}/validateMoveResources", + httpMethod: "POST", + responses: { + 200: {}, + 201: {}, + 202: {}, + 204: {}, + default: { + bodyMapper: CloudError + } + }, + requestBody: parameters4, + queryParameters: [apiVersion], + urlParameters: [ + $host, + subscriptionId, + sourceResourceGroupName + ], + headerParameters: [accept, contentType], + mediaType: "json", + serializer: serializer$3 +}; +const listOperationSpec$3 = { + path: "/subscriptions/{subscriptionId}/resources", + httpMethod: "GET", + responses: { + 200: { + bodyMapper: ResourceListResult + }, + default: { + bodyMapper: CloudError + } + }, + queryParameters: [ + apiVersion, + filter, + top, + expand + ], + urlParameters: [$host, subscriptionId], + headerParameters: [accept], + serializer: serializer$3 +}; +const checkExistenceOperationSpec$1 = { + path: "/subscriptions/{subscriptionId}/resourcegroups/{resourceGroupName}/providers/{resourceProviderNamespace}/{parentResourcePath}/{resourceType}/{resourceName}", + httpMethod: "HEAD", + responses: { + 204: {}, + 404: {}, + default: { + bodyMapper: CloudError + } + }, + queryParameters: [apiVersion1], + urlParameters: [ + $host, + subscriptionId, + resourceGroupName, + resourceProviderNamespace, + parentResourcePath, + resourceType, + resourceName + ], + headerParameters: [accept], + serializer: serializer$3 +}; +const deleteOperationSpec$2 = { + path: "/subscriptions/{subscriptionId}/resourcegroups/{resourceGroupName}/providers/{resourceProviderNamespace}/{parentResourcePath}/{resourceType}/{resourceName}", + httpMethod: "DELETE", + responses: { + 200: {}, + 201: {}, + 202: {}, + 204: {}, + default: { + bodyMapper: CloudError + } + }, + queryParameters: [apiVersion1], + urlParameters: [ + $host, + subscriptionId, + resourceGroupName, + resourceProviderNamespace, + parentResourcePath, + resourceType, + resourceName + ], + headerParameters: [accept], + serializer: serializer$3 +}; +const createOrUpdateOperationSpec$2 = { + path: "/subscriptions/{subscriptionId}/resourcegroups/{resourceGroupName}/providers/{resourceProviderNamespace}/{parentResourcePath}/{resourceType}/{resourceName}", + httpMethod: "PUT", + responses: { + 200: { + bodyMapper: GenericResource + }, + 201: { + bodyMapper: GenericResource + }, + 202: { + bodyMapper: GenericResource + }, + 204: { + bodyMapper: GenericResource + }, + default: { + bodyMapper: CloudError + } + }, + requestBody: parameters5, + queryParameters: [apiVersion1], + urlParameters: [ + $host, + subscriptionId, + resourceGroupName, + resourceProviderNamespace, + parentResourcePath, + resourceType, + resourceName + ], + headerParameters: [accept, contentType], + mediaType: "json", + serializer: serializer$3 +}; +const updateOperationSpec$1 = { + path: "/subscriptions/{subscriptionId}/resourcegroups/{resourceGroupName}/providers/{resourceProviderNamespace}/{parentResourcePath}/{resourceType}/{resourceName}", + httpMethod: "PATCH", + responses: { + 200: { + bodyMapper: GenericResource + }, + 201: { + bodyMapper: GenericResource + }, + 202: { + bodyMapper: GenericResource + }, + 204: { + bodyMapper: GenericResource + }, + default: { + bodyMapper: CloudError + } + }, + requestBody: parameters5, + queryParameters: [apiVersion1], + urlParameters: [ + $host, + subscriptionId, + resourceGroupName, + resourceProviderNamespace, + parentResourcePath, + resourceType, + resourceName + ], + headerParameters: [accept, contentType], + mediaType: "json", + serializer: serializer$3 +}; +const getOperationSpec$2 = { + path: "/subscriptions/{subscriptionId}/resourcegroups/{resourceGroupName}/providers/{resourceProviderNamespace}/{parentResourcePath}/{resourceType}/{resourceName}", + httpMethod: "GET", + responses: { + 200: { + bodyMapper: GenericResource + }, + default: { + bodyMapper: CloudError + } + }, + queryParameters: [apiVersion1], + urlParameters: [ + $host, + subscriptionId, + resourceGroupName, + resourceProviderNamespace, + parentResourcePath, + resourceType, + resourceName + ], + headerParameters: [accept], + serializer: serializer$3 +}; +const checkExistenceByIdOperationSpec = { + path: "/{resourceId}", + httpMethod: "HEAD", + responses: { + 204: {}, + 404: {}, + default: { + bodyMapper: CloudError + } + }, + queryParameters: [apiVersion1], + urlParameters: [$host, resourceId], + headerParameters: [accept], + serializer: serializer$3 +}; +const deleteByIdOperationSpec = { + path: "/{resourceId}", + httpMethod: "DELETE", + responses: { + 200: {}, + 201: {}, + 202: {}, + 204: {}, + default: { + bodyMapper: CloudError + } + }, + queryParameters: [apiVersion1], + urlParameters: [$host, resourceId], + headerParameters: [accept], + serializer: serializer$3 +}; +const createOrUpdateByIdOperationSpec = { + path: "/{resourceId}", + httpMethod: "PUT", + responses: { + 200: { + bodyMapper: GenericResource + }, + 201: { + bodyMapper: GenericResource + }, + 202: { + bodyMapper: GenericResource + }, + 204: { + bodyMapper: GenericResource + }, + default: { + bodyMapper: CloudError + } + }, + requestBody: parameters5, + queryParameters: [apiVersion1], + urlParameters: [$host, resourceId], + headerParameters: [accept, contentType], + mediaType: "json", + serializer: serializer$3 +}; +const updateByIdOperationSpec = { + path: "/{resourceId}", + httpMethod: "PATCH", + responses: { + 200: { + bodyMapper: GenericResource + }, + 201: { + bodyMapper: GenericResource + }, + 202: { + bodyMapper: GenericResource + }, + 204: { + bodyMapper: GenericResource + }, + default: { + bodyMapper: CloudError + } + }, + requestBody: parameters5, + queryParameters: [apiVersion1], + urlParameters: [$host, resourceId], + headerParameters: [accept, contentType], + mediaType: "json", + serializer: serializer$3 +}; +const getByIdOperationSpec = { + path: "/{resourceId}", + httpMethod: "GET", + responses: { + 200: { + bodyMapper: GenericResource + }, + default: { + bodyMapper: CloudError + } + }, + queryParameters: [apiVersion1], + urlParameters: [$host, resourceId], + headerParameters: [accept], + serializer: serializer$3 +}; +const listByResourceGroupNextOperationSpec = { + path: "{nextLink}", + httpMethod: "GET", + responses: { + 200: { + bodyMapper: ResourceListResult + }, + default: { + bodyMapper: CloudError + } + }, + urlParameters: [ + $host, + nextLink, + subscriptionId, + resourceGroupName + ], + headerParameters: [accept], + serializer: serializer$3 +}; +const listNextOperationSpec$3 = { + path: "{nextLink}", + httpMethod: "GET", + responses: { + 200: { + bodyMapper: ResourceListResult + }, + default: { + bodyMapper: CloudError + } + }, + urlParameters: [ + $host, + nextLink, + subscriptionId + ], + headerParameters: [accept], + serializer: serializer$3 +}; + +/* + * Copyright (c) Microsoft Corporation. + * Licensed under the MIT License. + * + * Code generated by Microsoft (R) AutoRest Code Generator. + * Changes may cause incorrect behavior and will be lost if the code is regenerated. + */ +/// +/** Class containing ResourceGroups operations. */ +class ResourceGroupsImpl { + /** + * Initialize a new instance of the class ResourceGroups class. + * @param client Reference to the service client + */ + constructor(client) { + this.client = client; + } + /** + * Gets all the resource groups for a subscription. + * @param options The options parameters. + */ + list(options) { + const iter = this.listPagingAll(options); + return { + next() { + return iter.next(); + }, + [Symbol.asyncIterator]() { + return this; + }, + byPage: (settings) => { + if (settings === null || settings === void 0 ? void 0 : settings.maxPageSize) { + throw new Error("maxPageSize is not supported by this operation."); + } + return this.listPagingPage(options, settings); + } + }; + } + listPagingPage(options, settings) { + return tslib.__asyncGenerator(this, arguments, function* listPagingPage_1() { + let result; + let continuationToken = settings === null || settings === void 0 ? void 0 : settings.continuationToken; + if (!continuationToken) { + result = yield tslib.__await(this._list(options)); + let page = result.value || []; + continuationToken = result.nextLink; + setContinuationToken(page, continuationToken); + yield yield tslib.__await(page); + } + while (continuationToken) { + result = yield tslib.__await(this._listNext(continuationToken, options)); + continuationToken = result.nextLink; + let page = result.value || []; + setContinuationToken(page, continuationToken); + yield yield tslib.__await(page); + } + }); + } + listPagingAll(options) { + return tslib.__asyncGenerator(this, arguments, function* listPagingAll_1() { + var e_1, _a; + try { + for (var _b = tslib.__asyncValues(this.listPagingPage(options)), _c; _c = yield tslib.__await(_b.next()), !_c.done;) { + const page = _c.value; + yield tslib.__await(yield* tslib.__asyncDelegator(tslib.__asyncValues(page))); + } + } + catch (e_1_1) { e_1 = { error: e_1_1 }; } + finally { + try { + if (_c && !_c.done && (_a = _b.return)) yield tslib.__await(_a.call(_b)); + } + finally { if (e_1) throw e_1.error; } + } + }); + } + /** + * Checks whether a resource group exists. + * @param resourceGroupName The name of the resource group to check. The name is case insensitive. + * @param options The options parameters. + */ + checkExistence(resourceGroupName, options) { + return this.client.sendOperationRequest({ resourceGroupName, options }, checkExistenceOperationSpec); + } + /** + * Creates or updates a resource group. + * @param resourceGroupName The name of the resource group to create or update. Can include + * alphanumeric, underscore, parentheses, hyphen, period (except at end), and Unicode characters that + * match the allowed characters. + * @param parameters Parameters supplied to the create or update a resource group. + * @param options The options parameters. + */ + createOrUpdate(resourceGroupName, parameters, options) { + return this.client.sendOperationRequest({ resourceGroupName, parameters, options }, createOrUpdateOperationSpec$1); + } + /** + * When you delete a resource group, all of its resources are also deleted. Deleting a resource group + * deletes all of its template deployments and currently stored operations. + * @param resourceGroupName The name of the resource group to delete. The name is case insensitive. + * @param options The options parameters. + */ + beginDelete(resourceGroupName, options) { + return tslib.__awaiter(this, void 0, void 0, function* () { + const directSendOperation = (args, spec) => tslib.__awaiter(this, void 0, void 0, function* () { + return this.client.sendOperationRequest(args, spec); + }); + const sendOperationFn = (args, spec) => tslib.__awaiter(this, void 0, void 0, function* () { + var _a; + let currentRawResponse = undefined; + const providedCallback = (_a = args.options) === null || _a === void 0 ? void 0 : _a.onResponse; + const callback = (rawResponse, flatResponse) => { + currentRawResponse = rawResponse; + providedCallback === null || providedCallback === void 0 ? void 0 : providedCallback(rawResponse, flatResponse); + }; + const updatedArgs = Object.assign(Object.assign({}, args), { options: Object.assign(Object.assign({}, args.options), { onResponse: callback }) }); + const flatResponse = yield directSendOperation(updatedArgs, spec); + return { + flatResponse, + rawResponse: { + statusCode: currentRawResponse.status, + body: currentRawResponse.parsedBody, + headers: currentRawResponse.headers.toJSON() + } + }; + }); + const lro = createLroSpec({ + sendOperationFn, + args: { resourceGroupName, options }, + spec: deleteOperationSpec$1 + }); + const poller = yield coreLro.createHttpPoller(lro, { + restoreFrom: options === null || options === void 0 ? void 0 : options.resumeFrom, + intervalInMs: options === null || options === void 0 ? void 0 : options.updateIntervalInMs + }); + yield poller.poll(); + return poller; + }); + } + /** + * When you delete a resource group, all of its resources are also deleted. Deleting a resource group + * deletes all of its template deployments and currently stored operations. + * @param resourceGroupName The name of the resource group to delete. The name is case insensitive. + * @param options The options parameters. + */ + beginDeleteAndWait(resourceGroupName, options) { + return tslib.__awaiter(this, void 0, void 0, function* () { + const poller = yield this.beginDelete(resourceGroupName, options); + return poller.pollUntilDone(); + }); + } + /** + * Gets a resource group. + * @param resourceGroupName The name of the resource group to get. The name is case insensitive. + * @param options The options parameters. + */ + get(resourceGroupName, options) { + return this.client.sendOperationRequest({ resourceGroupName, options }, getOperationSpec$1); + } + /** + * Resource groups can be updated through a simple PATCH operation to a group address. The format of + * the request is the same as that for creating a resource group. If a field is unspecified, the + * current value is retained. + * @param resourceGroupName The name of the resource group to update. The name is case insensitive. + * @param parameters Parameters supplied to update a resource group. + * @param options The options parameters. + */ + update(resourceGroupName, parameters, options) { + return this.client.sendOperationRequest({ resourceGroupName, parameters, options }, updateOperationSpec); + } + /** + * Captures the specified resource group as a template. + * @param resourceGroupName The name of the resource group. The name is case insensitive. + * @param parameters Parameters for exporting the template. + * @param options The options parameters. + */ + beginExportTemplate(resourceGroupName, parameters, options) { + return tslib.__awaiter(this, void 0, void 0, function* () { + const directSendOperation = (args, spec) => tslib.__awaiter(this, void 0, void 0, function* () { + return this.client.sendOperationRequest(args, spec); + }); + const sendOperationFn = (args, spec) => tslib.__awaiter(this, void 0, void 0, function* () { + var _a; + let currentRawResponse = undefined; + const providedCallback = (_a = args.options) === null || _a === void 0 ? void 0 : _a.onResponse; + const callback = (rawResponse, flatResponse) => { + currentRawResponse = rawResponse; + providedCallback === null || providedCallback === void 0 ? void 0 : providedCallback(rawResponse, flatResponse); + }; + const updatedArgs = Object.assign(Object.assign({}, args), { options: Object.assign(Object.assign({}, args.options), { onResponse: callback }) }); + const flatResponse = yield directSendOperation(updatedArgs, spec); + return { + flatResponse, + rawResponse: { + statusCode: currentRawResponse.status, + body: currentRawResponse.parsedBody, + headers: currentRawResponse.headers.toJSON() + } + }; + }); + const lro = createLroSpec({ + sendOperationFn, + args: { resourceGroupName, parameters, options }, + spec: exportTemplateOperationSpec + }); + const poller = yield coreLro.createHttpPoller(lro, { + restoreFrom: options === null || options === void 0 ? void 0 : options.resumeFrom, + intervalInMs: options === null || options === void 0 ? void 0 : options.updateIntervalInMs, + resourceLocationConfig: "location" + }); + yield poller.poll(); + return poller; + }); + } + /** + * Captures the specified resource group as a template. + * @param resourceGroupName The name of the resource group. The name is case insensitive. + * @param parameters Parameters for exporting the template. + * @param options The options parameters. + */ + beginExportTemplateAndWait(resourceGroupName, parameters, options) { + return tslib.__awaiter(this, void 0, void 0, function* () { + const poller = yield this.beginExportTemplate(resourceGroupName, parameters, options); + return poller.pollUntilDone(); + }); + } + /** + * Gets all the resource groups for a subscription. + * @param options The options parameters. + */ + _list(options) { + return this.client.sendOperationRequest({ options }, listOperationSpec$2); + } + /** + * ListNext + * @param nextLink The nextLink from the previous successful call to the List method. + * @param options The options parameters. + */ + _listNext(nextLink, options) { + return this.client.sendOperationRequest({ nextLink, options }, listNextOperationSpec$2); + } +} +// Operation Specifications +const serializer$2 = coreClient__namespace.createSerializer(Mappers, /* isXml */ false); +const checkExistenceOperationSpec = { + path: "/subscriptions/{subscriptionId}/resourcegroups/{resourceGroupName}", + httpMethod: "HEAD", + responses: { + 204: {}, + 404: {}, + default: { + bodyMapper: CloudError + } + }, + queryParameters: [apiVersion], + urlParameters: [ + $host, + subscriptionId, + resourceGroupName + ], + headerParameters: [accept], + serializer: serializer$2 +}; +const createOrUpdateOperationSpec$1 = { + path: "/subscriptions/{subscriptionId}/resourcegroups/{resourceGroupName}", + httpMethod: "PUT", + responses: { + 200: { + bodyMapper: ResourceGroup + }, + 201: { + bodyMapper: ResourceGroup + }, + default: { + bodyMapper: CloudError + } + }, + requestBody: parameters6, + queryParameters: [apiVersion], + urlParameters: [ + $host, + subscriptionId, + resourceGroupName + ], + headerParameters: [accept, contentType], + mediaType: "json", + serializer: serializer$2 +}; +const deleteOperationSpec$1 = { + path: "/subscriptions/{subscriptionId}/resourcegroups/{resourceGroupName}", + httpMethod: "DELETE", + responses: { + 200: {}, + 201: {}, + 202: {}, + 204: {}, + default: { + bodyMapper: CloudError + } + }, + queryParameters: [apiVersion, forceDeletionTypes], + urlParameters: [ + $host, + subscriptionId, + resourceGroupName + ], + headerParameters: [accept], + serializer: serializer$2 +}; +const getOperationSpec$1 = { + path: "/subscriptions/{subscriptionId}/resourcegroups/{resourceGroupName}", + httpMethod: "GET", + responses: { + 200: { + bodyMapper: ResourceGroup + }, + default: { + bodyMapper: CloudError + } + }, + queryParameters: [apiVersion], + urlParameters: [ + $host, + subscriptionId, + resourceGroupName + ], + headerParameters: [accept], + serializer: serializer$2 +}; +const updateOperationSpec = { + path: "/subscriptions/{subscriptionId}/resourcegroups/{resourceGroupName}", + httpMethod: "PATCH", + responses: { + 200: { + bodyMapper: ResourceGroup + }, + default: { + bodyMapper: CloudError + } + }, + requestBody: parameters7, + queryParameters: [apiVersion], + urlParameters: [ + $host, + subscriptionId, + resourceGroupName + ], + headerParameters: [accept, contentType], + mediaType: "json", + serializer: serializer$2 +}; +const exportTemplateOperationSpec = { + path: "/subscriptions/{subscriptionId}/resourcegroups/{resourceGroupName}/exportTemplate", + httpMethod: "POST", + responses: { + 200: { + bodyMapper: ResourceGroupExportResult + }, + 201: { + bodyMapper: ResourceGroupExportResult + }, + 202: { + bodyMapper: ResourceGroupExportResult + }, + 204: { + bodyMapper: ResourceGroupExportResult + }, + default: { + bodyMapper: CloudError + } + }, + requestBody: parameters8, + queryParameters: [apiVersion], + urlParameters: [ + $host, + subscriptionId, + resourceGroupName1 + ], + headerParameters: [accept, contentType], + mediaType: "json", + serializer: serializer$2 +}; +const listOperationSpec$2 = { + path: "/subscriptions/{subscriptionId}/resourcegroups", + httpMethod: "GET", + responses: { + 200: { + bodyMapper: ResourceGroupListResult + }, + default: { + bodyMapper: CloudError + } + }, + queryParameters: [apiVersion, filter, top], + urlParameters: [$host, subscriptionId], + headerParameters: [accept], + serializer: serializer$2 +}; +const listNextOperationSpec$2 = { + path: "{nextLink}", + httpMethod: "GET", + responses: { + 200: { + bodyMapper: ResourceGroupListResult + }, + default: { + bodyMapper: CloudError + } + }, + urlParameters: [ + $host, + nextLink, + subscriptionId + ], + headerParameters: [accept], + serializer: serializer$2 +}; + +/* + * Copyright (c) Microsoft Corporation. + * Licensed under the MIT License. + * + * Code generated by Microsoft (R) AutoRest Code Generator. + * Changes may cause incorrect behavior and will be lost if the code is regenerated. + */ +/// +/** Class containing TagsOperations operations. */ +class TagsOperationsImpl { + /** + * Initialize a new instance of the class TagsOperations class. + * @param client Reference to the service client + */ + constructor(client) { + this.client = client; + } + /** + * This operation performs a union of predefined tags, resource tags, resource group tags and + * subscription tags, and returns a summary of usage for each tag name and value under the given + * subscription. In case of a large number of tags, this operation may return a previously cached + * result. + * @param options The options parameters. + */ + list(options) { + const iter = this.listPagingAll(options); + return { + next() { + return iter.next(); + }, + [Symbol.asyncIterator]() { + return this; + }, + byPage: (settings) => { + if (settings === null || settings === void 0 ? void 0 : settings.maxPageSize) { + throw new Error("maxPageSize is not supported by this operation."); + } + return this.listPagingPage(options, settings); + } + }; + } + listPagingPage(options, settings) { + return tslib.__asyncGenerator(this, arguments, function* listPagingPage_1() { + let result; + let continuationToken = settings === null || settings === void 0 ? void 0 : settings.continuationToken; + if (!continuationToken) { + result = yield tslib.__await(this._list(options)); + let page = result.value || []; + continuationToken = result.nextLink; + setContinuationToken(page, continuationToken); + yield yield tslib.__await(page); + } + while (continuationToken) { + result = yield tslib.__await(this._listNext(continuationToken, options)); + continuationToken = result.nextLink; + let page = result.value || []; + setContinuationToken(page, continuationToken); + yield yield tslib.__await(page); + } + }); + } + listPagingAll(options) { + return tslib.__asyncGenerator(this, arguments, function* listPagingAll_1() { + var e_1, _a; + try { + for (var _b = tslib.__asyncValues(this.listPagingPage(options)), _c; _c = yield tslib.__await(_b.next()), !_c.done;) { + const page = _c.value; + yield tslib.__await(yield* tslib.__asyncDelegator(tslib.__asyncValues(page))); + } + } + catch (e_1_1) { e_1 = { error: e_1_1 }; } + finally { + try { + if (_c && !_c.done && (_a = _b.return)) yield tslib.__await(_a.call(_b)); + } + finally { if (e_1) throw e_1.error; } + } + }); + } + /** + * This operation allows deleting a value from the list of predefined values for an existing predefined + * tag name. The value being deleted must not be in use as a tag value for the given tag name for any + * resource. + * @param tagName The name of the tag. + * @param tagValue The value of the tag to delete. + * @param options The options parameters. + */ + deleteValue(tagName, tagValue, options) { + return this.client.sendOperationRequest({ tagName, tagValue, options }, deleteValueOperationSpec); + } + /** + * This operation allows adding a value to the list of predefined values for an existing predefined tag + * name. A tag value can have a maximum of 256 characters. + * @param tagName The name of the tag. + * @param tagValue The value of the tag to create. + * @param options The options parameters. + */ + createOrUpdateValue(tagName, tagValue, options) { + return this.client.sendOperationRequest({ tagName, tagValue, options }, createOrUpdateValueOperationSpec); + } + /** + * This operation allows adding a name to the list of predefined tag names for the given subscription. + * A tag name can have a maximum of 512 characters and is case-insensitive. Tag names cannot have the + * following prefixes which are reserved for Azure use: 'microsoft', 'azure', 'windows'. + * @param tagName The name of the tag to create. + * @param options The options parameters. + */ + createOrUpdate(tagName, options) { + return this.client.sendOperationRequest({ tagName, options }, createOrUpdateOperationSpec); + } + /** + * This operation allows deleting a name from the list of predefined tag names for the given + * subscription. The name being deleted must not be in use as a tag name for any resource. All + * predefined values for the given name must have already been deleted. + * @param tagName The name of the tag. + * @param options The options parameters. + */ + delete(tagName, options) { + return this.client.sendOperationRequest({ tagName, options }, deleteOperationSpec); + } + /** + * This operation performs a union of predefined tags, resource tags, resource group tags and + * subscription tags, and returns a summary of usage for each tag name and value under the given + * subscription. In case of a large number of tags, this operation may return a previously cached + * result. + * @param options The options parameters. + */ + _list(options) { + return this.client.sendOperationRequest({ options }, listOperationSpec$1); + } + /** + * This operation allows adding or replacing the entire set of tags on the specified resource or + * subscription. The specified entity can have a maximum of 50 tags. + * @param scope The resource scope. + * @param parameters Wrapper resource for tags API requests and responses. + * @param options The options parameters. + */ + createOrUpdateAtScope(scope, parameters, options) { + return this.client.sendOperationRequest({ scope, parameters, options }, createOrUpdateAtScopeOperationSpec); + } + /** + * This operation allows replacing, merging or selectively deleting tags on the specified resource or + * subscription. The specified entity can have a maximum of 50 tags at the end of the operation. The + * 'replace' option replaces the entire set of existing tags with a new set. The 'merge' option allows + * adding tags with new names and updating the values of tags with existing names. The 'delete' option + * allows selectively deleting tags based on given names or name/value pairs. + * @param scope The resource scope. + * @param parameters Wrapper resource for tags patch API request only. + * @param options The options parameters. + */ + updateAtScope(scope, parameters, options) { + return this.client.sendOperationRequest({ scope, parameters, options }, updateAtScopeOperationSpec); + } + /** + * Gets the entire set of tags on a resource or subscription. + * @param scope The resource scope. + * @param options The options parameters. + */ + getAtScope(scope, options) { + return this.client.sendOperationRequest({ scope, options }, getAtScopeOperationSpec$1); + } + /** + * Deletes the entire set of tags on a resource or subscription. + * @param scope The resource scope. + * @param options The options parameters. + */ + deleteAtScope(scope, options) { + return this.client.sendOperationRequest({ scope, options }, deleteAtScopeOperationSpec); + } + /** + * ListNext + * @param nextLink The nextLink from the previous successful call to the List method. + * @param options The options parameters. + */ + _listNext(nextLink, options) { + return this.client.sendOperationRequest({ nextLink, options }, listNextOperationSpec$1); + } +} +// Operation Specifications +const serializer$1 = coreClient__namespace.createSerializer(Mappers, /* isXml */ false); +const deleteValueOperationSpec = { + path: "/subscriptions/{subscriptionId}/tagNames/{tagName}/tagValues/{tagValue}", + httpMethod: "DELETE", + responses: { + 200: {}, + 204: {}, + default: { + bodyMapper: CloudError + } + }, + queryParameters: [apiVersion], + urlParameters: [ + $host, + subscriptionId, + tagName, + tagValue + ], + headerParameters: [accept], + serializer: serializer$1 +}; +const createOrUpdateValueOperationSpec = { + path: "/subscriptions/{subscriptionId}/tagNames/{tagName}/tagValues/{tagValue}", + httpMethod: "PUT", + responses: { + 200: { + bodyMapper: TagValue + }, + 201: { + bodyMapper: TagValue + }, + default: { + bodyMapper: CloudError + } + }, + queryParameters: [apiVersion], + urlParameters: [ + $host, + subscriptionId, + tagName, + tagValue + ], + headerParameters: [accept], + serializer: serializer$1 +}; +const createOrUpdateOperationSpec = { + path: "/subscriptions/{subscriptionId}/tagNames/{tagName}", + httpMethod: "PUT", + responses: { + 200: { + bodyMapper: TagDetails + }, + 201: { + bodyMapper: TagDetails + }, + default: { + bodyMapper: CloudError + } + }, + queryParameters: [apiVersion], + urlParameters: [ + $host, + subscriptionId, + tagName + ], + headerParameters: [accept], + serializer: serializer$1 +}; +const deleteOperationSpec = { + path: "/subscriptions/{subscriptionId}/tagNames/{tagName}", + httpMethod: "DELETE", + responses: { + 200: {}, + 204: {}, + default: { + bodyMapper: CloudError + } + }, + queryParameters: [apiVersion], + urlParameters: [ + $host, + subscriptionId, + tagName + ], + headerParameters: [accept], + serializer: serializer$1 +}; +const listOperationSpec$1 = { + path: "/subscriptions/{subscriptionId}/tagNames", + httpMethod: "GET", + responses: { + 200: { + bodyMapper: TagsListResult + }, + default: { + bodyMapper: CloudError + } + }, + queryParameters: [apiVersion], + urlParameters: [$host, subscriptionId], + headerParameters: [accept], + serializer: serializer$1 +}; +const createOrUpdateAtScopeOperationSpec = { + path: "/{scope}/providers/Microsoft.Resources/tags/default", + httpMethod: "PUT", + responses: { + 200: { + bodyMapper: TagsResource + }, + default: { + bodyMapper: CloudError + } + }, + requestBody: parameters9, + queryParameters: [apiVersion], + urlParameters: [$host, scope], + headerParameters: [accept, contentType], + mediaType: "json", + serializer: serializer$1 +}; +const updateAtScopeOperationSpec = { + path: "/{scope}/providers/Microsoft.Resources/tags/default", + httpMethod: "PATCH", + responses: { + 200: { + bodyMapper: TagsResource + }, + default: { + bodyMapper: CloudError + } + }, + requestBody: parameters10, + queryParameters: [apiVersion], + urlParameters: [$host, scope], + headerParameters: [accept, contentType], + mediaType: "json", + serializer: serializer$1 +}; +const getAtScopeOperationSpec$1 = { + path: "/{scope}/providers/Microsoft.Resources/tags/default", + httpMethod: "GET", + responses: { + 200: { + bodyMapper: TagsResource + }, + default: { + bodyMapper: CloudError + } + }, + queryParameters: [apiVersion], + urlParameters: [$host, scope], + headerParameters: [accept], + serializer: serializer$1 +}; +const deleteAtScopeOperationSpec = { + path: "/{scope}/providers/Microsoft.Resources/tags/default", + httpMethod: "DELETE", + responses: { + 200: {}, + default: { + bodyMapper: CloudError + } + }, + queryParameters: [apiVersion], + urlParameters: [$host, scope], + headerParameters: [accept], + serializer: serializer$1 +}; +const listNextOperationSpec$1 = { + path: "{nextLink}", + httpMethod: "GET", + responses: { + 200: { + bodyMapper: TagsListResult + }, + default: { + bodyMapper: CloudError + } + }, + urlParameters: [ + $host, + nextLink, + subscriptionId + ], + headerParameters: [accept], + serializer: serializer$1 +}; + +/* + * Copyright (c) Microsoft Corporation. + * Licensed under the MIT License. + * + * Code generated by Microsoft (R) AutoRest Code Generator. + * Changes may cause incorrect behavior and will be lost if the code is regenerated. + */ +/// +/** Class containing DeploymentOperations operations. */ +class DeploymentOperationsImpl { + /** + * Initialize a new instance of the class DeploymentOperations class. + * @param client Reference to the service client + */ + constructor(client) { + this.client = client; + } + /** + * Gets all deployments operations for a deployment. + * @param scope The resource scope. + * @param deploymentName The name of the deployment. + * @param options The options parameters. + */ + listAtScope(scope, deploymentName, options) { + const iter = this.listAtScopePagingAll(scope, deploymentName, options); + return { + next() { + return iter.next(); + }, + [Symbol.asyncIterator]() { + return this; + }, + byPage: (settings) => { + if (settings === null || settings === void 0 ? void 0 : settings.maxPageSize) { + throw new Error("maxPageSize is not supported by this operation."); + } + return this.listAtScopePagingPage(scope, deploymentName, options, settings); + } + }; + } + listAtScopePagingPage(scope, deploymentName, options, settings) { + return tslib.__asyncGenerator(this, arguments, function* listAtScopePagingPage_1() { + let result; + let continuationToken = settings === null || settings === void 0 ? void 0 : settings.continuationToken; + if (!continuationToken) { + result = yield tslib.__await(this._listAtScope(scope, deploymentName, options)); + let page = result.value || []; + continuationToken = result.nextLink; + setContinuationToken(page, continuationToken); + yield yield tslib.__await(page); + } + while (continuationToken) { + result = yield tslib.__await(this._listAtScopeNext(scope, deploymentName, continuationToken, options)); + continuationToken = result.nextLink; + let page = result.value || []; + setContinuationToken(page, continuationToken); + yield yield tslib.__await(page); + } + }); + } + listAtScopePagingAll(scope, deploymentName, options) { + return tslib.__asyncGenerator(this, arguments, function* listAtScopePagingAll_1() { + var e_1, _a; + try { + for (var _b = tslib.__asyncValues(this.listAtScopePagingPage(scope, deploymentName, options)), _c; _c = yield tslib.__await(_b.next()), !_c.done;) { + const page = _c.value; + yield tslib.__await(yield* tslib.__asyncDelegator(tslib.__asyncValues(page))); + } + } + catch (e_1_1) { e_1 = { error: e_1_1 }; } + finally { + try { + if (_c && !_c.done && (_a = _b.return)) yield tslib.__await(_a.call(_b)); + } + finally { if (e_1) throw e_1.error; } + } + }); + } + /** + * Gets all deployments operations for a deployment. + * @param deploymentName The name of the deployment. + * @param options The options parameters. + */ + listAtTenantScope(deploymentName, options) { + const iter = this.listAtTenantScopePagingAll(deploymentName, options); + return { + next() { + return iter.next(); + }, + [Symbol.asyncIterator]() { + return this; + }, + byPage: (settings) => { + if (settings === null || settings === void 0 ? void 0 : settings.maxPageSize) { + throw new Error("maxPageSize is not supported by this operation."); + } + return this.listAtTenantScopePagingPage(deploymentName, options, settings); + } + }; + } + listAtTenantScopePagingPage(deploymentName, options, settings) { + return tslib.__asyncGenerator(this, arguments, function* listAtTenantScopePagingPage_1() { + let result; + let continuationToken = settings === null || settings === void 0 ? void 0 : settings.continuationToken; + if (!continuationToken) { + result = yield tslib.__await(this._listAtTenantScope(deploymentName, options)); + let page = result.value || []; + continuationToken = result.nextLink; + setContinuationToken(page, continuationToken); + yield yield tslib.__await(page); + } + while (continuationToken) { + result = yield tslib.__await(this._listAtTenantScopeNext(deploymentName, continuationToken, options)); + continuationToken = result.nextLink; + let page = result.value || []; + setContinuationToken(page, continuationToken); + yield yield tslib.__await(page); + } + }); + } + listAtTenantScopePagingAll(deploymentName, options) { + return tslib.__asyncGenerator(this, arguments, function* listAtTenantScopePagingAll_1() { + var e_2, _a; + try { + for (var _b = tslib.__asyncValues(this.listAtTenantScopePagingPage(deploymentName, options)), _c; _c = yield tslib.__await(_b.next()), !_c.done;) { + const page = _c.value; + yield tslib.__await(yield* tslib.__asyncDelegator(tslib.__asyncValues(page))); + } + } + catch (e_2_1) { e_2 = { error: e_2_1 }; } + finally { + try { + if (_c && !_c.done && (_a = _b.return)) yield tslib.__await(_a.call(_b)); + } + finally { if (e_2) throw e_2.error; } + } + }); + } + /** + * Gets all deployments operations for a deployment. + * @param groupId The management group ID. + * @param deploymentName The name of the deployment. + * @param options The options parameters. + */ + listAtManagementGroupScope(groupId, deploymentName, options) { + const iter = this.listAtManagementGroupScopePagingAll(groupId, deploymentName, options); + return { + next() { + return iter.next(); + }, + [Symbol.asyncIterator]() { + return this; + }, + byPage: (settings) => { + if (settings === null || settings === void 0 ? void 0 : settings.maxPageSize) { + throw new Error("maxPageSize is not supported by this operation."); + } + return this.listAtManagementGroupScopePagingPage(groupId, deploymentName, options, settings); + } + }; + } + listAtManagementGroupScopePagingPage(groupId, deploymentName, options, settings) { + return tslib.__asyncGenerator(this, arguments, function* listAtManagementGroupScopePagingPage_1() { + let result; + let continuationToken = settings === null || settings === void 0 ? void 0 : settings.continuationToken; + if (!continuationToken) { + result = yield tslib.__await(this._listAtManagementGroupScope(groupId, deploymentName, options)); + let page = result.value || []; + continuationToken = result.nextLink; + setContinuationToken(page, continuationToken); + yield yield tslib.__await(page); + } + while (continuationToken) { + result = yield tslib.__await(this._listAtManagementGroupScopeNext(groupId, deploymentName, continuationToken, options)); + continuationToken = result.nextLink; + let page = result.value || []; + setContinuationToken(page, continuationToken); + yield yield tslib.__await(page); + } + }); + } + listAtManagementGroupScopePagingAll(groupId, deploymentName, options) { + return tslib.__asyncGenerator(this, arguments, function* listAtManagementGroupScopePagingAll_1() { + var e_3, _a; + try { + for (var _b = tslib.__asyncValues(this.listAtManagementGroupScopePagingPage(groupId, deploymentName, options)), _c; _c = yield tslib.__await(_b.next()), !_c.done;) { + const page = _c.value; + yield tslib.__await(yield* tslib.__asyncDelegator(tslib.__asyncValues(page))); + } + } + catch (e_3_1) { e_3 = { error: e_3_1 }; } + finally { + try { + if (_c && !_c.done && (_a = _b.return)) yield tslib.__await(_a.call(_b)); + } + finally { if (e_3) throw e_3.error; } + } + }); + } + /** + * Gets all deployments operations for a deployment. + * @param deploymentName The name of the deployment. + * @param options The options parameters. + */ + listAtSubscriptionScope(deploymentName, options) { + const iter = this.listAtSubscriptionScopePagingAll(deploymentName, options); + return { + next() { + return iter.next(); + }, + [Symbol.asyncIterator]() { + return this; + }, + byPage: (settings) => { + if (settings === null || settings === void 0 ? void 0 : settings.maxPageSize) { + throw new Error("maxPageSize is not supported by this operation."); + } + return this.listAtSubscriptionScopePagingPage(deploymentName, options, settings); + } + }; + } + listAtSubscriptionScopePagingPage(deploymentName, options, settings) { + return tslib.__asyncGenerator(this, arguments, function* listAtSubscriptionScopePagingPage_1() { + let result; + let continuationToken = settings === null || settings === void 0 ? void 0 : settings.continuationToken; + if (!continuationToken) { + result = yield tslib.__await(this._listAtSubscriptionScope(deploymentName, options)); + let page = result.value || []; + continuationToken = result.nextLink; + setContinuationToken(page, continuationToken); + yield yield tslib.__await(page); + } + while (continuationToken) { + result = yield tslib.__await(this._listAtSubscriptionScopeNext(deploymentName, continuationToken, options)); + continuationToken = result.nextLink; + let page = result.value || []; + setContinuationToken(page, continuationToken); + yield yield tslib.__await(page); + } + }); + } + listAtSubscriptionScopePagingAll(deploymentName, options) { + return tslib.__asyncGenerator(this, arguments, function* listAtSubscriptionScopePagingAll_1() { + var e_4, _a; + try { + for (var _b = tslib.__asyncValues(this.listAtSubscriptionScopePagingPage(deploymentName, options)), _c; _c = yield tslib.__await(_b.next()), !_c.done;) { + const page = _c.value; + yield tslib.__await(yield* tslib.__asyncDelegator(tslib.__asyncValues(page))); + } + } + catch (e_4_1) { e_4 = { error: e_4_1 }; } + finally { + try { + if (_c && !_c.done && (_a = _b.return)) yield tslib.__await(_a.call(_b)); + } + finally { if (e_4) throw e_4.error; } + } + }); + } + /** + * Gets all deployments operations for a deployment. + * @param resourceGroupName The name of the resource group. The name is case insensitive. + * @param deploymentName The name of the deployment. + * @param options The options parameters. + */ + list(resourceGroupName, deploymentName, options) { + const iter = this.listPagingAll(resourceGroupName, deploymentName, options); + return { + next() { + return iter.next(); + }, + [Symbol.asyncIterator]() { + return this; + }, + byPage: (settings) => { + if (settings === null || settings === void 0 ? void 0 : settings.maxPageSize) { + throw new Error("maxPageSize is not supported by this operation."); + } + return this.listPagingPage(resourceGroupName, deploymentName, options, settings); + } + }; + } + listPagingPage(resourceGroupName, deploymentName, options, settings) { + return tslib.__asyncGenerator(this, arguments, function* listPagingPage_1() { + let result; + let continuationToken = settings === null || settings === void 0 ? void 0 : settings.continuationToken; + if (!continuationToken) { + result = yield tslib.__await(this._list(resourceGroupName, deploymentName, options)); + let page = result.value || []; + continuationToken = result.nextLink; + setContinuationToken(page, continuationToken); + yield yield tslib.__await(page); + } + while (continuationToken) { + result = yield tslib.__await(this._listNext(resourceGroupName, deploymentName, continuationToken, options)); + continuationToken = result.nextLink; + let page = result.value || []; + setContinuationToken(page, continuationToken); + yield yield tslib.__await(page); + } + }); + } + listPagingAll(resourceGroupName, deploymentName, options) { + return tslib.__asyncGenerator(this, arguments, function* listPagingAll_1() { + var e_5, _a; + try { + for (var _b = tslib.__asyncValues(this.listPagingPage(resourceGroupName, deploymentName, options)), _c; _c = yield tslib.__await(_b.next()), !_c.done;) { + const page = _c.value; + yield tslib.__await(yield* tslib.__asyncDelegator(tslib.__asyncValues(page))); + } + } + catch (e_5_1) { e_5 = { error: e_5_1 }; } + finally { + try { + if (_c && !_c.done && (_a = _b.return)) yield tslib.__await(_a.call(_b)); + } + finally { if (e_5) throw e_5.error; } + } + }); + } + /** + * Gets a deployments operation. + * @param scope The resource scope. + * @param deploymentName The name of the deployment. + * @param operationId The ID of the operation to get. + * @param options The options parameters. + */ + getAtScope(scope, deploymentName, operationId, options) { + return this.client.sendOperationRequest({ scope, deploymentName, operationId, options }, getAtScopeOperationSpec); + } + /** + * Gets all deployments operations for a deployment. + * @param scope The resource scope. + * @param deploymentName The name of the deployment. + * @param options The options parameters. + */ + _listAtScope(scope, deploymentName, options) { + return this.client.sendOperationRequest({ scope, deploymentName, options }, listAtScopeOperationSpec); + } + /** + * Gets a deployments operation. + * @param deploymentName The name of the deployment. + * @param operationId The ID of the operation to get. + * @param options The options parameters. + */ + getAtTenantScope(deploymentName, operationId, options) { + return this.client.sendOperationRequest({ deploymentName, operationId, options }, getAtTenantScopeOperationSpec); + } + /** + * Gets all deployments operations for a deployment. + * @param deploymentName The name of the deployment. + * @param options The options parameters. + */ + _listAtTenantScope(deploymentName, options) { + return this.client.sendOperationRequest({ deploymentName, options }, listAtTenantScopeOperationSpec); + } + /** + * Gets a deployments operation. + * @param groupId The management group ID. + * @param deploymentName The name of the deployment. + * @param operationId The ID of the operation to get. + * @param options The options parameters. + */ + getAtManagementGroupScope(groupId, deploymentName, operationId, options) { + return this.client.sendOperationRequest({ groupId, deploymentName, operationId, options }, getAtManagementGroupScopeOperationSpec); + } + /** + * Gets all deployments operations for a deployment. + * @param groupId The management group ID. + * @param deploymentName The name of the deployment. + * @param options The options parameters. + */ + _listAtManagementGroupScope(groupId, deploymentName, options) { + return this.client.sendOperationRequest({ groupId, deploymentName, options }, listAtManagementGroupScopeOperationSpec); + } + /** + * Gets a deployments operation. + * @param deploymentName The name of the deployment. + * @param operationId The ID of the operation to get. + * @param options The options parameters. + */ + getAtSubscriptionScope(deploymentName, operationId, options) { + return this.client.sendOperationRequest({ deploymentName, operationId, options }, getAtSubscriptionScopeOperationSpec); + } + /** + * Gets all deployments operations for a deployment. + * @param deploymentName The name of the deployment. + * @param options The options parameters. + */ + _listAtSubscriptionScope(deploymentName, options) { + return this.client.sendOperationRequest({ deploymentName, options }, listAtSubscriptionScopeOperationSpec); + } + /** + * Gets a deployments operation. + * @param resourceGroupName The name of the resource group. The name is case insensitive. + * @param deploymentName The name of the deployment. + * @param operationId The ID of the operation to get. + * @param options The options parameters. + */ + get(resourceGroupName, deploymentName, operationId, options) { + return this.client.sendOperationRequest({ resourceGroupName, deploymentName, operationId, options }, getOperationSpec); + } + /** + * Gets all deployments operations for a deployment. + * @param resourceGroupName The name of the resource group. The name is case insensitive. + * @param deploymentName The name of the deployment. + * @param options The options parameters. + */ + _list(resourceGroupName, deploymentName, options) { + return this.client.sendOperationRequest({ resourceGroupName, deploymentName, options }, listOperationSpec); + } + /** + * ListAtScopeNext + * @param scope The resource scope. + * @param deploymentName The name of the deployment. + * @param nextLink The nextLink from the previous successful call to the ListAtScope method. + * @param options The options parameters. + */ + _listAtScopeNext(scope, deploymentName, nextLink, options) { + return this.client.sendOperationRequest({ scope, deploymentName, nextLink, options }, listAtScopeNextOperationSpec); + } + /** + * ListAtTenantScopeNext + * @param deploymentName The name of the deployment. + * @param nextLink The nextLink from the previous successful call to the ListAtTenantScope method. + * @param options The options parameters. + */ + _listAtTenantScopeNext(deploymentName, nextLink, options) { + return this.client.sendOperationRequest({ deploymentName, nextLink, options }, listAtTenantScopeNextOperationSpec); + } + /** + * ListAtManagementGroupScopeNext + * @param groupId The management group ID. + * @param deploymentName The name of the deployment. + * @param nextLink The nextLink from the previous successful call to the ListAtManagementGroupScope + * method. + * @param options The options parameters. + */ + _listAtManagementGroupScopeNext(groupId, deploymentName, nextLink, options) { + return this.client.sendOperationRequest({ groupId, deploymentName, nextLink, options }, listAtManagementGroupScopeNextOperationSpec); + } + /** + * ListAtSubscriptionScopeNext + * @param deploymentName The name of the deployment. + * @param nextLink The nextLink from the previous successful call to the ListAtSubscriptionScope + * method. + * @param options The options parameters. + */ + _listAtSubscriptionScopeNext(deploymentName, nextLink, options) { + return this.client.sendOperationRequest({ deploymentName, nextLink, options }, listAtSubscriptionScopeNextOperationSpec); + } + /** + * ListNext + * @param resourceGroupName The name of the resource group. The name is case insensitive. + * @param deploymentName The name of the deployment. + * @param nextLink The nextLink from the previous successful call to the List method. + * @param options The options parameters. + */ + _listNext(resourceGroupName, deploymentName, nextLink, options) { + return this.client.sendOperationRequest({ resourceGroupName, deploymentName, nextLink, options }, listNextOperationSpec); + } +} +// Operation Specifications +const serializer = coreClient__namespace.createSerializer(Mappers, /* isXml */ false); +const getAtScopeOperationSpec = { + path: "/{scope}/providers/Microsoft.Resources/deployments/{deploymentName}/operations/{operationId}", + httpMethod: "GET", + responses: { + 200: { + bodyMapper: DeploymentOperation + }, + default: { + bodyMapper: CloudError + } + }, + queryParameters: [apiVersion], + urlParameters: [ + $host, + scope, + deploymentName, + operationId + ], + headerParameters: [accept], + serializer +}; +const listAtScopeOperationSpec = { + path: "/{scope}/providers/Microsoft.Resources/deployments/{deploymentName}/operations", + httpMethod: "GET", + responses: { + 200: { + bodyMapper: DeploymentOperationsListResult + }, + default: { + bodyMapper: CloudError + } + }, + queryParameters: [apiVersion, top], + urlParameters: [ + $host, + scope, + deploymentName + ], + headerParameters: [accept], + serializer +}; +const getAtTenantScopeOperationSpec = { + path: "/providers/Microsoft.Resources/deployments/{deploymentName}/operations/{operationId}", + httpMethod: "GET", + responses: { + 200: { + bodyMapper: DeploymentOperation + }, + default: { + bodyMapper: CloudError + } + }, + queryParameters: [apiVersion], + urlParameters: [ + $host, + deploymentName, + operationId + ], + headerParameters: [accept], + serializer +}; +const listAtTenantScopeOperationSpec = { + path: "/providers/Microsoft.Resources/deployments/{deploymentName}/operations", + httpMethod: "GET", + responses: { + 200: { + bodyMapper: DeploymentOperationsListResult + }, + default: { + bodyMapper: CloudError + } + }, + queryParameters: [apiVersion, top], + urlParameters: [$host, deploymentName], + headerParameters: [accept], + serializer +}; +const getAtManagementGroupScopeOperationSpec = { + path: "/providers/Microsoft.Management/managementGroups/{groupId}/providers/Microsoft.Resources/deployments/{deploymentName}/operations/{operationId}", + httpMethod: "GET", + responses: { + 200: { + bodyMapper: DeploymentOperation + }, + default: { + bodyMapper: CloudError + } + }, + queryParameters: [apiVersion], + urlParameters: [ + $host, + deploymentName, + groupId, + operationId + ], + headerParameters: [accept], + serializer +}; +const listAtManagementGroupScopeOperationSpec = { + path: "/providers/Microsoft.Management/managementGroups/{groupId}/providers/Microsoft.Resources/deployments/{deploymentName}/operations", + httpMethod: "GET", + responses: { + 200: { + bodyMapper: DeploymentOperationsListResult + }, + default: { + bodyMapper: CloudError + } + }, + queryParameters: [apiVersion, top], + urlParameters: [ + $host, + deploymentName, + groupId + ], + headerParameters: [accept], + serializer +}; +const getAtSubscriptionScopeOperationSpec = { + path: "/subscriptions/{subscriptionId}/providers/Microsoft.Resources/deployments/{deploymentName}/operations/{operationId}", + httpMethod: "GET", + responses: { + 200: { + bodyMapper: DeploymentOperation + }, + default: { + bodyMapper: CloudError + } + }, + queryParameters: [apiVersion], + urlParameters: [ + $host, + deploymentName, + subscriptionId, + operationId + ], + headerParameters: [accept], + serializer +}; +const listAtSubscriptionScopeOperationSpec = { + path: "/subscriptions/{subscriptionId}/providers/Microsoft.Resources/deployments/{deploymentName}/operations", + httpMethod: "GET", + responses: { + 200: { + bodyMapper: DeploymentOperationsListResult + }, + default: { + bodyMapper: CloudError + } + }, + queryParameters: [apiVersion, top], + urlParameters: [ + $host, + deploymentName, + subscriptionId + ], + headerParameters: [accept], + serializer +}; +const getOperationSpec = { + path: "/subscriptions/{subscriptionId}/resourcegroups/{resourceGroupName}/deployments/{deploymentName}/operations/{operationId}", + httpMethod: "GET", + responses: { + 200: { + bodyMapper: DeploymentOperation + }, + default: { + bodyMapper: CloudError + } + }, + queryParameters: [apiVersion], + urlParameters: [ + $host, + deploymentName, + subscriptionId, + resourceGroupName, + operationId + ], + headerParameters: [accept], + serializer +}; +const listOperationSpec = { + path: "/subscriptions/{subscriptionId}/resourcegroups/{resourceGroupName}/deployments/{deploymentName}/operations", + httpMethod: "GET", + responses: { + 200: { + bodyMapper: DeploymentOperationsListResult + }, + default: { + bodyMapper: CloudError + } + }, + queryParameters: [apiVersion, top], + urlParameters: [ + $host, + deploymentName, + subscriptionId, + resourceGroupName + ], + headerParameters: [accept], + serializer +}; +const listAtScopeNextOperationSpec = { + path: "{nextLink}", + httpMethod: "GET", + responses: { + 200: { + bodyMapper: DeploymentOperationsListResult + }, + default: { + bodyMapper: CloudError + } + }, + urlParameters: [ + $host, + nextLink, + scope, + deploymentName + ], + headerParameters: [accept], + serializer +}; +const listAtTenantScopeNextOperationSpec = { + path: "{nextLink}", + httpMethod: "GET", + responses: { + 200: { + bodyMapper: DeploymentOperationsListResult + }, + default: { + bodyMapper: CloudError + } + }, + urlParameters: [ + $host, + nextLink, + deploymentName + ], + headerParameters: [accept], + serializer +}; +const listAtManagementGroupScopeNextOperationSpec = { + path: "{nextLink}", + httpMethod: "GET", + responses: { + 200: { + bodyMapper: DeploymentOperationsListResult + }, + default: { + bodyMapper: CloudError + } + }, + urlParameters: [ + $host, + nextLink, + deploymentName, + groupId + ], + headerParameters: [accept], + serializer +}; +const listAtSubscriptionScopeNextOperationSpec = { + path: "{nextLink}", + httpMethod: "GET", + responses: { + 200: { + bodyMapper: DeploymentOperationsListResult + }, + default: { + bodyMapper: CloudError + } + }, + urlParameters: [ + $host, + nextLink, + deploymentName, + subscriptionId + ], + headerParameters: [accept], + serializer +}; +const listNextOperationSpec = { + path: "{nextLink}", + httpMethod: "GET", + responses: { + 200: { + bodyMapper: DeploymentOperationsListResult + }, + default: { + bodyMapper: CloudError + } + }, + urlParameters: [ + $host, + nextLink, + deploymentName, + subscriptionId, + resourceGroupName + ], + headerParameters: [accept], + serializer +}; + +/* + * Copyright (c) Microsoft Corporation. + * Licensed under the MIT License. + * + * Code generated by Microsoft (R) AutoRest Code Generator. + * Changes may cause incorrect behavior and will be lost if the code is regenerated. + */ +class ResourceManagementClient extends coreClient__namespace.ServiceClient { + /** + * Initializes a new instance of the ResourceManagementClient class. + * @param credentials Subscription credentials which uniquely identify client subscription. + * @param subscriptionId The Microsoft Azure subscription ID. + * @param options The parameter options + */ + constructor(credentials, subscriptionId, options) { + var _a, _b, _c; + if (credentials === undefined) { + throw new Error("'credentials' cannot be null"); + } + if (subscriptionId === undefined) { + throw new Error("'subscriptionId' cannot be null"); + } + // Initializing default values for options + if (!options) { + options = {}; + } + const defaults = { + requestContentType: "application/json; charset=utf-8", + credential: credentials + }; + const packageDetails = `azsdk-js-arm-resources/5.2.0`; + const userAgentPrefix = options.userAgentOptions && options.userAgentOptions.userAgentPrefix + ? `${options.userAgentOptions.userAgentPrefix} ${packageDetails}` + : `${packageDetails}`; + const optionsWithDefaults = Object.assign(Object.assign(Object.assign({}, defaults), options), { userAgentOptions: { + userAgentPrefix + }, endpoint: (_b = (_a = options.endpoint) !== null && _a !== void 0 ? _a : options.baseUri) !== null && _b !== void 0 ? _b : "https://management.azure.com" }); + super(optionsWithDefaults); + let bearerTokenAuthenticationPolicyFound = false; + if ((options === null || options === void 0 ? void 0 : options.pipeline) && options.pipeline.getOrderedPolicies().length > 0) { + const pipelinePolicies = options.pipeline.getOrderedPolicies(); + bearerTokenAuthenticationPolicyFound = pipelinePolicies.some((pipelinePolicy) => pipelinePolicy.name === + coreRestPipeline__namespace.bearerTokenAuthenticationPolicyName); + } + if (!options || + !options.pipeline || + options.pipeline.getOrderedPolicies().length == 0 || + !bearerTokenAuthenticationPolicyFound) { + this.pipeline.removePolicy({ + name: coreRestPipeline__namespace.bearerTokenAuthenticationPolicyName + }); + this.pipeline.addPolicy(coreRestPipeline__namespace.bearerTokenAuthenticationPolicy({ + credential: credentials, + scopes: (_c = optionsWithDefaults.credentialScopes) !== null && _c !== void 0 ? _c : `${optionsWithDefaults.endpoint}/.default`, + challengeCallbacks: { + authorizeRequestOnChallenge: coreClient__namespace.authorizeRequestOnClaimChallenge + } + })); + } + // Parameter assignments + this.subscriptionId = subscriptionId; + // Assigning values to Constant parameters + this.$host = options.$host || "https://management.azure.com"; + this.apiVersion = options.apiVersion || "2021-04-01"; + this.operations = new OperationsImpl(this); + this.deployments = new DeploymentsImpl(this); + this.providers = new ProvidersImpl(this); + this.providerResourceTypes = new ProviderResourceTypesImpl(this); + this.resources = new ResourcesImpl(this); + this.resourceGroups = new ResourceGroupsImpl(this); + this.tagsOperations = new TagsOperationsImpl(this); + this.deploymentOperations = new DeploymentOperationsImpl(this); + this.addCustomApiVersionPolicy(options.apiVersion); + } + /** A function that adds a policy that sets the api-version (or equivalent) to reflect the library version. */ + addCustomApiVersionPolicy(apiVersion) { + if (!apiVersion) { + return; + } + const apiVersionPolicy = { + name: "CustomApiVersionPolicy", + sendRequest(request, next) { + return tslib.__awaiter(this, void 0, void 0, function* () { + const param = request.url.split("?"); + if (param.length > 1) { + const newParams = param[1].split("&").map((item) => { + if (item.indexOf("api-version") > -1) { + return "api-version=" + apiVersion; + } + else { + return item; + } + }); + request.url = param[0] + "?" + newParams.join("&"); + } + return next(request); + }); + } + }; + this.pipeline.addPolicy(apiVersionPolicy); + } +} + +exports.ResourceManagementClient = ResourceManagementClient; +exports.getContinuationToken = getContinuationToken; +//# sourceMappingURL=index.js.map + + +/***/ }), + +/***/ 9729: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ value: true })); + +var coreRestPipeline = __nccwpck_require__(8121); +var logger$1 = __nccwpck_require__(3233); + +// Copyright (c) Microsoft Corporation. +/** + * Encodes a byte array in base64 format. + * @param value - the Uint8Aray to encode + * @internal + */ +function encodeByteArray(value) { + // Buffer.from accepts | -- the TypeScript definition is off here + // https://nodejs.org/api/buffer.html#buffer_class_method_buffer_from_arraybuffer_byteoffset_length + const bufferValue = value instanceof Buffer ? value : Buffer.from(value.buffer); + return bufferValue.toString("base64"); +} +/** + * Decodes a base64 string into a byte array. + * @param value - the base64 string to decode + * @internal + */ +function decodeString(value) { + return Buffer.from(value, "base64"); +} +/** + * Decodes a base64 string into a string. + * @param value - the base64 string to decode + * @internal + */ +function decodeStringToString(value) { + return Buffer.from(value, "base64").toString(); +} + +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. +/** + * Default key used to access the XML attributes. + */ +const XML_ATTRKEY = "$"; +/** + * Default key used to access the XML value content. + */ +const XML_CHARKEY = "_"; + +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. +/** + * A type guard for a primitive response body. + * @param value - Value to test + * + * @internal + */ +function isPrimitiveBody(value, mapperTypeName) { + return (mapperTypeName !== "Composite" && + mapperTypeName !== "Dictionary" && + (typeof value === "string" || + typeof value === "number" || + typeof value === "boolean" || + (mapperTypeName === null || mapperTypeName === void 0 ? void 0 : mapperTypeName.match(/^(Date|DateTime|DateTimeRfc1123|UnixTime|ByteArray|Base64Url)$/i)) !== + null || + value === undefined || + value === null)); +} +const validateISODuration = /^(-|\+)?P(?:([-+]?[0-9,.]*)Y)?(?:([-+]?[0-9,.]*)M)?(?:([-+]?[0-9,.]*)W)?(?:([-+]?[0-9,.]*)D)?(?:T(?:([-+]?[0-9,.]*)H)?(?:([-+]?[0-9,.]*)M)?(?:([-+]?[0-9,.]*)S)?)?$/; +/** + * Returns true if the given string is in ISO 8601 format. + * @param value - The value to be validated for ISO 8601 duration format. + * @internal + */ +function isDuration(value) { + return validateISODuration.test(value); +} +const validUuidRegex = /^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/i; +/** + * Returns true if the provided uuid is valid. + * + * @param uuid - The uuid that needs to be validated. + * + * @internal + */ +function isValidUuid(uuid) { + return validUuidRegex.test(uuid); +} +/** + * Maps the response as follows: + * - wraps the response body if needed (typically if its type is primitive). + * - returns null if the combination of the headers and the body is empty. + * - otherwise, returns the combination of the headers and the body. + * + * @param responseObject - a representation of the parsed response + * @returns the response that will be returned to the user which can be null and/or wrapped + * + * @internal + */ +function handleNullableResponseAndWrappableBody(responseObject) { + const combinedHeadersAndBody = Object.assign(Object.assign({}, responseObject.headers), responseObject.body); + if (responseObject.hasNullableType && + Object.getOwnPropertyNames(combinedHeadersAndBody).length === 0) { + return responseObject.shouldWrapBody ? { body: null } : null; + } + else { + return responseObject.shouldWrapBody + ? Object.assign(Object.assign({}, responseObject.headers), { body: responseObject.body }) : combinedHeadersAndBody; + } +} +/** + * Take a `FullOperationResponse` and turn it into a flat + * response object to hand back to the consumer. + * @param fullResponse - The processed response from the operation request + * @param responseSpec - The response map from the OperationSpec + * + * @internal + */ +function flattenResponse(fullResponse, responseSpec) { + var _a, _b; + const parsedHeaders = fullResponse.parsedHeaders; + // head methods never have a body, but we return a boolean set to body property + // to indicate presence/absence of the resource + if (fullResponse.request.method === "HEAD") { + return Object.assign(Object.assign({}, parsedHeaders), { body: fullResponse.parsedBody }); + } + const bodyMapper = responseSpec && responseSpec.bodyMapper; + const isNullable = Boolean(bodyMapper === null || bodyMapper === void 0 ? void 0 : bodyMapper.nullable); + const expectedBodyTypeName = bodyMapper === null || bodyMapper === void 0 ? void 0 : bodyMapper.type.name; + /** If the body is asked for, we look at the expected body type to handle it */ + if (expectedBodyTypeName === "Stream") { + return Object.assign(Object.assign({}, parsedHeaders), { blobBody: fullResponse.blobBody, readableStreamBody: fullResponse.readableStreamBody }); + } + const modelProperties = (expectedBodyTypeName === "Composite" && + bodyMapper.type.modelProperties) || + {}; + const isPageableResponse = Object.keys(modelProperties).some((k) => modelProperties[k].serializedName === ""); + if (expectedBodyTypeName === "Sequence" || isPageableResponse) { + const arrayResponse = (_a = fullResponse.parsedBody) !== null && _a !== void 0 ? _a : []; + for (const key of Object.keys(modelProperties)) { + if (modelProperties[key].serializedName) { + arrayResponse[key] = (_b = fullResponse.parsedBody) === null || _b === void 0 ? void 0 : _b[key]; + } + } + if (parsedHeaders) { + for (const key of Object.keys(parsedHeaders)) { + arrayResponse[key] = parsedHeaders[key]; + } + } + return isNullable && + !fullResponse.parsedBody && + !parsedHeaders && + Object.getOwnPropertyNames(modelProperties).length === 0 + ? null + : arrayResponse; + } + return handleNullableResponseAndWrappableBody({ + body: fullResponse.parsedBody, + headers: parsedHeaders, + hasNullableType: isNullable, + shouldWrapBody: isPrimitiveBody(fullResponse.parsedBody, expectedBodyTypeName), + }); +} + +// Copyright (c) Microsoft Corporation. +class SerializerImpl { + constructor(modelMappers = {}, isXML = false) { + this.modelMappers = modelMappers; + this.isXML = isXML; + } + /** + * @deprecated Removing the constraints validation on client side. + */ + validateConstraints(mapper, value, objectName) { + const failValidation = (constraintName, constraintValue) => { + throw new Error(`"${objectName}" with value "${value}" should satisfy the constraint "${constraintName}": ${constraintValue}.`); + }; + if (mapper.constraints && value !== undefined && value !== null) { + const { ExclusiveMaximum, ExclusiveMinimum, InclusiveMaximum, InclusiveMinimum, MaxItems, MaxLength, MinItems, MinLength, MultipleOf, Pattern, UniqueItems, } = mapper.constraints; + if (ExclusiveMaximum !== undefined && value >= ExclusiveMaximum) { + failValidation("ExclusiveMaximum", ExclusiveMaximum); + } + if (ExclusiveMinimum !== undefined && value <= ExclusiveMinimum) { + failValidation("ExclusiveMinimum", ExclusiveMinimum); + } + if (InclusiveMaximum !== undefined && value > InclusiveMaximum) { + failValidation("InclusiveMaximum", InclusiveMaximum); + } + if (InclusiveMinimum !== undefined && value < InclusiveMinimum) { + failValidation("InclusiveMinimum", InclusiveMinimum); + } + if (MaxItems !== undefined && value.length > MaxItems) { + failValidation("MaxItems", MaxItems); + } + if (MaxLength !== undefined && value.length > MaxLength) { + failValidation("MaxLength", MaxLength); + } + if (MinItems !== undefined && value.length < MinItems) { + failValidation("MinItems", MinItems); + } + if (MinLength !== undefined && value.length < MinLength) { + failValidation("MinLength", MinLength); + } + if (MultipleOf !== undefined && value % MultipleOf !== 0) { + failValidation("MultipleOf", MultipleOf); + } + if (Pattern) { + const pattern = typeof Pattern === "string" ? new RegExp(Pattern) : Pattern; + if (typeof value !== "string" || value.match(pattern) === null) { + failValidation("Pattern", Pattern); + } + } + if (UniqueItems && + value.some((item, i, ar) => ar.indexOf(item) !== i)) { + failValidation("UniqueItems", UniqueItems); + } + } + } + /** + * Serialize the given object based on its metadata defined in the mapper + * + * @param mapper - The mapper which defines the metadata of the serializable object + * + * @param object - A valid Javascript object to be serialized + * + * @param objectName - Name of the serialized object + * + * @param options - additional options to serialization + * + * @returns A valid serialized Javascript object + */ + serialize(mapper, object, objectName, options = { xml: {} }) { + var _a, _b, _c; + const updatedOptions = { + xml: { + rootName: (_a = options.xml.rootName) !== null && _a !== void 0 ? _a : "", + includeRoot: (_b = options.xml.includeRoot) !== null && _b !== void 0 ? _b : false, + xmlCharKey: (_c = options.xml.xmlCharKey) !== null && _c !== void 0 ? _c : XML_CHARKEY, + }, + }; + let payload = {}; + const mapperType = mapper.type.name; + if (!objectName) { + objectName = mapper.serializedName; + } + if (mapperType.match(/^Sequence$/i) !== null) { + payload = []; + } + if (mapper.isConstant) { + object = mapper.defaultValue; + } + // This table of allowed values should help explain + // the mapper.required and mapper.nullable properties. + // X means "neither undefined or null are allowed". + // || required + // || true | false + // nullable || ========================== + // true || null | undefined/null + // false || X | undefined + // undefined || X | undefined/null + const { required, nullable } = mapper; + if (required && nullable && object === undefined) { + throw new Error(`${objectName} cannot be undefined.`); + } + if (required && !nullable && (object === undefined || object === null)) { + throw new Error(`${objectName} cannot be null or undefined.`); + } + if (!required && nullable === false && object === null) { + throw new Error(`${objectName} cannot be null.`); + } + if (object === undefined || object === null) { + payload = object; + } + else { + if (mapperType.match(/^any$/i) !== null) { + payload = object; + } + else if (mapperType.match(/^(Number|String|Boolean|Object|Stream|Uuid)$/i) !== null) { + payload = serializeBasicTypes(mapperType, objectName, object); + } + else if (mapperType.match(/^Enum$/i) !== null) { + const enumMapper = mapper; + payload = serializeEnumType(objectName, enumMapper.type.allowedValues, object); + } + else if (mapperType.match(/^(Date|DateTime|TimeSpan|DateTimeRfc1123|UnixTime)$/i) !== null) { + payload = serializeDateTypes(mapperType, object, objectName); + } + else if (mapperType.match(/^ByteArray$/i) !== null) { + payload = serializeByteArrayType(objectName, object); + } + else if (mapperType.match(/^Base64Url$/i) !== null) { + payload = serializeBase64UrlType(objectName, object); + } + else if (mapperType.match(/^Sequence$/i) !== null) { + payload = serializeSequenceType(this, mapper, object, objectName, Boolean(this.isXML), updatedOptions); + } + else if (mapperType.match(/^Dictionary$/i) !== null) { + payload = serializeDictionaryType(this, mapper, object, objectName, Boolean(this.isXML), updatedOptions); + } + else if (mapperType.match(/^Composite$/i) !== null) { + payload = serializeCompositeType(this, mapper, object, objectName, Boolean(this.isXML), updatedOptions); + } + } + return payload; + } + /** + * Deserialize the given object based on its metadata defined in the mapper + * + * @param mapper - The mapper which defines the metadata of the serializable object + * + * @param responseBody - A valid Javascript entity to be deserialized + * + * @param objectName - Name of the deserialized object + * + * @param options - Controls behavior of XML parser and builder. + * + * @returns A valid deserialized Javascript object + */ + deserialize(mapper, responseBody, objectName, options = { xml: {} }) { + var _a, _b, _c, _d; + const updatedOptions = { + xml: { + rootName: (_a = options.xml.rootName) !== null && _a !== void 0 ? _a : "", + includeRoot: (_b = options.xml.includeRoot) !== null && _b !== void 0 ? _b : false, + xmlCharKey: (_c = options.xml.xmlCharKey) !== null && _c !== void 0 ? _c : XML_CHARKEY, + }, + ignoreUnknownProperties: (_d = options.ignoreUnknownProperties) !== null && _d !== void 0 ? _d : false, + }; + if (responseBody === undefined || responseBody === null) { + if (this.isXML && mapper.type.name === "Sequence" && !mapper.xmlIsWrapped) { + // Edge case for empty XML non-wrapped lists. xml2js can't distinguish + // between the list being empty versus being missing, + // so let's do the more user-friendly thing and return an empty list. + responseBody = []; + } + // specifically check for undefined as default value can be a falsey value `0, "", false, null` + if (mapper.defaultValue !== undefined) { + responseBody = mapper.defaultValue; + } + return responseBody; + } + let payload; + const mapperType = mapper.type.name; + if (!objectName) { + objectName = mapper.serializedName; + } + if (mapperType.match(/^Composite$/i) !== null) { + payload = deserializeCompositeType(this, mapper, responseBody, objectName, updatedOptions); + } + else { + if (this.isXML) { + const xmlCharKey = updatedOptions.xml.xmlCharKey; + /** + * If the mapper specifies this as a non-composite type value but the responseBody contains + * both header ("$" i.e., XML_ATTRKEY) and body ("#" i.e., XML_CHARKEY) properties, + * then just reduce the responseBody value to the body ("#" i.e., XML_CHARKEY) property. + */ + if (responseBody[XML_ATTRKEY] !== undefined && responseBody[xmlCharKey] !== undefined) { + responseBody = responseBody[xmlCharKey]; + } + } + if (mapperType.match(/^Number$/i) !== null) { + payload = parseFloat(responseBody); + if (isNaN(payload)) { + payload = responseBody; + } + } + else if (mapperType.match(/^Boolean$/i) !== null) { + if (responseBody === "true") { + payload = true; + } + else if (responseBody === "false") { + payload = false; + } + else { + payload = responseBody; + } + } + else if (mapperType.match(/^(String|Enum|Object|Stream|Uuid|TimeSpan|any)$/i) !== null) { + payload = responseBody; + } + else if (mapperType.match(/^(Date|DateTime|DateTimeRfc1123)$/i) !== null) { + payload = new Date(responseBody); + } + else if (mapperType.match(/^UnixTime$/i) !== null) { + payload = unixTimeToDate(responseBody); + } + else if (mapperType.match(/^ByteArray$/i) !== null) { + payload = decodeString(responseBody); + } + else if (mapperType.match(/^Base64Url$/i) !== null) { + payload = base64UrlToByteArray(responseBody); + } + else if (mapperType.match(/^Sequence$/i) !== null) { + payload = deserializeSequenceType(this, mapper, responseBody, objectName, updatedOptions); + } + else if (mapperType.match(/^Dictionary$/i) !== null) { + payload = deserializeDictionaryType(this, mapper, responseBody, objectName, updatedOptions); + } + } + if (mapper.isConstant) { + payload = mapper.defaultValue; + } + return payload; + } +} +/** + * Method that creates and returns a Serializer. + * @param modelMappers - Known models to map + * @param isXML - If XML should be supported + */ +function createSerializer(modelMappers = {}, isXML = false) { + return new SerializerImpl(modelMappers, isXML); +} +function trimEnd(str, ch) { + let len = str.length; + while (len - 1 >= 0 && str[len - 1] === ch) { + --len; + } + return str.substr(0, len); +} +function bufferToBase64Url(buffer) { + if (!buffer) { + return undefined; + } + if (!(buffer instanceof Uint8Array)) { + throw new Error(`Please provide an input of type Uint8Array for converting to Base64Url.`); + } + // Uint8Array to Base64. + const str = encodeByteArray(buffer); + // Base64 to Base64Url. + return trimEnd(str, "=").replace(/\+/g, "-").replace(/\//g, "_"); +} +function base64UrlToByteArray(str) { + if (!str) { + return undefined; + } + if (str && typeof str.valueOf() !== "string") { + throw new Error("Please provide an input of type string for converting to Uint8Array"); + } + // Base64Url to Base64. + str = str.replace(/-/g, "+").replace(/_/g, "/"); + // Base64 to Uint8Array. + return decodeString(str); +} +function splitSerializeName(prop) { + const classes = []; + let partialclass = ""; + if (prop) { + const subwords = prop.split("."); + for (const item of subwords) { + if (item.charAt(item.length - 1) === "\\") { + partialclass += item.substr(0, item.length - 1) + "."; + } + else { + partialclass += item; + classes.push(partialclass); + partialclass = ""; + } + } + } + return classes; +} +function dateToUnixTime(d) { + if (!d) { + return undefined; + } + if (typeof d.valueOf() === "string") { + d = new Date(d); + } + return Math.floor(d.getTime() / 1000); +} +function unixTimeToDate(n) { + if (!n) { + return undefined; + } + return new Date(n * 1000); +} +function serializeBasicTypes(typeName, objectName, value) { + if (value !== null && value !== undefined) { + if (typeName.match(/^Number$/i) !== null) { + if (typeof value !== "number") { + throw new Error(`${objectName} with value ${value} must be of type number.`); + } + } + else if (typeName.match(/^String$/i) !== null) { + if (typeof value.valueOf() !== "string") { + throw new Error(`${objectName} with value "${value}" must be of type string.`); + } + } + else if (typeName.match(/^Uuid$/i) !== null) { + if (!(typeof value.valueOf() === "string" && isValidUuid(value))) { + throw new Error(`${objectName} with value "${value}" must be of type string and a valid uuid.`); + } + } + else if (typeName.match(/^Boolean$/i) !== null) { + if (typeof value !== "boolean") { + throw new Error(`${objectName} with value ${value} must be of type boolean.`); + } + } + else if (typeName.match(/^Stream$/i) !== null) { + const objectType = typeof value; + if (objectType !== "string" && + typeof value.pipe !== "function" && + !(value instanceof ArrayBuffer) && + !ArrayBuffer.isView(value) && + // File objects count as a type of Blob, so we want to use instanceof explicitly + !((typeof Blob === "function" || typeof Blob === "object") && value instanceof Blob) && + objectType !== "function") { + throw new Error(`${objectName} must be a string, Blob, ArrayBuffer, ArrayBufferView, NodeJS.ReadableStream, or () => NodeJS.ReadableStream.`); + } + } + } + return value; +} +function serializeEnumType(objectName, allowedValues, value) { + if (!allowedValues) { + throw new Error(`Please provide a set of allowedValues to validate ${objectName} as an Enum Type.`); + } + const isPresent = allowedValues.some((item) => { + if (typeof item.valueOf() === "string") { + return item.toLowerCase() === value.toLowerCase(); + } + return item === value; + }); + if (!isPresent) { + throw new Error(`${value} is not a valid value for ${objectName}. The valid values are: ${JSON.stringify(allowedValues)}.`); + } + return value; +} +function serializeByteArrayType(objectName, value) { + if (value !== undefined && value !== null) { + if (!(value instanceof Uint8Array)) { + throw new Error(`${objectName} must be of type Uint8Array.`); + } + value = encodeByteArray(value); + } + return value; +} +function serializeBase64UrlType(objectName, value) { + if (value !== undefined && value !== null) { + if (!(value instanceof Uint8Array)) { + throw new Error(`${objectName} must be of type Uint8Array.`); + } + value = bufferToBase64Url(value); + } + return value; +} +function serializeDateTypes(typeName, value, objectName) { + if (value !== undefined && value !== null) { + if (typeName.match(/^Date$/i) !== null) { + if (!(value instanceof Date || + (typeof value.valueOf() === "string" && !isNaN(Date.parse(value))))) { + throw new Error(`${objectName} must be an instanceof Date or a string in ISO8601 format.`); + } + value = + value instanceof Date + ? value.toISOString().substring(0, 10) + : new Date(value).toISOString().substring(0, 10); + } + else if (typeName.match(/^DateTime$/i) !== null) { + if (!(value instanceof Date || + (typeof value.valueOf() === "string" && !isNaN(Date.parse(value))))) { + throw new Error(`${objectName} must be an instanceof Date or a string in ISO8601 format.`); + } + value = value instanceof Date ? value.toISOString() : new Date(value).toISOString(); + } + else if (typeName.match(/^DateTimeRfc1123$/i) !== null) { + if (!(value instanceof Date || + (typeof value.valueOf() === "string" && !isNaN(Date.parse(value))))) { + throw new Error(`${objectName} must be an instanceof Date or a string in RFC-1123 format.`); + } + value = value instanceof Date ? value.toUTCString() : new Date(value).toUTCString(); + } + else if (typeName.match(/^UnixTime$/i) !== null) { + if (!(value instanceof Date || + (typeof value.valueOf() === "string" && !isNaN(Date.parse(value))))) { + throw new Error(`${objectName} must be an instanceof Date or a string in RFC-1123/ISO8601 format ` + + `for it to be serialized in UnixTime/Epoch format.`); + } + value = dateToUnixTime(value); + } + else if (typeName.match(/^TimeSpan$/i) !== null) { + if (!isDuration(value)) { + throw new Error(`${objectName} must be a string in ISO 8601 format. Instead was "${value}".`); + } + } + } + return value; +} +function serializeSequenceType(serializer, mapper, object, objectName, isXml, options) { + var _a; + if (!Array.isArray(object)) { + throw new Error(`${objectName} must be of type Array.`); + } + let elementType = mapper.type.element; + if (!elementType || typeof elementType !== "object") { + throw new Error(`element" metadata for an Array must be defined in the ` + + `mapper and it must of type "object" in ${objectName}.`); + } + // Quirk: Composite mappers referenced by `element` might + // not have *all* properties declared (like uberParent), + // so let's try to look up the full definition by name. + if (elementType.type.name === "Composite" && elementType.type.className) { + elementType = (_a = serializer.modelMappers[elementType.type.className]) !== null && _a !== void 0 ? _a : elementType; + } + const tempArray = []; + for (let i = 0; i < object.length; i++) { + const serializedValue = serializer.serialize(elementType, object[i], objectName, options); + if (isXml && elementType.xmlNamespace) { + const xmlnsKey = elementType.xmlNamespacePrefix + ? `xmlns:${elementType.xmlNamespacePrefix}` + : "xmlns"; + if (elementType.type.name === "Composite") { + tempArray[i] = Object.assign({}, serializedValue); + tempArray[i][XML_ATTRKEY] = { [xmlnsKey]: elementType.xmlNamespace }; + } + else { + tempArray[i] = {}; + tempArray[i][options.xml.xmlCharKey] = serializedValue; + tempArray[i][XML_ATTRKEY] = { [xmlnsKey]: elementType.xmlNamespace }; + } + } + else { + tempArray[i] = serializedValue; + } + } + return tempArray; +} +function serializeDictionaryType(serializer, mapper, object, objectName, isXml, options) { + if (typeof object !== "object") { + throw new Error(`${objectName} must be of type object.`); + } + const valueType = mapper.type.value; + if (!valueType || typeof valueType !== "object") { + throw new Error(`"value" metadata for a Dictionary must be defined in the ` + + `mapper and it must of type "object" in ${objectName}.`); + } + const tempDictionary = {}; + for (const key of Object.keys(object)) { + const serializedValue = serializer.serialize(valueType, object[key], objectName, options); + // If the element needs an XML namespace we need to add it within the $ property + tempDictionary[key] = getXmlObjectValue(valueType, serializedValue, isXml, options); + } + // Add the namespace to the root element if needed + if (isXml && mapper.xmlNamespace) { + const xmlnsKey = mapper.xmlNamespacePrefix ? `xmlns:${mapper.xmlNamespacePrefix}` : "xmlns"; + const result = tempDictionary; + result[XML_ATTRKEY] = { [xmlnsKey]: mapper.xmlNamespace }; + return result; + } + return tempDictionary; +} +/** + * Resolves the additionalProperties property from a referenced mapper + * @param serializer - the serializer containing the entire set of mappers + * @param mapper - the composite mapper to resolve + * @param objectName - name of the object being serialized + */ +function resolveAdditionalProperties(serializer, mapper, objectName) { + const additionalProperties = mapper.type.additionalProperties; + if (!additionalProperties && mapper.type.className) { + const modelMapper = resolveReferencedMapper(serializer, mapper, objectName); + return modelMapper === null || modelMapper === void 0 ? void 0 : modelMapper.type.additionalProperties; + } + return additionalProperties; +} +/** + * Finds the mapper referenced by className + * @param serializer - the serializer containing the entire set of mappers + * @param mapper - the composite mapper to resolve + * @param objectName - name of the object being serialized + */ +function resolveReferencedMapper(serializer, mapper, objectName) { + const className = mapper.type.className; + if (!className) { + throw new Error(`Class name for model "${objectName}" is not provided in the mapper "${JSON.stringify(mapper, undefined, 2)}".`); + } + return serializer.modelMappers[className]; +} +/** + * Resolves a composite mapper's modelProperties. + * @param serializer - the serializer containing the entire set of mappers + * @param mapper - the composite mapper to resolve + */ +function resolveModelProperties(serializer, mapper, objectName) { + let modelProps = mapper.type.modelProperties; + if (!modelProps) { + const modelMapper = resolveReferencedMapper(serializer, mapper, objectName); + if (!modelMapper) { + throw new Error(`mapper() cannot be null or undefined for model "${mapper.type.className}".`); + } + modelProps = modelMapper === null || modelMapper === void 0 ? void 0 : modelMapper.type.modelProperties; + if (!modelProps) { + throw new Error(`modelProperties cannot be null or undefined in the ` + + `mapper "${JSON.stringify(modelMapper)}" of type "${mapper.type.className}" for object "${objectName}".`); + } + } + return modelProps; +} +function serializeCompositeType(serializer, mapper, object, objectName, isXml, options) { + if (getPolymorphicDiscriminatorRecursively(serializer, mapper)) { + mapper = getPolymorphicMapper(serializer, mapper, object, "clientName"); + } + if (object !== undefined && object !== null) { + const payload = {}; + const modelProps = resolveModelProperties(serializer, mapper, objectName); + for (const key of Object.keys(modelProps)) { + const propertyMapper = modelProps[key]; + if (propertyMapper.readOnly) { + continue; + } + let propName; + let parentObject = payload; + if (serializer.isXML) { + if (propertyMapper.xmlIsWrapped) { + propName = propertyMapper.xmlName; + } + else { + propName = propertyMapper.xmlElementName || propertyMapper.xmlName; + } + } + else { + const paths = splitSerializeName(propertyMapper.serializedName); + propName = paths.pop(); + for (const pathName of paths) { + const childObject = parentObject[pathName]; + if ((childObject === undefined || childObject === null) && + ((object[key] !== undefined && object[key] !== null) || + propertyMapper.defaultValue !== undefined)) { + parentObject[pathName] = {}; + } + parentObject = parentObject[pathName]; + } + } + if (parentObject !== undefined && parentObject !== null) { + if (isXml && mapper.xmlNamespace) { + const xmlnsKey = mapper.xmlNamespacePrefix + ? `xmlns:${mapper.xmlNamespacePrefix}` + : "xmlns"; + parentObject[XML_ATTRKEY] = Object.assign(Object.assign({}, parentObject[XML_ATTRKEY]), { [xmlnsKey]: mapper.xmlNamespace }); + } + const propertyObjectName = propertyMapper.serializedName !== "" + ? objectName + "." + propertyMapper.serializedName + : objectName; + let toSerialize = object[key]; + const polymorphicDiscriminator = getPolymorphicDiscriminatorRecursively(serializer, mapper); + if (polymorphicDiscriminator && + polymorphicDiscriminator.clientName === key && + (toSerialize === undefined || toSerialize === null)) { + toSerialize = mapper.serializedName; + } + const serializedValue = serializer.serialize(propertyMapper, toSerialize, propertyObjectName, options); + if (serializedValue !== undefined && propName !== undefined && propName !== null) { + const value = getXmlObjectValue(propertyMapper, serializedValue, isXml, options); + if (isXml && propertyMapper.xmlIsAttribute) { + // XML_ATTRKEY, i.e., $ is the key attributes are kept under in xml2js. + // This keeps things simple while preventing name collision + // with names in user documents. + parentObject[XML_ATTRKEY] = parentObject[XML_ATTRKEY] || {}; + parentObject[XML_ATTRKEY][propName] = serializedValue; + } + else if (isXml && propertyMapper.xmlIsWrapped) { + parentObject[propName] = { [propertyMapper.xmlElementName]: value }; + } + else { + parentObject[propName] = value; + } + } + } + } + const additionalPropertiesMapper = resolveAdditionalProperties(serializer, mapper, objectName); + if (additionalPropertiesMapper) { + const propNames = Object.keys(modelProps); + for (const clientPropName in object) { + const isAdditionalProperty = propNames.every((pn) => pn !== clientPropName); + if (isAdditionalProperty) { + payload[clientPropName] = serializer.serialize(additionalPropertiesMapper, object[clientPropName], objectName + '["' + clientPropName + '"]', options); + } + } + } + return payload; + } + return object; +} +function getXmlObjectValue(propertyMapper, serializedValue, isXml, options) { + if (!isXml || !propertyMapper.xmlNamespace) { + return serializedValue; + } + const xmlnsKey = propertyMapper.xmlNamespacePrefix + ? `xmlns:${propertyMapper.xmlNamespacePrefix}` + : "xmlns"; + const xmlNamespace = { [xmlnsKey]: propertyMapper.xmlNamespace }; + if (["Composite"].includes(propertyMapper.type.name)) { + if (serializedValue[XML_ATTRKEY]) { + return serializedValue; + } + else { + const result = Object.assign({}, serializedValue); + result[XML_ATTRKEY] = xmlNamespace; + return result; + } + } + const result = {}; + result[options.xml.xmlCharKey] = serializedValue; + result[XML_ATTRKEY] = xmlNamespace; + return result; +} +function isSpecialXmlProperty(propertyName, options) { + return [XML_ATTRKEY, options.xml.xmlCharKey].includes(propertyName); +} +function deserializeCompositeType(serializer, mapper, responseBody, objectName, options) { + var _a, _b; + const xmlCharKey = (_a = options.xml.xmlCharKey) !== null && _a !== void 0 ? _a : XML_CHARKEY; + if (getPolymorphicDiscriminatorRecursively(serializer, mapper)) { + mapper = getPolymorphicMapper(serializer, mapper, responseBody, "serializedName"); + } + const modelProps = resolveModelProperties(serializer, mapper, objectName); + let instance = {}; + const handledPropertyNames = []; + for (const key of Object.keys(modelProps)) { + const propertyMapper = modelProps[key]; + const paths = splitSerializeName(modelProps[key].serializedName); + handledPropertyNames.push(paths[0]); + const { serializedName, xmlName, xmlElementName } = propertyMapper; + let propertyObjectName = objectName; + if (serializedName !== "" && serializedName !== undefined) { + propertyObjectName = objectName + "." + serializedName; + } + const headerCollectionPrefix = propertyMapper.headerCollectionPrefix; + if (headerCollectionPrefix) { + const dictionary = {}; + for (const headerKey of Object.keys(responseBody)) { + if (headerKey.startsWith(headerCollectionPrefix)) { + dictionary[headerKey.substring(headerCollectionPrefix.length)] = serializer.deserialize(propertyMapper.type.value, responseBody[headerKey], propertyObjectName, options); + } + handledPropertyNames.push(headerKey); + } + instance[key] = dictionary; + } + else if (serializer.isXML) { + if (propertyMapper.xmlIsAttribute && responseBody[XML_ATTRKEY]) { + instance[key] = serializer.deserialize(propertyMapper, responseBody[XML_ATTRKEY][xmlName], propertyObjectName, options); + } + else if (propertyMapper.xmlIsMsText) { + if (responseBody[xmlCharKey] !== undefined) { + instance[key] = responseBody[xmlCharKey]; + } + else if (typeof responseBody === "string") { + // The special case where xml parser parses "content" into JSON of + // `{ name: "content"}` instead of `{ name: { "_": "content" }}` + instance[key] = responseBody; + } + } + else { + const propertyName = xmlElementName || xmlName || serializedName; + if (propertyMapper.xmlIsWrapped) { + /* a list of wrapped by + For the xml example below + + ... + ... + + the responseBody has + { + Cors: { + CorsRule: [{...}, {...}] + } + } + xmlName is "Cors" and xmlElementName is"CorsRule". + */ + const wrapped = responseBody[xmlName]; + const elementList = (_b = wrapped === null || wrapped === void 0 ? void 0 : wrapped[xmlElementName]) !== null && _b !== void 0 ? _b : []; + instance[key] = serializer.deserialize(propertyMapper, elementList, propertyObjectName, options); + handledPropertyNames.push(xmlName); + } + else { + const property = responseBody[propertyName]; + instance[key] = serializer.deserialize(propertyMapper, property, propertyObjectName, options); + handledPropertyNames.push(propertyName); + } + } + } + else { + // deserialize the property if it is present in the provided responseBody instance + let propertyInstance; + let res = responseBody; + // traversing the object step by step. + let steps = 0; + for (const item of paths) { + if (!res) + break; + steps++; + res = res[item]; + } + // only accept null when reaching the last position of object otherwise it would be undefined + if (res === null && steps < paths.length) { + res = undefined; + } + propertyInstance = res; + const polymorphicDiscriminator = mapper.type.polymorphicDiscriminator; + // checking that the model property name (key)(ex: "fishtype") and the + // clientName of the polymorphicDiscriminator {metadata} (ex: "fishtype") + // instead of the serializedName of the polymorphicDiscriminator (ex: "fish.type") + // is a better approach. The generator is not consistent with escaping '\.' in the + // serializedName of the property (ex: "fish\.type") that is marked as polymorphic discriminator + // and the serializedName of the metadata polymorphicDiscriminator (ex: "fish.type"). However, + // the clientName transformation of the polymorphicDiscriminator (ex: "fishtype") and + // the transformation of model property name (ex: "fishtype") is done consistently. + // Hence, it is a safer bet to rely on the clientName of the polymorphicDiscriminator. + if (polymorphicDiscriminator && + key === polymorphicDiscriminator.clientName && + (propertyInstance === undefined || propertyInstance === null)) { + propertyInstance = mapper.serializedName; + } + let serializedValue; + // paging + if (Array.isArray(responseBody[key]) && modelProps[key].serializedName === "") { + propertyInstance = responseBody[key]; + const arrayInstance = serializer.deserialize(propertyMapper, propertyInstance, propertyObjectName, options); + // Copy over any properties that have already been added into the instance, where they do + // not exist on the newly de-serialized array + for (const [k, v] of Object.entries(instance)) { + if (!Object.prototype.hasOwnProperty.call(arrayInstance, k)) { + arrayInstance[k] = v; + } + } + instance = arrayInstance; + } + else if (propertyInstance !== undefined || propertyMapper.defaultValue !== undefined) { + serializedValue = serializer.deserialize(propertyMapper, propertyInstance, propertyObjectName, options); + instance[key] = serializedValue; + } + } + } + const additionalPropertiesMapper = mapper.type.additionalProperties; + if (additionalPropertiesMapper) { + const isAdditionalProperty = (responsePropName) => { + for (const clientPropName in modelProps) { + const paths = splitSerializeName(modelProps[clientPropName].serializedName); + if (paths[0] === responsePropName) { + return false; + } + } + return true; + }; + for (const responsePropName in responseBody) { + if (isAdditionalProperty(responsePropName)) { + instance[responsePropName] = serializer.deserialize(additionalPropertiesMapper, responseBody[responsePropName], objectName + '["' + responsePropName + '"]', options); + } + } + } + else if (responseBody && !options.ignoreUnknownProperties) { + for (const key of Object.keys(responseBody)) { + if (instance[key] === undefined && + !handledPropertyNames.includes(key) && + !isSpecialXmlProperty(key, options)) { + instance[key] = responseBody[key]; + } + } + } + return instance; +} +function deserializeDictionaryType(serializer, mapper, responseBody, objectName, options) { + /* jshint validthis: true */ + const value = mapper.type.value; + if (!value || typeof value !== "object") { + throw new Error(`"value" metadata for a Dictionary must be defined in the ` + + `mapper and it must of type "object" in ${objectName}`); + } + if (responseBody) { + const tempDictionary = {}; + for (const key of Object.keys(responseBody)) { + tempDictionary[key] = serializer.deserialize(value, responseBody[key], objectName, options); + } + return tempDictionary; + } + return responseBody; +} +function deserializeSequenceType(serializer, mapper, responseBody, objectName, options) { + var _a; + let element = mapper.type.element; + if (!element || typeof element !== "object") { + throw new Error(`element" metadata for an Array must be defined in the ` + + `mapper and it must of type "object" in ${objectName}`); + } + if (responseBody) { + if (!Array.isArray(responseBody)) { + // xml2js will interpret a single element array as just the element, so force it to be an array + responseBody = [responseBody]; + } + // Quirk: Composite mappers referenced by `element` might + // not have *all* properties declared (like uberParent), + // so let's try to look up the full definition by name. + if (element.type.name === "Composite" && element.type.className) { + element = (_a = serializer.modelMappers[element.type.className]) !== null && _a !== void 0 ? _a : element; + } + const tempArray = []; + for (let i = 0; i < responseBody.length; i++) { + tempArray[i] = serializer.deserialize(element, responseBody[i], `${objectName}[${i}]`, options); + } + return tempArray; + } + return responseBody; +} +function getIndexDiscriminator(discriminators, discriminatorValue, typeName) { + const typeNamesToCheck = [typeName]; + while (typeNamesToCheck.length) { + const currentName = typeNamesToCheck.shift(); + const indexDiscriminator = discriminatorValue === currentName + ? discriminatorValue + : currentName + "." + discriminatorValue; + if (Object.prototype.hasOwnProperty.call(discriminators, indexDiscriminator)) { + return discriminators[indexDiscriminator]; + } + else { + for (const [name, mapper] of Object.entries(discriminators)) { + if (name.startsWith(currentName + ".") && + mapper.type.uberParent === currentName && + mapper.type.className) { + typeNamesToCheck.push(mapper.type.className); + } + } + } + } + return undefined; +} +function getPolymorphicMapper(serializer, mapper, object, polymorphicPropertyName) { + var _a; + const polymorphicDiscriminator = getPolymorphicDiscriminatorRecursively(serializer, mapper); + if (polymorphicDiscriminator) { + let discriminatorName = polymorphicDiscriminator[polymorphicPropertyName]; + if (discriminatorName) { + // The serializedName might have \\, which we just want to ignore + if (polymorphicPropertyName === "serializedName") { + discriminatorName = discriminatorName.replace(/\\/gi, ""); + } + const discriminatorValue = object[discriminatorName]; + const typeName = (_a = mapper.type.uberParent) !== null && _a !== void 0 ? _a : mapper.type.className; + if (typeof discriminatorValue === "string" && typeName) { + const polymorphicMapper = getIndexDiscriminator(serializer.modelMappers.discriminators, discriminatorValue, typeName); + if (polymorphicMapper) { + mapper = polymorphicMapper; + } + } + } + } + return mapper; +} +function getPolymorphicDiscriminatorRecursively(serializer, mapper) { + return (mapper.type.polymorphicDiscriminator || + getPolymorphicDiscriminatorSafely(serializer, mapper.type.uberParent) || + getPolymorphicDiscriminatorSafely(serializer, mapper.type.className)); +} +function getPolymorphicDiscriminatorSafely(serializer, typeName) { + return (typeName && + serializer.modelMappers[typeName] && + serializer.modelMappers[typeName].type.polymorphicDiscriminator); +} +/** + * Known types of Mappers + */ +const MapperTypeNames = { + Base64Url: "Base64Url", + Boolean: "Boolean", + ByteArray: "ByteArray", + Composite: "Composite", + Date: "Date", + DateTime: "DateTime", + DateTimeRfc1123: "DateTimeRfc1123", + Dictionary: "Dictionary", + Enum: "Enum", + Number: "Number", + Object: "Object", + Sequence: "Sequence", + String: "String", + Stream: "Stream", + TimeSpan: "TimeSpan", + UnixTime: "UnixTime", +}; + +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. +/** + * @internal + * Retrieves the value to use for a given operation argument + * @param operationArguments - The arguments passed from the generated client + * @param parameter - The parameter description + * @param fallbackObject - If something isn't found in the arguments bag, look here. + * Generally used to look at the service client properties. + */ +function getOperationArgumentValueFromParameter(operationArguments, parameter, fallbackObject) { + let parameterPath = parameter.parameterPath; + const parameterMapper = parameter.mapper; + let value; + if (typeof parameterPath === "string") { + parameterPath = [parameterPath]; + } + if (Array.isArray(parameterPath)) { + if (parameterPath.length > 0) { + if (parameterMapper.isConstant) { + value = parameterMapper.defaultValue; + } + else { + let propertySearchResult = getPropertyFromParameterPath(operationArguments, parameterPath); + if (!propertySearchResult.propertyFound && fallbackObject) { + propertySearchResult = getPropertyFromParameterPath(fallbackObject, parameterPath); + } + let useDefaultValue = false; + if (!propertySearchResult.propertyFound) { + useDefaultValue = + parameterMapper.required || + (parameterPath[0] === "options" && parameterPath.length === 2); + } + value = useDefaultValue ? parameterMapper.defaultValue : propertySearchResult.propertyValue; + } + } + } + else { + if (parameterMapper.required) { + value = {}; + } + for (const propertyName in parameterPath) { + const propertyMapper = parameterMapper.type.modelProperties[propertyName]; + const propertyPath = parameterPath[propertyName]; + const propertyValue = getOperationArgumentValueFromParameter(operationArguments, { + parameterPath: propertyPath, + mapper: propertyMapper, + }, fallbackObject); + if (propertyValue !== undefined) { + if (!value) { + value = {}; + } + value[propertyName] = propertyValue; + } + } + } + return value; +} +function getPropertyFromParameterPath(parent, parameterPath) { + const result = { propertyFound: false }; + let i = 0; + for (; i < parameterPath.length; ++i) { + const parameterPathPart = parameterPath[i]; + // Make sure to check inherited properties too, so don't use hasOwnProperty(). + if (parent && parameterPathPart in parent) { + parent = parent[parameterPathPart]; + } + else { + break; + } + } + if (i === parameterPath.length) { + result.propertyValue = parent; + result.propertyFound = true; + } + return result; +} +const operationRequestMap = new WeakMap(); +const originalRequestSymbol = Symbol.for("@azure/core-client original request"); +function hasOriginalRequest(request) { + return originalRequestSymbol in request; +} +function getOperationRequestInfo(request) { + if (hasOriginalRequest(request)) { + return getOperationRequestInfo(request[originalRequestSymbol]); + } + let info = operationRequestMap.get(request); + if (!info) { + info = {}; + operationRequestMap.set(request, info); + } + return info; +} + +// Copyright (c) Microsoft Corporation. +const defaultJsonContentTypes = ["application/json", "text/json"]; +const defaultXmlContentTypes = ["application/xml", "application/atom+xml"]; +/** + * The programmatic identifier of the deserializationPolicy. + */ +const deserializationPolicyName = "deserializationPolicy"; +/** + * This policy handles parsing out responses according to OperationSpecs on the request. + */ +function deserializationPolicy(options = {}) { + var _a, _b, _c, _d, _e, _f, _g; + const jsonContentTypes = (_b = (_a = options.expectedContentTypes) === null || _a === void 0 ? void 0 : _a.json) !== null && _b !== void 0 ? _b : defaultJsonContentTypes; + const xmlContentTypes = (_d = (_c = options.expectedContentTypes) === null || _c === void 0 ? void 0 : _c.xml) !== null && _d !== void 0 ? _d : defaultXmlContentTypes; + const parseXML = options.parseXML; + const serializerOptions = options.serializerOptions; + const updatedOptions = { + xml: { + rootName: (_e = serializerOptions === null || serializerOptions === void 0 ? void 0 : serializerOptions.xml.rootName) !== null && _e !== void 0 ? _e : "", + includeRoot: (_f = serializerOptions === null || serializerOptions === void 0 ? void 0 : serializerOptions.xml.includeRoot) !== null && _f !== void 0 ? _f : false, + xmlCharKey: (_g = serializerOptions === null || serializerOptions === void 0 ? void 0 : serializerOptions.xml.xmlCharKey) !== null && _g !== void 0 ? _g : XML_CHARKEY, + }, + }; + return { + name: deserializationPolicyName, + async sendRequest(request, next) { + const response = await next(request); + return deserializeResponseBody(jsonContentTypes, xmlContentTypes, response, updatedOptions, parseXML); + }, + }; +} +function getOperationResponseMap(parsedResponse) { + let result; + const request = parsedResponse.request; + const operationInfo = getOperationRequestInfo(request); + const operationSpec = operationInfo === null || operationInfo === void 0 ? void 0 : operationInfo.operationSpec; + if (operationSpec) { + if (!(operationInfo === null || operationInfo === void 0 ? void 0 : operationInfo.operationResponseGetter)) { + result = operationSpec.responses[parsedResponse.status]; + } + else { + result = operationInfo === null || operationInfo === void 0 ? void 0 : operationInfo.operationResponseGetter(operationSpec, parsedResponse); + } + } + return result; +} +function shouldDeserializeResponse(parsedResponse) { + const request = parsedResponse.request; + const operationInfo = getOperationRequestInfo(request); + const shouldDeserialize = operationInfo === null || operationInfo === void 0 ? void 0 : operationInfo.shouldDeserialize; + let result; + if (shouldDeserialize === undefined) { + result = true; + } + else if (typeof shouldDeserialize === "boolean") { + result = shouldDeserialize; + } + else { + result = shouldDeserialize(parsedResponse); + } + return result; +} +async function deserializeResponseBody(jsonContentTypes, xmlContentTypes, response, options, parseXML) { + const parsedResponse = await parse(jsonContentTypes, xmlContentTypes, response, options, parseXML); + if (!shouldDeserializeResponse(parsedResponse)) { + return parsedResponse; + } + const operationInfo = getOperationRequestInfo(parsedResponse.request); + const operationSpec = operationInfo === null || operationInfo === void 0 ? void 0 : operationInfo.operationSpec; + if (!operationSpec || !operationSpec.responses) { + return parsedResponse; + } + const responseSpec = getOperationResponseMap(parsedResponse); + const { error, shouldReturnResponse } = handleErrorResponse(parsedResponse, operationSpec, responseSpec, options); + if (error) { + throw error; + } + else if (shouldReturnResponse) { + return parsedResponse; + } + // An operation response spec does exist for current status code, so + // use it to deserialize the response. + if (responseSpec) { + if (responseSpec.bodyMapper) { + let valueToDeserialize = parsedResponse.parsedBody; + if (operationSpec.isXML && responseSpec.bodyMapper.type.name === MapperTypeNames.Sequence) { + valueToDeserialize = + typeof valueToDeserialize === "object" + ? valueToDeserialize[responseSpec.bodyMapper.xmlElementName] + : []; + } + try { + parsedResponse.parsedBody = operationSpec.serializer.deserialize(responseSpec.bodyMapper, valueToDeserialize, "operationRes.parsedBody", options); + } + catch (deserializeError) { + const restError = new coreRestPipeline.RestError(`Error ${deserializeError} occurred in deserializing the responseBody - ${parsedResponse.bodyAsText}`, { + statusCode: parsedResponse.status, + request: parsedResponse.request, + response: parsedResponse, + }); + throw restError; + } + } + else if (operationSpec.httpMethod === "HEAD") { + // head methods never have a body, but we return a boolean to indicate presence/absence of the resource + parsedResponse.parsedBody = response.status >= 200 && response.status < 300; + } + if (responseSpec.headersMapper) { + parsedResponse.parsedHeaders = operationSpec.serializer.deserialize(responseSpec.headersMapper, parsedResponse.headers.toJSON(), "operationRes.parsedHeaders", { xml: {}, ignoreUnknownProperties: true }); + } + } + return parsedResponse; +} +function isOperationSpecEmpty(operationSpec) { + const expectedStatusCodes = Object.keys(operationSpec.responses); + return (expectedStatusCodes.length === 0 || + (expectedStatusCodes.length === 1 && expectedStatusCodes[0] === "default")); +} +function handleErrorResponse(parsedResponse, operationSpec, responseSpec, options) { + var _a; + const isSuccessByStatus = 200 <= parsedResponse.status && parsedResponse.status < 300; + const isExpectedStatusCode = isOperationSpecEmpty(operationSpec) + ? isSuccessByStatus + : !!responseSpec; + if (isExpectedStatusCode) { + if (responseSpec) { + if (!responseSpec.isError) { + return { error: null, shouldReturnResponse: false }; + } + } + else { + return { error: null, shouldReturnResponse: false }; + } + } + const errorResponseSpec = responseSpec !== null && responseSpec !== void 0 ? responseSpec : operationSpec.responses.default; + const initialErrorMessage = ((_a = parsedResponse.request.streamResponseStatusCodes) === null || _a === void 0 ? void 0 : _a.has(parsedResponse.status)) + ? `Unexpected status code: ${parsedResponse.status}` + : parsedResponse.bodyAsText; + const error = new coreRestPipeline.RestError(initialErrorMessage, { + statusCode: parsedResponse.status, + request: parsedResponse.request, + response: parsedResponse, + }); + // If the item failed but there's no error spec or default spec to deserialize the error, + // we should fail so we just throw the parsed response + if (!errorResponseSpec) { + throw error; + } + const defaultBodyMapper = errorResponseSpec.bodyMapper; + const defaultHeadersMapper = errorResponseSpec.headersMapper; + try { + // If error response has a body, try to deserialize it using default body mapper. + // Then try to extract error code & message from it + if (parsedResponse.parsedBody) { + const parsedBody = parsedResponse.parsedBody; + let deserializedError; + if (defaultBodyMapper) { + let valueToDeserialize = parsedBody; + if (operationSpec.isXML && defaultBodyMapper.type.name === MapperTypeNames.Sequence) { + valueToDeserialize = []; + const elementName = defaultBodyMapper.xmlElementName; + if (typeof parsedBody === "object" && elementName) { + valueToDeserialize = parsedBody[elementName]; + } + } + deserializedError = operationSpec.serializer.deserialize(defaultBodyMapper, valueToDeserialize, "error.response.parsedBody", options); + } + const internalError = parsedBody.error || deserializedError || parsedBody; + error.code = internalError.code; + if (internalError.message) { + error.message = internalError.message; + } + if (defaultBodyMapper) { + error.response.parsedBody = deserializedError; + } + } + // If error response has headers, try to deserialize it using default header mapper + if (parsedResponse.headers && defaultHeadersMapper) { + error.response.parsedHeaders = + operationSpec.serializer.deserialize(defaultHeadersMapper, parsedResponse.headers.toJSON(), "operationRes.parsedHeaders"); + } + } + catch (defaultError) { + error.message = `Error "${defaultError.message}" occurred in deserializing the responseBody - "${parsedResponse.bodyAsText}" for the default response.`; + } + return { error, shouldReturnResponse: false }; +} +async function parse(jsonContentTypes, xmlContentTypes, operationResponse, opts, parseXML) { + var _a; + if (!((_a = operationResponse.request.streamResponseStatusCodes) === null || _a === void 0 ? void 0 : _a.has(operationResponse.status)) && + operationResponse.bodyAsText) { + const text = operationResponse.bodyAsText; + const contentType = operationResponse.headers.get("Content-Type") || ""; + const contentComponents = !contentType + ? [] + : contentType.split(";").map((component) => component.toLowerCase()); + try { + if (contentComponents.length === 0 || + contentComponents.some((component) => jsonContentTypes.indexOf(component) !== -1)) { + operationResponse.parsedBody = JSON.parse(text); + return operationResponse; + } + else if (contentComponents.some((component) => xmlContentTypes.indexOf(component) !== -1)) { + if (!parseXML) { + throw new Error("Parsing XML not supported."); + } + const body = await parseXML(text, opts.xml); + operationResponse.parsedBody = body; + return operationResponse; + } + } + catch (err) { + const msg = `Error "${err}" occurred while parsing the response body - ${operationResponse.bodyAsText}.`; + const errCode = err.code || coreRestPipeline.RestError.PARSE_ERROR; + const e = new coreRestPipeline.RestError(msg, { + code: errCode, + statusCode: operationResponse.status, + request: operationResponse.request, + response: operationResponse, + }); + throw e; + } + } + return operationResponse; +} + +// Copyright (c) Microsoft Corporation. +/** + * Gets the list of status codes for streaming responses. + * @internal + */ +function getStreamingResponseStatusCodes(operationSpec) { + const result = new Set(); + for (const statusCode in operationSpec.responses) { + const operationResponse = operationSpec.responses[statusCode]; + if (operationResponse.bodyMapper && + operationResponse.bodyMapper.type.name === MapperTypeNames.Stream) { + result.add(Number(statusCode)); + } + } + return result; +} +/** + * Get the path to this parameter's value as a dotted string (a.b.c). + * @param parameter - The parameter to get the path string for. + * @returns The path to this parameter's value as a dotted string. + * @internal + */ +function getPathStringFromParameter(parameter) { + const { parameterPath, mapper } = parameter; + let result; + if (typeof parameterPath === "string") { + result = parameterPath; + } + else if (Array.isArray(parameterPath)) { + result = parameterPath.join("."); + } + else { + result = mapper.serializedName; + } + return result; +} + +// Copyright (c) Microsoft Corporation. +/** + * The programmatic identifier of the serializationPolicy. + */ +const serializationPolicyName = "serializationPolicy"; +/** + * This policy handles assembling the request body and headers using + * an OperationSpec and OperationArguments on the request. + */ +function serializationPolicy(options = {}) { + const stringifyXML = options.stringifyXML; + return { + name: serializationPolicyName, + async sendRequest(request, next) { + const operationInfo = getOperationRequestInfo(request); + const operationSpec = operationInfo === null || operationInfo === void 0 ? void 0 : operationInfo.operationSpec; + const operationArguments = operationInfo === null || operationInfo === void 0 ? void 0 : operationInfo.operationArguments; + if (operationSpec && operationArguments) { + serializeHeaders(request, operationArguments, operationSpec); + serializeRequestBody(request, operationArguments, operationSpec, stringifyXML); + } + return next(request); + }, + }; +} +/** + * @internal + */ +function serializeHeaders(request, operationArguments, operationSpec) { + var _a, _b; + if (operationSpec.headerParameters) { + for (const headerParameter of operationSpec.headerParameters) { + let headerValue = getOperationArgumentValueFromParameter(operationArguments, headerParameter); + if ((headerValue !== null && headerValue !== undefined) || headerParameter.mapper.required) { + headerValue = operationSpec.serializer.serialize(headerParameter.mapper, headerValue, getPathStringFromParameter(headerParameter)); + const headerCollectionPrefix = headerParameter.mapper + .headerCollectionPrefix; + if (headerCollectionPrefix) { + for (const key of Object.keys(headerValue)) { + request.headers.set(headerCollectionPrefix + key, headerValue[key]); + } + } + else { + request.headers.set(headerParameter.mapper.serializedName || getPathStringFromParameter(headerParameter), headerValue); + } + } + } + } + const customHeaders = (_b = (_a = operationArguments.options) === null || _a === void 0 ? void 0 : _a.requestOptions) === null || _b === void 0 ? void 0 : _b.customHeaders; + if (customHeaders) { + for (const customHeaderName of Object.keys(customHeaders)) { + request.headers.set(customHeaderName, customHeaders[customHeaderName]); + } + } +} +/** + * @internal + */ +function serializeRequestBody(request, operationArguments, operationSpec, stringifyXML = function () { + throw new Error("XML serialization unsupported!"); +}) { + var _a, _b, _c, _d, _e; + const serializerOptions = (_a = operationArguments.options) === null || _a === void 0 ? void 0 : _a.serializerOptions; + const updatedOptions = { + xml: { + rootName: (_b = serializerOptions === null || serializerOptions === void 0 ? void 0 : serializerOptions.xml.rootName) !== null && _b !== void 0 ? _b : "", + includeRoot: (_c = serializerOptions === null || serializerOptions === void 0 ? void 0 : serializerOptions.xml.includeRoot) !== null && _c !== void 0 ? _c : false, + xmlCharKey: (_d = serializerOptions === null || serializerOptions === void 0 ? void 0 : serializerOptions.xml.xmlCharKey) !== null && _d !== void 0 ? _d : XML_CHARKEY, + }, + }; + const xmlCharKey = updatedOptions.xml.xmlCharKey; + if (operationSpec.requestBody && operationSpec.requestBody.mapper) { + request.body = getOperationArgumentValueFromParameter(operationArguments, operationSpec.requestBody); + const bodyMapper = operationSpec.requestBody.mapper; + const { required, serializedName, xmlName, xmlElementName, xmlNamespace, xmlNamespacePrefix, nullable, } = bodyMapper; + const typeName = bodyMapper.type.name; + try { + if ((request.body !== undefined && request.body !== null) || + (nullable && request.body === null) || + required) { + const requestBodyParameterPathString = getPathStringFromParameter(operationSpec.requestBody); + request.body = operationSpec.serializer.serialize(bodyMapper, request.body, requestBodyParameterPathString, updatedOptions); + const isStream = typeName === MapperTypeNames.Stream; + if (operationSpec.isXML) { + const xmlnsKey = xmlNamespacePrefix ? `xmlns:${xmlNamespacePrefix}` : "xmlns"; + const value = getXmlValueWithNamespace(xmlNamespace, xmlnsKey, typeName, request.body, updatedOptions); + if (typeName === MapperTypeNames.Sequence) { + request.body = stringifyXML(prepareXMLRootList(value, xmlElementName || xmlName || serializedName, xmlnsKey, xmlNamespace), { rootName: xmlName || serializedName, xmlCharKey }); + } + else if (!isStream) { + request.body = stringifyXML(value, { + rootName: xmlName || serializedName, + xmlCharKey, + }); + } + } + else if (typeName === MapperTypeNames.String && + (((_e = operationSpec.contentType) === null || _e === void 0 ? void 0 : _e.match("text/plain")) || operationSpec.mediaType === "text")) { + // the String serializer has validated that request body is a string + // so just send the string. + return; + } + else if (!isStream) { + request.body = JSON.stringify(request.body); + } + } + } + catch (error) { + throw new Error(`Error "${error.message}" occurred in serializing the payload - ${JSON.stringify(serializedName, undefined, " ")}.`); + } + } + else if (operationSpec.formDataParameters && operationSpec.formDataParameters.length > 0) { + request.formData = {}; + for (const formDataParameter of operationSpec.formDataParameters) { + const formDataParameterValue = getOperationArgumentValueFromParameter(operationArguments, formDataParameter); + if (formDataParameterValue !== undefined && formDataParameterValue !== null) { + const formDataParameterPropertyName = formDataParameter.mapper.serializedName || getPathStringFromParameter(formDataParameter); + request.formData[formDataParameterPropertyName] = operationSpec.serializer.serialize(formDataParameter.mapper, formDataParameterValue, getPathStringFromParameter(formDataParameter), updatedOptions); + } + } + } +} +/** + * Adds an xml namespace to the xml serialized object if needed, otherwise it just returns the value itself + */ +function getXmlValueWithNamespace(xmlNamespace, xmlnsKey, typeName, serializedValue, options) { + // Composite and Sequence schemas already got their root namespace set during serialization + // We just need to add xmlns to the other schema types + if (xmlNamespace && !["Composite", "Sequence", "Dictionary"].includes(typeName)) { + const result = {}; + result[options.xml.xmlCharKey] = serializedValue; + result[XML_ATTRKEY] = { [xmlnsKey]: xmlNamespace }; + return result; + } + return serializedValue; +} +function prepareXMLRootList(obj, elementName, xmlNamespaceKey, xmlNamespace) { + if (!Array.isArray(obj)) { + obj = [obj]; + } + if (!xmlNamespaceKey || !xmlNamespace) { + return { [elementName]: obj }; + } + const result = { [elementName]: obj }; + result[XML_ATTRKEY] = { [xmlNamespaceKey]: xmlNamespace }; + return result; +} + +// Copyright (c) Microsoft Corporation. +/** + * Creates a new Pipeline for use with a Service Client. + * Adds in deserializationPolicy by default. + * Also adds in bearerTokenAuthenticationPolicy if passed a TokenCredential. + * @param options - Options to customize the created pipeline. + */ +function createClientPipeline(options = {}) { + const pipeline = coreRestPipeline.createPipelineFromOptions(options !== null && options !== void 0 ? options : {}); + if (options.credentialOptions) { + pipeline.addPolicy(coreRestPipeline.bearerTokenAuthenticationPolicy({ + credential: options.credentialOptions.credential, + scopes: options.credentialOptions.credentialScopes, + })); + } + pipeline.addPolicy(serializationPolicy(options.serializationOptions), { phase: "Serialize" }); + pipeline.addPolicy(deserializationPolicy(options.deserializationOptions), { + phase: "Deserialize", + }); + return pipeline; +} + +// Copyright (c) Microsoft Corporation. +let cachedHttpClient; +function getCachedDefaultHttpClient() { + if (!cachedHttpClient) { + cachedHttpClient = coreRestPipeline.createDefaultHttpClient(); + } + return cachedHttpClient; +} + +// Copyright (c) Microsoft Corporation. +const CollectionFormatToDelimiterMap = { + CSV: ",", + SSV: " ", + Multi: "Multi", + TSV: "\t", + Pipes: "|", +}; +function getRequestUrl(baseUri, operationSpec, operationArguments, fallbackObject) { + const urlReplacements = calculateUrlReplacements(operationSpec, operationArguments, fallbackObject); + let isAbsolutePath = false; + let requestUrl = replaceAll(baseUri, urlReplacements); + if (operationSpec.path) { + let path = replaceAll(operationSpec.path, urlReplacements); + // QUIRK: sometimes we get a path component like /{nextLink} + // which may be a fully formed URL with a leading /. In that case, we should + // remove the leading / + if (operationSpec.path === "/{nextLink}" && path.startsWith("/")) { + path = path.substring(1); + } + // QUIRK: sometimes we get a path component like {nextLink} + // which may be a fully formed URL. In that case, we should + // ignore the baseUri. + if (isAbsoluteUrl(path)) { + requestUrl = path; + isAbsolutePath = true; + } + else { + requestUrl = appendPath(requestUrl, path); + } + } + const { queryParams, sequenceParams } = calculateQueryParameters(operationSpec, operationArguments, fallbackObject); + /** + * Notice that this call sets the `noOverwrite` parameter to true if the `requestUrl` + * is an absolute path. This ensures that existing query parameter values in `requestUrl` + * do not get overwritten. On the other hand when `requestUrl` is not absolute path, it + * is still being built so there is nothing to overwrite. + */ + requestUrl = appendQueryParams(requestUrl, queryParams, sequenceParams, isAbsolutePath); + return requestUrl; +} +function replaceAll(input, replacements) { + let result = input; + for (const [searchValue, replaceValue] of replacements) { + result = result.split(searchValue).join(replaceValue); + } + return result; +} +function calculateUrlReplacements(operationSpec, operationArguments, fallbackObject) { + var _a; + const result = new Map(); + if ((_a = operationSpec.urlParameters) === null || _a === void 0 ? void 0 : _a.length) { + for (const urlParameter of operationSpec.urlParameters) { + let urlParameterValue = getOperationArgumentValueFromParameter(operationArguments, urlParameter, fallbackObject); + const parameterPathString = getPathStringFromParameter(urlParameter); + urlParameterValue = operationSpec.serializer.serialize(urlParameter.mapper, urlParameterValue, parameterPathString); + if (!urlParameter.skipEncoding) { + urlParameterValue = encodeURIComponent(urlParameterValue); + } + result.set(`{${urlParameter.mapper.serializedName || parameterPathString}}`, urlParameterValue); + } + } + return result; +} +function isAbsoluteUrl(url) { + return url.includes("://"); +} +function appendPath(url, pathToAppend) { + if (!pathToAppend) { + return url; + } + const parsedUrl = new URL(url); + let newPath = parsedUrl.pathname; + if (!newPath.endsWith("/")) { + newPath = `${newPath}/`; + } + if (pathToAppend.startsWith("/")) { + pathToAppend = pathToAppend.substring(1); + } + const searchStart = pathToAppend.indexOf("?"); + if (searchStart !== -1) { + const path = pathToAppend.substring(0, searchStart); + const search = pathToAppend.substring(searchStart + 1); + newPath = newPath + path; + if (search) { + parsedUrl.search = parsedUrl.search ? `${parsedUrl.search}&${search}` : search; + } + } + else { + newPath = newPath + pathToAppend; + } + parsedUrl.pathname = newPath; + return parsedUrl.toString(); +} +function calculateQueryParameters(operationSpec, operationArguments, fallbackObject) { + var _a; + const result = new Map(); + const sequenceParams = new Set(); + if ((_a = operationSpec.queryParameters) === null || _a === void 0 ? void 0 : _a.length) { + for (const queryParameter of operationSpec.queryParameters) { + if (queryParameter.mapper.type.name === "Sequence" && queryParameter.mapper.serializedName) { + sequenceParams.add(queryParameter.mapper.serializedName); + } + let queryParameterValue = getOperationArgumentValueFromParameter(operationArguments, queryParameter, fallbackObject); + if ((queryParameterValue !== undefined && queryParameterValue !== null) || + queryParameter.mapper.required) { + queryParameterValue = operationSpec.serializer.serialize(queryParameter.mapper, queryParameterValue, getPathStringFromParameter(queryParameter)); + const delimiter = queryParameter.collectionFormat + ? CollectionFormatToDelimiterMap[queryParameter.collectionFormat] + : ""; + if (Array.isArray(queryParameterValue)) { + // replace null and undefined + queryParameterValue = queryParameterValue.map((item) => { + if (item === null || item === undefined) { + return ""; + } + return item; + }); + } + if (queryParameter.collectionFormat === "Multi" && queryParameterValue.length === 0) { + continue; + } + else if (Array.isArray(queryParameterValue) && + (queryParameter.collectionFormat === "SSV" || queryParameter.collectionFormat === "TSV")) { + queryParameterValue = queryParameterValue.join(delimiter); + } + if (!queryParameter.skipEncoding) { + if (Array.isArray(queryParameterValue)) { + queryParameterValue = queryParameterValue.map((item) => { + return encodeURIComponent(item); + }); + } + else { + queryParameterValue = encodeURIComponent(queryParameterValue); + } + } + // Join pipes and CSV *after* encoding, or the server will be upset. + if (Array.isArray(queryParameterValue) && + (queryParameter.collectionFormat === "CSV" || queryParameter.collectionFormat === "Pipes")) { + queryParameterValue = queryParameterValue.join(delimiter); + } + result.set(queryParameter.mapper.serializedName || getPathStringFromParameter(queryParameter), queryParameterValue); + } + } + } + return { + queryParams: result, + sequenceParams, + }; +} +function simpleParseQueryParams(queryString) { + const result = new Map(); + if (!queryString || queryString[0] !== "?") { + return result; + } + // remove the leading ? + queryString = queryString.slice(1); + const pairs = queryString.split("&"); + for (const pair of pairs) { + const [name, value] = pair.split("=", 2); + const existingValue = result.get(name); + if (existingValue) { + if (Array.isArray(existingValue)) { + existingValue.push(value); + } + else { + result.set(name, [existingValue, value]); + } + } + else { + result.set(name, value); + } + } + return result; +} +/** @internal */ +function appendQueryParams(url, queryParams, sequenceParams, noOverwrite = false) { + if (queryParams.size === 0) { + return url; + } + const parsedUrl = new URL(url); + // QUIRK: parsedUrl.searchParams will have their name/value pairs decoded, which + // can change their meaning to the server, such as in the case of a SAS signature. + // To avoid accidentally un-encoding a query param, we parse the key/values ourselves + const combinedParams = simpleParseQueryParams(parsedUrl.search); + for (const [name, value] of queryParams) { + const existingValue = combinedParams.get(name); + if (Array.isArray(existingValue)) { + if (Array.isArray(value)) { + existingValue.push(...value); + const valueSet = new Set(existingValue); + combinedParams.set(name, Array.from(valueSet)); + } + else { + existingValue.push(value); + } + } + else if (existingValue) { + if (Array.isArray(value)) { + value.unshift(existingValue); + } + else if (sequenceParams.has(name)) { + combinedParams.set(name, [existingValue, value]); + } + if (!noOverwrite) { + combinedParams.set(name, value); + } + } + else { + combinedParams.set(name, value); + } + } + const searchPieces = []; + for (const [name, value] of combinedParams) { + if (typeof value === "string") { + searchPieces.push(`${name}=${value}`); + } + else if (Array.isArray(value)) { + // QUIRK: If we get an array of values, include multiple key/value pairs + for (const subValue of value) { + searchPieces.push(`${name}=${subValue}`); + } + } + else { + searchPieces.push(`${name}=${value}`); + } + } + // QUIRK: we have to set search manually as searchParams will encode comma when it shouldn't. + parsedUrl.search = searchPieces.length ? `?${searchPieces.join("&")}` : ""; + return parsedUrl.toString(); +} + +// Copyright (c) Microsoft Corporation. +const logger = logger$1.createClientLogger("core-client"); + +// Copyright (c) Microsoft Corporation. +/** + * Initializes a new instance of the ServiceClient. + */ +class ServiceClient { + /** + * The ServiceClient constructor + * @param credential - The credentials used for authentication with the service. + * @param options - The service client options that govern the behavior of the client. + */ + constructor(options = {}) { + var _a, _b; + this._requestContentType = options.requestContentType; + this._endpoint = (_a = options.endpoint) !== null && _a !== void 0 ? _a : options.baseUri; + if (options.baseUri) { + logger.warning("The baseUri option for SDK Clients has been deprecated, please use endpoint instead."); + } + this._allowInsecureConnection = options.allowInsecureConnection; + this._httpClient = options.httpClient || getCachedDefaultHttpClient(); + this.pipeline = options.pipeline || createDefaultPipeline(options); + if ((_b = options.additionalPolicies) === null || _b === void 0 ? void 0 : _b.length) { + for (const { policy, position } of options.additionalPolicies) { + // Sign happens after Retry and is commonly needed to occur + // before policies that intercept post-retry. + const afterPhase = position === "perRetry" ? "Sign" : undefined; + this.pipeline.addPolicy(policy, { + afterPhase, + }); + } + } + } + /** + * Send the provided httpRequest. + */ + async sendRequest(request) { + return this.pipeline.sendRequest(this._httpClient, request); + } + /** + * Send an HTTP request that is populated using the provided OperationSpec. + * @typeParam T - The typed result of the request, based on the OperationSpec. + * @param operationArguments - The arguments that the HTTP request's templated values will be populated from. + * @param operationSpec - The OperationSpec to use to populate the httpRequest. + */ + async sendOperationRequest(operationArguments, operationSpec) { + const endpoint = operationSpec.baseUrl || this._endpoint; + if (!endpoint) { + throw new Error("If operationSpec.baseUrl is not specified, then the ServiceClient must have a endpoint string property that contains the base URL to use."); + } + // Templatized URLs sometimes reference properties on the ServiceClient child class, + // so we have to pass `this` below in order to search these properties if they're + // not part of OperationArguments + const url = getRequestUrl(endpoint, operationSpec, operationArguments, this); + const request = coreRestPipeline.createPipelineRequest({ + url, + }); + request.method = operationSpec.httpMethod; + const operationInfo = getOperationRequestInfo(request); + operationInfo.operationSpec = operationSpec; + operationInfo.operationArguments = operationArguments; + const contentType = operationSpec.contentType || this._requestContentType; + if (contentType && operationSpec.requestBody) { + request.headers.set("Content-Type", contentType); + } + const options = operationArguments.options; + if (options) { + const requestOptions = options.requestOptions; + if (requestOptions) { + if (requestOptions.timeout) { + request.timeout = requestOptions.timeout; + } + if (requestOptions.onUploadProgress) { + request.onUploadProgress = requestOptions.onUploadProgress; + } + if (requestOptions.onDownloadProgress) { + request.onDownloadProgress = requestOptions.onDownloadProgress; + } + if (requestOptions.shouldDeserialize !== undefined) { + operationInfo.shouldDeserialize = requestOptions.shouldDeserialize; + } + if (requestOptions.allowInsecureConnection) { + request.allowInsecureConnection = true; + } + } + if (options.abortSignal) { + request.abortSignal = options.abortSignal; + } + if (options.tracingOptions) { + request.tracingOptions = options.tracingOptions; + } + } + if (this._allowInsecureConnection) { + request.allowInsecureConnection = true; + } + if (request.streamResponseStatusCodes === undefined) { + request.streamResponseStatusCodes = getStreamingResponseStatusCodes(operationSpec); + } + try { + const rawResponse = await this.sendRequest(request); + const flatResponse = flattenResponse(rawResponse, operationSpec.responses[rawResponse.status]); + if (options === null || options === void 0 ? void 0 : options.onResponse) { + options.onResponse(rawResponse, flatResponse); + } + return flatResponse; + } + catch (error) { + if (typeof error === "object" && (error === null || error === void 0 ? void 0 : error.response)) { + const rawResponse = error.response; + const flatResponse = flattenResponse(rawResponse, operationSpec.responses[error.statusCode] || operationSpec.responses["default"]); + error.details = flatResponse; + if (options === null || options === void 0 ? void 0 : options.onResponse) { + options.onResponse(rawResponse, flatResponse, error); + } + } + throw error; + } + } +} +function createDefaultPipeline(options) { + const credentialScopes = getCredentialScopes(options); + const credentialOptions = options.credential && credentialScopes + ? { credentialScopes, credential: options.credential } + : undefined; + return createClientPipeline(Object.assign(Object.assign({}, options), { credentialOptions })); +} +function getCredentialScopes(options) { + if (options.credentialScopes) { + return options.credentialScopes; + } + if (options.endpoint) { + return `${options.endpoint}/.default`; + } + if (options.baseUri) { + return `${options.baseUri}/.default`; + } + if (options.credential && !options.credentialScopes) { + throw new Error(`When using credentials, the ServiceClientOptions must contain either a endpoint or a credentialScopes. Unable to create a bearerTokenAuthenticationPolicy`); + } + return undefined; +} + +// Copyright (c) Microsoft Corporation. +/** + * Converts: `Bearer a="b", c="d", Bearer d="e", f="g"`. + * Into: `[ { a: 'b', c: 'd' }, { d: 'e', f: 'g' } ]`. + * + * @internal + */ +function parseCAEChallenge(challenges) { + const bearerChallenges = `, ${challenges.trim()}`.split(", Bearer ").filter((x) => x); + return bearerChallenges.map((challenge) => { + const challengeParts = `${challenge.trim()}, `.split('", ').filter((x) => x); + const keyValuePairs = challengeParts.map((keyValue) => (([key, value]) => ({ [key]: value }))(keyValue.trim().split('="'))); + // Key-value pairs to plain object: + return keyValuePairs.reduce((a, b) => (Object.assign(Object.assign({}, a), b)), {}); + }); +} +/** + * This function can be used as a callback for the `bearerTokenAuthenticationPolicy` of `@azure/core-rest-pipeline`, to support CAE challenges: + * [Continuous Access Evaluation](https://docs.microsoft.com/azure/active-directory/conditional-access/concept-continuous-access-evaluation). + * + * Call the `bearerTokenAuthenticationPolicy` with the following options: + * + * ```ts + * import { bearerTokenAuthenticationPolicy } from "@azure/core-rest-pipeline"; + * import { authorizeRequestOnClaimChallenge } from "@azure/core-client"; + * + * const bearerTokenAuthenticationPolicy = bearerTokenAuthenticationPolicy({ + * authorizeRequestOnChallenge: authorizeRequestOnClaimChallenge + * }); + * ``` + * + * Once provided, the `bearerTokenAuthenticationPolicy` policy will internally handle Continuous Access Evaluation (CAE) challenges. + * When it can't complete a challenge it will return the 401 (unauthorized) response from ARM. + * + * Example challenge with claims: + * + * ``` + * Bearer authorization_uri="https://login.windows-ppe.net/", error="invalid_token", + * error_description="User session has been revoked", + * claims="eyJhY2Nlc3NfdG9rZW4iOnsibmJmIjp7ImVzc2VudGlhbCI6dHJ1ZSwgInZhbHVlIjoiMTYwMzc0MjgwMCJ9fX0=" + * ``` + */ +async function authorizeRequestOnClaimChallenge(onChallengeOptions) { + const { scopes, response } = onChallengeOptions; + const logger$1 = onChallengeOptions.logger || logger; + const challenge = response.headers.get("WWW-Authenticate"); + if (!challenge) { + logger$1.info(`The WWW-Authenticate header was missing. Failed to perform the Continuous Access Evaluation authentication flow.`); + return false; + } + const challenges = parseCAEChallenge(challenge) || []; + const parsedChallenge = challenges.find((x) => x.claims); + if (!parsedChallenge) { + logger$1.info(`The WWW-Authenticate header was missing the necessary "claims" to perform the Continuous Access Evaluation authentication flow.`); + return false; + } + const accessToken = await onChallengeOptions.getAccessToken(parsedChallenge.scope ? [parsedChallenge.scope] : scopes, { + claims: decodeStringToString(parsedChallenge.claims), + }); + if (!accessToken) { + return false; + } + onChallengeOptions.request.headers.set("Authorization", `Bearer ${accessToken.token}`); + return true; +} + +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. +/** + * A set of constants used internally when processing requests. + */ +const Constants = { + DefaultScope: "/.default", + /** + * Defines constants for use with HTTP headers. + */ + HeaderConstants: { + /** + * The Authorization header. + */ + AUTHORIZATION: "authorization", + }, +}; +/** + * Defines a callback to handle auth challenge for Storage APIs. + * This implements the bearer challenge process described here: https://docs.microsoft.com/rest/api/storageservices/authorize-with-azure-active-directory#bearer-challenge + * Handling has specific features for storage that departs to the general AAD challenge docs. + **/ +const authorizeRequestOnTenantChallenge = async (challengeOptions) => { + const requestOptions = requestToOptions(challengeOptions.request); + const challenge = getChallenge(challengeOptions.response); + if (challenge) { + const challengeInfo = parseChallenge(challenge); + const challengeScopes = buildScopes(challengeOptions, challengeInfo); + const tenantId = extractTenantId(challengeInfo); + const accessToken = await challengeOptions.getAccessToken(challengeScopes, Object.assign(Object.assign({}, requestOptions), { tenantId })); + if (!accessToken) { + return false; + } + challengeOptions.request.headers.set(Constants.HeaderConstants.AUTHORIZATION, `Bearer ${accessToken.token}`); + return true; + } + return false; +}; +/** + * Extracts the tenant id from the challenge information + * The tenant id is contained in the authorization_uri as the first + * path part. + */ +function extractTenantId(challengeInfo) { + const parsedAuthUri = new URL(challengeInfo.authorization_uri); + const pathSegments = parsedAuthUri.pathname.split("/"); + const tenantId = pathSegments[1]; + return tenantId; +} +/** + * Builds the authentication scopes based on the information that comes in the + * challenge information. Scopes url is present in the resource_id, if it is empty + * we keep using the original scopes. + */ +function buildScopes(challengeOptions, challengeInfo) { + if (!challengeInfo.resource_uri) { + return challengeOptions.scopes; + } + const challengeScopes = new URL(challengeInfo.resource_uri); + challengeScopes.pathname = Constants.DefaultScope; + return [challengeScopes.toString()]; +} +/** + * We will retrieve the challenge only if the response status code was 401, + * and if the response contained the header "WWW-Authenticate" with a non-empty value. + */ +function getChallenge(response) { + const challenge = response.headers.get("WWW-Authenticate"); + if (response.status === 401 && challenge) { + return challenge; + } + return; +} +/** + * Converts: `Bearer a="b" c="d"`. + * Into: `[ { a: 'b', c: 'd' }]`. + * + * @internal + */ +function parseChallenge(challenge) { + const bearerChallenge = challenge.slice("Bearer ".length); + const challengeParts = `${bearerChallenge.trim()} `.split(" ").filter((x) => x); + const keyValuePairs = challengeParts.map((keyValue) => (([key, value]) => ({ [key]: value }))(keyValue.trim().split("="))); + // Key-value pairs to plain object: + return keyValuePairs.reduce((a, b) => (Object.assign(Object.assign({}, a), b)), {}); +} +/** + * Extracts the options form a Pipeline Request for later re-use + */ +function requestToOptions(request) { + return { + abortSignal: request.abortSignal, + requestOptions: { + timeout: request.timeout, + }, + tracingOptions: request.tracingOptions, + }; +} + +exports.MapperTypeNames = MapperTypeNames; +exports.ServiceClient = ServiceClient; +exports.XML_ATTRKEY = XML_ATTRKEY; +exports.XML_CHARKEY = XML_CHARKEY; +exports.authorizeRequestOnClaimChallenge = authorizeRequestOnClaimChallenge; +exports.authorizeRequestOnTenantChallenge = authorizeRequestOnTenantChallenge; +exports.createClientPipeline = createClientPipeline; +exports.createSerializer = createSerializer; +exports.deserializationPolicy = deserializationPolicy; +exports.deserializationPolicyName = deserializationPolicyName; +exports.serializationPolicy = serializationPolicy; +exports.serializationPolicyName = serializationPolicyName; +//# sourceMappingURL=index.js.map + + +/***/ }), + +/***/ 7094: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ value: true })); + +var logger$1 = __nccwpck_require__(3233); +var abortController = __nccwpck_require__(2557); +var coreUtil = __nccwpck_require__(1333); + +// Copyright (c) Microsoft Corporation. +/** + * The `@azure/logger` configuration for this package. + * @internal + */ +const logger = logger$1.createClientLogger("core-lro"); + +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. +/** + * The default time interval to wait before sending the next polling request. + */ +const POLL_INTERVAL_IN_MS = 2000; +/** + * The closed set of terminal states. + */ +const terminalStates = ["succeeded", "canceled", "failed"]; + +// Copyright (c) Microsoft Corporation. +/** + * Deserializes the state + */ +function deserializeState(serializedState) { + try { + return JSON.parse(serializedState).state; + } + catch (e) { + throw new Error(`Unable to deserialize input state: ${serializedState}`); + } +} +function setStateError(inputs) { + const { state, stateProxy, isOperationError } = inputs; + return (error) => { + if (isOperationError(error)) { + stateProxy.setError(state, error); + stateProxy.setFailed(state); + } + throw error; + }; +} +function appendReadableErrorMessage(currentMessage, innerMessage) { + let message = currentMessage; + if (message.slice(-1) !== ".") { + message = message + "."; + } + return message + " " + innerMessage; +} +function simplifyError(err) { + let message = err.message; + let code = err.code; + let curErr = err; + while (curErr.innererror) { + curErr = curErr.innererror; + code = curErr.code; + message = appendReadableErrorMessage(message, curErr.message); + } + return { + code, + message, + }; +} +function processOperationStatus(result) { + const { state, stateProxy, status, isDone, processResult, getError, response, setErrorAsResult } = result; + switch (status) { + case "succeeded": { + stateProxy.setSucceeded(state); + break; + } + case "failed": { + const err = getError === null || getError === void 0 ? void 0 : getError(response); + let postfix = ""; + if (err) { + const { code, message } = simplifyError(err); + postfix = `. ${code}. ${message}`; + } + const errStr = `The long-running operation has failed${postfix}`; + stateProxy.setError(state, new Error(errStr)); + stateProxy.setFailed(state); + logger.warning(errStr); + break; + } + case "canceled": { + stateProxy.setCanceled(state); + break; + } + } + if ((isDone === null || isDone === void 0 ? void 0 : isDone(response, state)) || + (isDone === undefined && + ["succeeded", "canceled"].concat(setErrorAsResult ? [] : ["failed"]).includes(status))) { + stateProxy.setResult(state, buildResult({ + response, + state, + processResult, + })); + } +} +function buildResult(inputs) { + const { processResult, response, state } = inputs; + return processResult ? processResult(response, state) : response; +} +/** + * Initiates the long-running operation. + */ +async function initOperation(inputs) { + const { init, stateProxy, processResult, getOperationStatus, withOperationLocation, setErrorAsResult, } = inputs; + const { operationLocation, resourceLocation, metadata, response } = await init(); + if (operationLocation) + withOperationLocation === null || withOperationLocation === void 0 ? void 0 : withOperationLocation(operationLocation, false); + const config = { + metadata, + operationLocation, + resourceLocation, + }; + logger.verbose(`LRO: Operation description:`, config); + const state = stateProxy.initState(config); + const status = getOperationStatus({ response, state, operationLocation }); + processOperationStatus({ state, status, stateProxy, response, setErrorAsResult, processResult }); + return state; +} +async function pollOperationHelper(inputs) { + const { poll, state, stateProxy, operationLocation, getOperationStatus, getResourceLocation, isOperationError, options, } = inputs; + const response = await poll(operationLocation, options).catch(setStateError({ + state, + stateProxy, + isOperationError, + })); + const status = getOperationStatus(response, state); + logger.verbose(`LRO: Status:\n\tPolling from: ${state.config.operationLocation}\n\tOperation status: ${status}\n\tPolling status: ${terminalStates.includes(status) ? "Stopped" : "Running"}`); + if (status === "succeeded") { + const resourceLocation = getResourceLocation(response, state); + if (resourceLocation !== undefined) { + return { + response: await poll(resourceLocation).catch(setStateError({ state, stateProxy, isOperationError })), + status, + }; + } + } + return { response, status }; +} +/** Polls the long-running operation. */ +async function pollOperation(inputs) { + const { poll, state, stateProxy, options, getOperationStatus, getResourceLocation, getOperationLocation, isOperationError, withOperationLocation, getPollingInterval, processResult, getError, updateState, setDelay, isDone, setErrorAsResult, } = inputs; + const { operationLocation } = state.config; + if (operationLocation !== undefined) { + const { response, status } = await pollOperationHelper({ + poll, + getOperationStatus, + state, + stateProxy, + operationLocation, + getResourceLocation, + isOperationError, + options, + }); + processOperationStatus({ + status, + response, + state, + stateProxy, + isDone, + processResult, + getError, + setErrorAsResult, + }); + if (!terminalStates.includes(status)) { + const intervalInMs = getPollingInterval === null || getPollingInterval === void 0 ? void 0 : getPollingInterval(response); + if (intervalInMs) + setDelay(intervalInMs); + const location = getOperationLocation === null || getOperationLocation === void 0 ? void 0 : getOperationLocation(response, state); + if (location !== undefined) { + const isUpdated = operationLocation !== location; + state.config.operationLocation = location; + withOperationLocation === null || withOperationLocation === void 0 ? void 0 : withOperationLocation(location, isUpdated); + } + else + withOperationLocation === null || withOperationLocation === void 0 ? void 0 : withOperationLocation(operationLocation, false); + } + updateState === null || updateState === void 0 ? void 0 : updateState(state, response); + } +} + +// Copyright (c) Microsoft Corporation. +function getOperationLocationPollingUrl(inputs) { + const { azureAsyncOperation, operationLocation } = inputs; + return operationLocation !== null && operationLocation !== void 0 ? operationLocation : azureAsyncOperation; +} +function getLocationHeader(rawResponse) { + return rawResponse.headers["location"]; +} +function getOperationLocationHeader(rawResponse) { + return rawResponse.headers["operation-location"]; +} +function getAzureAsyncOperationHeader(rawResponse) { + return rawResponse.headers["azure-asyncoperation"]; +} +function findResourceLocation(inputs) { + var _a; + const { location, requestMethod, requestPath, resourceLocationConfig } = inputs; + switch (requestMethod) { + case "PUT": { + return requestPath; + } + case "DELETE": { + return undefined; + } + case "PATCH": { + return (_a = getDefault()) !== null && _a !== void 0 ? _a : requestPath; + } + default: { + return getDefault(); + } + } + function getDefault() { + switch (resourceLocationConfig) { + case "azure-async-operation": { + return undefined; + } + case "original-uri": { + return requestPath; + } + case "location": + default: { + return location; + } + } + } +} +function inferLroMode(inputs) { + const { rawResponse, requestMethod, requestPath, resourceLocationConfig } = inputs; + const operationLocation = getOperationLocationHeader(rawResponse); + const azureAsyncOperation = getAzureAsyncOperationHeader(rawResponse); + const pollingUrl = getOperationLocationPollingUrl({ operationLocation, azureAsyncOperation }); + const location = getLocationHeader(rawResponse); + const normalizedRequestMethod = requestMethod === null || requestMethod === void 0 ? void 0 : requestMethod.toLocaleUpperCase(); + if (pollingUrl !== undefined) { + return { + mode: "OperationLocation", + operationLocation: pollingUrl, + resourceLocation: findResourceLocation({ + requestMethod: normalizedRequestMethod, + location, + requestPath, + resourceLocationConfig, + }), + }; + } + else if (location !== undefined) { + return { + mode: "ResourceLocation", + operationLocation: location, + }; + } + else if (normalizedRequestMethod === "PUT" && requestPath) { + return { + mode: "Body", + operationLocation: requestPath, + }; + } + else { + return undefined; + } +} +function transformStatus(inputs) { + const { status, statusCode } = inputs; + if (typeof status !== "string" && status !== undefined) { + throw new Error(`Polling was unsuccessful. Expected status to have a string value or no value but it has instead: ${status}. This doesn't necessarily indicate the operation has failed. Check your Azure subscription or resource status for more information.`); + } + switch (status === null || status === void 0 ? void 0 : status.toLocaleLowerCase()) { + case undefined: + return toOperationStatus(statusCode); + case "succeeded": + return "succeeded"; + case "failed": + return "failed"; + case "running": + case "accepted": + case "started": + case "canceling": + case "cancelling": + return "running"; + case "canceled": + case "cancelled": + return "canceled"; + default: { + logger.verbose(`LRO: unrecognized operation status: ${status}`); + return status; + } + } +} +function getStatus(rawResponse) { + var _a; + const { status } = (_a = rawResponse.body) !== null && _a !== void 0 ? _a : {}; + return transformStatus({ status, statusCode: rawResponse.statusCode }); +} +function getProvisioningState(rawResponse) { + var _a, _b; + const { properties, provisioningState } = (_a = rawResponse.body) !== null && _a !== void 0 ? _a : {}; + const status = (_b = properties === null || properties === void 0 ? void 0 : properties.provisioningState) !== null && _b !== void 0 ? _b : provisioningState; + return transformStatus({ status, statusCode: rawResponse.statusCode }); +} +function toOperationStatus(statusCode) { + if (statusCode === 202) { + return "running"; + } + else if (statusCode < 300) { + return "succeeded"; + } + else { + return "failed"; + } +} +function parseRetryAfter({ rawResponse }) { + const retryAfter = rawResponse.headers["retry-after"]; + if (retryAfter !== undefined) { + // Retry-After header value is either in HTTP date format, or in seconds + const retryAfterInSeconds = parseInt(retryAfter); + return isNaN(retryAfterInSeconds) + ? calculatePollingIntervalFromDate(new Date(retryAfter)) + : retryAfterInSeconds * 1000; + } + return undefined; +} +function getErrorFromResponse(response) { + const error = response.flatResponse.error; + if (!error) { + logger.warning(`The long-running operation failed but there is no error property in the response's body`); + return; + } + if (!error.code || !error.message) { + logger.warning(`The long-running operation failed but the error property in the response's body doesn't contain code or message`); + return; + } + return error; +} +function calculatePollingIntervalFromDate(retryAfterDate) { + const timeNow = Math.floor(new Date().getTime()); + const retryAfterTime = retryAfterDate.getTime(); + if (timeNow < retryAfterTime) { + return retryAfterTime - timeNow; + } + return undefined; +} +function getStatusFromInitialResponse(inputs) { + const { response, state, operationLocation } = inputs; + function helper() { + var _a; + const mode = (_a = state.config.metadata) === null || _a === void 0 ? void 0 : _a["mode"]; + switch (mode) { + case undefined: + return toOperationStatus(response.rawResponse.statusCode); + case "Body": + return getOperationStatus(response, state); + default: + return "running"; + } + } + const status = helper(); + return status === "running" && operationLocation === undefined ? "succeeded" : status; +} +/** + * Initiates the long-running operation. + */ +async function initHttpOperation(inputs) { + const { stateProxy, resourceLocationConfig, processResult, lro, setErrorAsResult } = inputs; + return initOperation({ + init: async () => { + const response = await lro.sendInitialRequest(); + const config = inferLroMode({ + rawResponse: response.rawResponse, + requestPath: lro.requestPath, + requestMethod: lro.requestMethod, + resourceLocationConfig, + }); + return Object.assign({ response, operationLocation: config === null || config === void 0 ? void 0 : config.operationLocation, resourceLocation: config === null || config === void 0 ? void 0 : config.resourceLocation }, ((config === null || config === void 0 ? void 0 : config.mode) ? { metadata: { mode: config.mode } } : {})); + }, + stateProxy, + processResult: processResult + ? ({ flatResponse }, state) => processResult(flatResponse, state) + : ({ flatResponse }) => flatResponse, + getOperationStatus: getStatusFromInitialResponse, + setErrorAsResult, + }); +} +function getOperationLocation({ rawResponse }, state) { + var _a; + const mode = (_a = state.config.metadata) === null || _a === void 0 ? void 0 : _a["mode"]; + switch (mode) { + case "OperationLocation": { + return getOperationLocationPollingUrl({ + operationLocation: getOperationLocationHeader(rawResponse), + azureAsyncOperation: getAzureAsyncOperationHeader(rawResponse), + }); + } + case "ResourceLocation": { + return getLocationHeader(rawResponse); + } + case "Body": + default: { + return undefined; + } + } +} +function getOperationStatus({ rawResponse }, state) { + var _a; + const mode = (_a = state.config.metadata) === null || _a === void 0 ? void 0 : _a["mode"]; + switch (mode) { + case "OperationLocation": { + return getStatus(rawResponse); + } + case "ResourceLocation": { + return toOperationStatus(rawResponse.statusCode); + } + case "Body": { + return getProvisioningState(rawResponse); + } + default: + throw new Error(`Internal error: Unexpected operation mode: ${mode}`); + } +} +function getResourceLocation({ flatResponse }, state) { + if (typeof flatResponse === "object") { + const resourceLocation = flatResponse.resourceLocation; + if (resourceLocation !== undefined) { + state.config.resourceLocation = resourceLocation; + } + } + return state.config.resourceLocation; +} +function isOperationError(e) { + return e.name === "RestError"; +} +/** Polls the long-running operation. */ +async function pollHttpOperation(inputs) { + const { lro, stateProxy, options, processResult, updateState, setDelay, state, setErrorAsResult, } = inputs; + return pollOperation({ + state, + stateProxy, + setDelay, + processResult: processResult + ? ({ flatResponse }, inputState) => processResult(flatResponse, inputState) + : ({ flatResponse }) => flatResponse, + getError: getErrorFromResponse, + updateState, + getPollingInterval: parseRetryAfter, + getOperationLocation, + getOperationStatus, + isOperationError, + getResourceLocation, + options, + /** + * The expansion here is intentional because `lro` could be an object that + * references an inner this, so we need to preserve a reference to it. + */ + poll: async (location, inputOptions) => lro.sendPollRequest(location, inputOptions), + setErrorAsResult, + }); +} + +// Copyright (c) Microsoft Corporation. +const createStateProxy$1 = () => ({ + /** + * The state at this point is created to be of type OperationState. + * It will be updated later to be of type TState when the + * customer-provided callback, `updateState`, is called during polling. + */ + initState: (config) => ({ status: "running", config }), + setCanceled: (state) => (state.status = "canceled"), + setError: (state, error) => (state.error = error), + setResult: (state, result) => (state.result = result), + setRunning: (state) => (state.status = "running"), + setSucceeded: (state) => (state.status = "succeeded"), + setFailed: (state) => (state.status = "failed"), + getError: (state) => state.error, + getResult: (state) => state.result, + isCanceled: (state) => state.status === "canceled", + isFailed: (state) => state.status === "failed", + isRunning: (state) => state.status === "running", + isSucceeded: (state) => state.status === "succeeded", +}); +/** + * Returns a poller factory. + */ +function buildCreatePoller(inputs) { + const { getOperationLocation, getStatusFromInitialResponse, getStatusFromPollResponse, isOperationError, getResourceLocation, getPollingInterval, getError, resolveOnUnsuccessful, } = inputs; + return async ({ init, poll }, options) => { + const { processResult, updateState, withOperationLocation: withOperationLocationCallback, intervalInMs = POLL_INTERVAL_IN_MS, restoreFrom, } = options || {}; + const stateProxy = createStateProxy$1(); + const withOperationLocation = withOperationLocationCallback + ? (() => { + let called = false; + return (operationLocation, isUpdated) => { + if (isUpdated) + withOperationLocationCallback(operationLocation); + else if (!called) + withOperationLocationCallback(operationLocation); + called = true; + }; + })() + : undefined; + const state = restoreFrom + ? deserializeState(restoreFrom) + : await initOperation({ + init, + stateProxy, + processResult, + getOperationStatus: getStatusFromInitialResponse, + withOperationLocation, + setErrorAsResult: !resolveOnUnsuccessful, + }); + let resultPromise; + const abortController$1 = new abortController.AbortController(); + const handlers = new Map(); + const handleProgressEvents = async () => handlers.forEach((h) => h(state)); + const cancelErrMsg = "Operation was canceled"; + let currentPollIntervalInMs = intervalInMs; + const poller = { + getOperationState: () => state, + getResult: () => state.result, + isDone: () => ["succeeded", "failed", "canceled"].includes(state.status), + isStopped: () => resultPromise === undefined, + stopPolling: () => { + abortController$1.abort(); + }, + toString: () => JSON.stringify({ + state, + }), + onProgress: (callback) => { + const s = Symbol(); + handlers.set(s, callback); + return () => handlers.delete(s); + }, + pollUntilDone: (pollOptions) => (resultPromise !== null && resultPromise !== void 0 ? resultPromise : (resultPromise = (async () => { + const { abortSignal: inputAbortSignal } = pollOptions || {}; + const { signal: abortSignal } = inputAbortSignal + ? new abortController.AbortController([inputAbortSignal, abortController$1.signal]) + : abortController$1; + if (!poller.isDone()) { + await poller.poll({ abortSignal }); + while (!poller.isDone()) { + await coreUtil.delay(currentPollIntervalInMs, { abortSignal }); + await poller.poll({ abortSignal }); + } + } + if (resolveOnUnsuccessful) { + return poller.getResult(); + } + else { + switch (state.status) { + case "succeeded": + return poller.getResult(); + case "canceled": + throw new Error(cancelErrMsg); + case "failed": + throw state.error; + case "notStarted": + case "running": + throw new Error(`Polling completed without succeeding or failing`); + } + } + })().finally(() => { + resultPromise = undefined; + }))), + async poll(pollOptions) { + if (resolveOnUnsuccessful) { + if (poller.isDone()) + return; + } + else { + switch (state.status) { + case "succeeded": + return; + case "canceled": + throw new Error(cancelErrMsg); + case "failed": + throw state.error; + } + } + await pollOperation({ + poll, + state, + stateProxy, + getOperationLocation, + isOperationError, + withOperationLocation, + getPollingInterval, + getOperationStatus: getStatusFromPollResponse, + getResourceLocation, + processResult, + getError, + updateState, + options: pollOptions, + setDelay: (pollIntervalInMs) => { + currentPollIntervalInMs = pollIntervalInMs; + }, + setErrorAsResult: !resolveOnUnsuccessful, + }); + await handleProgressEvents(); + if (!resolveOnUnsuccessful) { + switch (state.status) { + case "canceled": + throw new Error(cancelErrMsg); + case "failed": + throw state.error; + } + } + }, + }; + return poller; + }; +} + +// Copyright (c) Microsoft Corporation. +/** + * Creates a poller that can be used to poll a long-running operation. + * @param lro - Description of the long-running operation + * @param options - options to configure the poller + * @returns an initialized poller + */ +async function createHttpPoller(lro, options) { + const { resourceLocationConfig, intervalInMs, processResult, restoreFrom, updateState, withOperationLocation, resolveOnUnsuccessful = false, } = options || {}; + return buildCreatePoller({ + getStatusFromInitialResponse, + getStatusFromPollResponse: getOperationStatus, + isOperationError, + getOperationLocation, + getResourceLocation, + getPollingInterval: parseRetryAfter, + getError: getErrorFromResponse, + resolveOnUnsuccessful, + })({ + init: async () => { + const response = await lro.sendInitialRequest(); + const config = inferLroMode({ + rawResponse: response.rawResponse, + requestPath: lro.requestPath, + requestMethod: lro.requestMethod, + resourceLocationConfig, + }); + return Object.assign({ response, operationLocation: config === null || config === void 0 ? void 0 : config.operationLocation, resourceLocation: config === null || config === void 0 ? void 0 : config.resourceLocation }, ((config === null || config === void 0 ? void 0 : config.mode) ? { metadata: { mode: config.mode } } : {})); + }, + poll: lro.sendPollRequest, + }, { + intervalInMs, + withOperationLocation, + restoreFrom, + updateState, + processResult: processResult + ? ({ flatResponse }, state) => processResult(flatResponse, state) + : ({ flatResponse }) => flatResponse, + }); +} + +// Copyright (c) Microsoft Corporation. +const createStateProxy = () => ({ + initState: (config) => ({ config, isStarted: true }), + setCanceled: (state) => (state.isCancelled = true), + setError: (state, error) => (state.error = error), + setResult: (state, result) => (state.result = result), + setRunning: (state) => (state.isStarted = true), + setSucceeded: (state) => (state.isCompleted = true), + setFailed: () => { + /** empty body */ + }, + getError: (state) => state.error, + getResult: (state) => state.result, + isCanceled: (state) => !!state.isCancelled, + isFailed: (state) => !!state.error, + isRunning: (state) => !!state.isStarted, + isSucceeded: (state) => Boolean(state.isCompleted && !state.isCancelled && !state.error), +}); +class GenericPollOperation { + constructor(state, lro, setErrorAsResult, lroResourceLocationConfig, processResult, updateState, isDone) { + this.state = state; + this.lro = lro; + this.setErrorAsResult = setErrorAsResult; + this.lroResourceLocationConfig = lroResourceLocationConfig; + this.processResult = processResult; + this.updateState = updateState; + this.isDone = isDone; + } + setPollerConfig(pollerConfig) { + this.pollerConfig = pollerConfig; + } + async update(options) { + var _a; + const stateProxy = createStateProxy(); + if (!this.state.isStarted) { + this.state = Object.assign(Object.assign({}, this.state), (await initHttpOperation({ + lro: this.lro, + stateProxy, + resourceLocationConfig: this.lroResourceLocationConfig, + processResult: this.processResult, + setErrorAsResult: this.setErrorAsResult, + }))); + } + const updateState = this.updateState; + const isDone = this.isDone; + if (!this.state.isCompleted && this.state.error === undefined) { + await pollHttpOperation({ + lro: this.lro, + state: this.state, + stateProxy, + processResult: this.processResult, + updateState: updateState + ? (state, { rawResponse }) => updateState(state, rawResponse) + : undefined, + isDone: isDone + ? ({ flatResponse }, state) => isDone(flatResponse, state) + : undefined, + options, + setDelay: (intervalInMs) => { + this.pollerConfig.intervalInMs = intervalInMs; + }, + setErrorAsResult: this.setErrorAsResult, + }); + } + (_a = options === null || options === void 0 ? void 0 : options.fireProgress) === null || _a === void 0 ? void 0 : _a.call(options, this.state); + return this; + } + async cancel() { + logger.error("`cancelOperation` is deprecated because it wasn't implemented"); + return this; + } + /** + * Serializes the Poller operation. + */ + toString() { + return JSON.stringify({ + state: this.state, + }); + } +} + +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. +/** + * When a poller is manually stopped through the `stopPolling` method, + * the poller will be rejected with an instance of the PollerStoppedError. + */ +class PollerStoppedError extends Error { + constructor(message) { + super(message); + this.name = "PollerStoppedError"; + Object.setPrototypeOf(this, PollerStoppedError.prototype); + } +} +/** + * When the operation is cancelled, the poller will be rejected with an instance + * of the PollerCancelledError. + */ +class PollerCancelledError extends Error { + constructor(message) { + super(message); + this.name = "PollerCancelledError"; + Object.setPrototypeOf(this, PollerCancelledError.prototype); + } +} +/** + * A class that represents the definition of a program that polls through consecutive requests + * until it reaches a state of completion. + * + * A poller can be executed manually, by polling request by request by calling to the `poll()` method repeatedly, until its operation is completed. + * It also provides a way to wait until the operation completes, by calling `pollUntilDone()` and waiting until the operation finishes. + * Pollers can also request the cancellation of the ongoing process to whom is providing the underlying long running operation. + * + * ```ts + * const poller = new MyPoller(); + * + * // Polling just once: + * await poller.poll(); + * + * // We can try to cancel the request here, by calling: + * // + * // await poller.cancelOperation(); + * // + * + * // Getting the final result: + * const result = await poller.pollUntilDone(); + * ``` + * + * The Poller is defined by two types, a type representing the state of the poller, which + * must include a basic set of properties from `PollOperationState`, + * and a return type defined by `TResult`, which can be anything. + * + * The Poller class implements the `PollerLike` interface, which allows poller implementations to avoid having + * to export the Poller's class directly, and instead only export the already instantiated poller with the PollerLike type. + * + * ```ts + * class Client { + * public async makePoller: PollerLike { + * const poller = new MyPoller({}); + * // It might be preferred to return the poller after the first request is made, + * // so that some information can be obtained right away. + * await poller.poll(); + * return poller; + * } + * } + * + * const poller: PollerLike = myClient.makePoller(); + * ``` + * + * A poller can be created through its constructor, then it can be polled until it's completed. + * At any point in time, the state of the poller can be obtained without delay through the getOperationState method. + * At any point in time, the intermediate forms of the result type can be requested without delay. + * Once the underlying operation is marked as completed, the poller will stop and the final value will be returned. + * + * ```ts + * const poller = myClient.makePoller(); + * const state: MyOperationState = poller.getOperationState(); + * + * // The intermediate result can be obtained at any time. + * const result: MyResult | undefined = poller.getResult(); + * + * // The final result can only be obtained after the poller finishes. + * const result: MyResult = await poller.pollUntilDone(); + * ``` + * + */ +// eslint-disable-next-line no-use-before-define +class Poller { + /** + * A poller needs to be initialized by passing in at least the basic properties of the `PollOperation`. + * + * When writing an implementation of a Poller, this implementation needs to deal with the initialization + * of any custom state beyond the basic definition of the poller. The basic poller assumes that the poller's + * operation has already been defined, at least its basic properties. The code below shows how to approach + * the definition of the constructor of a new custom poller. + * + * ```ts + * export class MyPoller extends Poller { + * constructor({ + * // Anything you might need outside of the basics + * }) { + * let state: MyOperationState = { + * privateProperty: private, + * publicProperty: public, + * }; + * + * const operation = { + * state, + * update, + * cancel, + * toString + * } + * + * // Sending the operation to the parent's constructor. + * super(operation); + * + * // You can assign more local properties here. + * } + * } + * ``` + * + * Inside of this constructor, a new promise is created. This will be used to + * tell the user when the poller finishes (see `pollUntilDone()`). The promise's + * resolve and reject methods are also used internally to control when to resolve + * or reject anyone waiting for the poller to finish. + * + * The constructor of a custom implementation of a poller is where any serialized version of + * a previous poller's operation should be deserialized into the operation sent to the + * base constructor. For example: + * + * ```ts + * export class MyPoller extends Poller { + * constructor( + * baseOperation: string | undefined + * ) { + * let state: MyOperationState = {}; + * if (baseOperation) { + * state = { + * ...JSON.parse(baseOperation).state, + * ...state + * }; + * } + * const operation = { + * state, + * // ... + * } + * super(operation); + * } + * } + * ``` + * + * @param operation - Must contain the basic properties of `PollOperation`. + */ + constructor(operation) { + /** controls whether to throw an error if the operation failed or was canceled. */ + this.resolveOnUnsuccessful = false; + this.stopped = true; + this.pollProgressCallbacks = []; + this.operation = operation; + this.promise = new Promise((resolve, reject) => { + this.resolve = resolve; + this.reject = reject; + }); + // This prevents the UnhandledPromiseRejectionWarning in node.js from being thrown. + // The above warning would get thrown if `poller.poll` is called, it returns an error, + // and pullUntilDone did not have a .catch or await try/catch on it's return value. + this.promise.catch(() => { + /* intentionally blank */ + }); + } + /** + * Starts a loop that will break only if the poller is done + * or if the poller is stopped. + */ + async startPolling(pollOptions = {}) { + if (this.stopped) { + this.stopped = false; + } + while (!this.isStopped() && !this.isDone()) { + await this.poll(pollOptions); + await this.delay(); + } + } + /** + * pollOnce does one polling, by calling to the update method of the underlying + * poll operation to make any relevant change effective. + * + * It only optionally receives an object with an abortSignal property, from \@azure/abort-controller's AbortSignalLike. + * + * @param options - Optional properties passed to the operation's update method. + */ + async pollOnce(options = {}) { + if (!this.isDone()) { + this.operation = await this.operation.update({ + abortSignal: options.abortSignal, + fireProgress: this.fireProgress.bind(this), + }); + } + this.processUpdatedState(); + } + /** + * fireProgress calls the functions passed in via onProgress the method of the poller. + * + * It loops over all of the callbacks received from onProgress, and executes them, sending them + * the current operation state. + * + * @param state - The current operation state. + */ + fireProgress(state) { + for (const callback of this.pollProgressCallbacks) { + callback(state); + } + } + /** + * Invokes the underlying operation's cancel method. + */ + async cancelOnce(options = {}) { + this.operation = await this.operation.cancel(options); + } + /** + * Returns a promise that will resolve once a single polling request finishes. + * It does this by calling the update method of the Poller's operation. + * + * It only optionally receives an object with an abortSignal property, from \@azure/abort-controller's AbortSignalLike. + * + * @param options - Optional properties passed to the operation's update method. + */ + poll(options = {}) { + if (!this.pollOncePromise) { + this.pollOncePromise = this.pollOnce(options); + const clearPollOncePromise = () => { + this.pollOncePromise = undefined; + }; + this.pollOncePromise.then(clearPollOncePromise, clearPollOncePromise).catch(this.reject); + } + return this.pollOncePromise; + } + processUpdatedState() { + if (this.operation.state.error) { + this.stopped = true; + if (!this.resolveOnUnsuccessful) { + this.reject(this.operation.state.error); + throw this.operation.state.error; + } + } + if (this.operation.state.isCancelled) { + this.stopped = true; + if (!this.resolveOnUnsuccessful) { + const error = new PollerCancelledError("Operation was canceled"); + this.reject(error); + throw error; + } + } + if (this.isDone() && this.resolve) { + // If the poller has finished polling, this means we now have a result. + // However, it can be the case that TResult is instantiated to void, so + // we are not expecting a result anyway. To assert that we might not + // have a result eventually after finishing polling, we cast the result + // to TResult. + this.resolve(this.getResult()); + } + } + /** + * Returns a promise that will resolve once the underlying operation is completed. + */ + async pollUntilDone(pollOptions = {}) { + if (this.stopped) { + this.startPolling(pollOptions).catch(this.reject); + } + // This is needed because the state could have been updated by + // `cancelOperation`, e.g. the operation is canceled or an error occurred. + this.processUpdatedState(); + return this.promise; + } + /** + * Invokes the provided callback after each polling is completed, + * sending the current state of the poller's operation. + * + * It returns a method that can be used to stop receiving updates on the given callback function. + */ + onProgress(callback) { + this.pollProgressCallbacks.push(callback); + return () => { + this.pollProgressCallbacks = this.pollProgressCallbacks.filter((c) => c !== callback); + }; + } + /** + * Returns true if the poller has finished polling. + */ + isDone() { + const state = this.operation.state; + return Boolean(state.isCompleted || state.isCancelled || state.error); + } + /** + * Stops the poller from continuing to poll. + */ + stopPolling() { + if (!this.stopped) { + this.stopped = true; + if (this.reject) { + this.reject(new PollerStoppedError("This poller is already stopped")); + } + } + } + /** + * Returns true if the poller is stopped. + */ + isStopped() { + return this.stopped; + } + /** + * Attempts to cancel the underlying operation. + * + * It only optionally receives an object with an abortSignal property, from \@azure/abort-controller's AbortSignalLike. + * + * If it's called again before it finishes, it will throw an error. + * + * @param options - Optional properties passed to the operation's update method. + */ + cancelOperation(options = {}) { + if (!this.cancelPromise) { + this.cancelPromise = this.cancelOnce(options); + } + else if (options.abortSignal) { + throw new Error("A cancel request is currently pending"); + } + return this.cancelPromise; + } + /** + * Returns the state of the operation. + * + * Even though TState will be the same type inside any of the methods of any extension of the Poller class, + * implementations of the pollers can customize what's shared with the public by writing their own + * version of the `getOperationState` method, and by defining two types, one representing the internal state of the poller + * and a public type representing a safe to share subset of the properties of the internal state. + * Their definition of getOperationState can then return their public type. + * + * Example: + * + * ```ts + * // Let's say we have our poller's operation state defined as: + * interface MyOperationState extends PollOperationState { + * privateProperty?: string; + * publicProperty?: string; + * } + * + * // To allow us to have a true separation of public and private state, we have to define another interface: + * interface PublicState extends PollOperationState { + * publicProperty?: string; + * } + * + * // Then, we define our Poller as follows: + * export class MyPoller extends Poller { + * // ... More content is needed here ... + * + * public getOperationState(): PublicState { + * const state: PublicState = this.operation.state; + * return { + * // Properties from PollOperationState + * isStarted: state.isStarted, + * isCompleted: state.isCompleted, + * isCancelled: state.isCancelled, + * error: state.error, + * result: state.result, + * + * // The only other property needed by PublicState. + * publicProperty: state.publicProperty + * } + * } + * } + * ``` + * + * You can see this in the tests of this repository, go to the file: + * `../test/utils/testPoller.ts` + * and look for the getOperationState implementation. + */ + getOperationState() { + return this.operation.state; + } + /** + * Returns the result value of the operation, + * regardless of the state of the poller. + * It can return undefined or an incomplete form of the final TResult value + * depending on the implementation. + */ + getResult() { + const state = this.operation.state; + return state.result; + } + /** + * Returns a serialized version of the poller's operation + * by invoking the operation's toString method. + */ + toString() { + return this.operation.toString(); + } +} + +// Copyright (c) Microsoft Corporation. +/** + * The LRO Engine, a class that performs polling. + */ +class LroEngine extends Poller { + constructor(lro, options) { + const { intervalInMs = POLL_INTERVAL_IN_MS, resumeFrom, resolveOnUnsuccessful = false, isDone, lroResourceLocationConfig, processResult, updateState, } = options || {}; + const state = resumeFrom + ? deserializeState(resumeFrom) + : {}; + const operation = new GenericPollOperation(state, lro, !resolveOnUnsuccessful, lroResourceLocationConfig, processResult, updateState, isDone); + super(operation); + this.resolveOnUnsuccessful = resolveOnUnsuccessful; + this.config = { intervalInMs: intervalInMs }; + operation.setPollerConfig(this.config); + } + /** + * The method used by the poller to wait before attempting to update its operation. + */ + delay() { + return new Promise((resolve) => setTimeout(() => resolve(), this.config.intervalInMs)); + } +} + +exports.LroEngine = LroEngine; +exports.Poller = Poller; +exports.PollerCancelledError = PollerCancelledError; +exports.PollerStoppedError = PollerStoppedError; +exports.createHttpPoller = createHttpPoller; +//# sourceMappingURL=index.js.map + + +/***/ }), + +/***/ 8121: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ value: true })); + +var logger$1 = __nccwpck_require__(3233); +var coreUtil = __nccwpck_require__(1333); +var os = __nccwpck_require__(2037); +var abortController = __nccwpck_require__(2557); +var FormData = __nccwpck_require__(4334); +var httpsProxyAgent = __nccwpck_require__(7219); +var httpProxyAgent = __nccwpck_require__(3764); +var coreTracing = __nccwpck_require__(4175); +var util = __nccwpck_require__(3837); +var http = __nccwpck_require__(3685); +var https = __nccwpck_require__(5687); +var zlib = __nccwpck_require__(9796); +var stream = __nccwpck_require__(2781); + +function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; } + +function _interopNamespace(e) { + if (e && e.__esModule) return e; + var n = Object.create(null); + if (e) { + Object.keys(e).forEach(function (k) { + if (k !== 'default') { + var d = Object.getOwnPropertyDescriptor(e, k); + Object.defineProperty(n, k, d.get ? d : { + enumerable: true, + get: function () { return e[k]; } + }); + } + }); + } + n["default"] = e; + return Object.freeze(n); +} + +var os__namespace = /*#__PURE__*/_interopNamespace(os); +var FormData__default = /*#__PURE__*/_interopDefaultLegacy(FormData); +var http__namespace = /*#__PURE__*/_interopNamespace(http); +var https__namespace = /*#__PURE__*/_interopNamespace(https); +var zlib__namespace = /*#__PURE__*/_interopNamespace(zlib); + +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. +const ValidPhaseNames = new Set(["Deserialize", "Serialize", "Retry", "Sign"]); +/** + * A private implementation of Pipeline. + * Do not export this class from the package. + * @internal + */ +class HttpPipeline { + constructor(policies) { + var _a; + this._policies = []; + this._policies = (_a = policies === null || policies === void 0 ? void 0 : policies.slice(0)) !== null && _a !== void 0 ? _a : []; + this._orderedPolicies = undefined; + } + addPolicy(policy, options = {}) { + if (options.phase && options.afterPhase) { + throw new Error("Policies inside a phase cannot specify afterPhase."); + } + if (options.phase && !ValidPhaseNames.has(options.phase)) { + throw new Error(`Invalid phase name: ${options.phase}`); + } + if (options.afterPhase && !ValidPhaseNames.has(options.afterPhase)) { + throw new Error(`Invalid afterPhase name: ${options.afterPhase}`); + } + this._policies.push({ + policy, + options, + }); + this._orderedPolicies = undefined; + } + removePolicy(options) { + const removedPolicies = []; + this._policies = this._policies.filter((policyDescriptor) => { + if ((options.name && policyDescriptor.policy.name === options.name) || + (options.phase && policyDescriptor.options.phase === options.phase)) { + removedPolicies.push(policyDescriptor.policy); + return false; + } + else { + return true; + } + }); + this._orderedPolicies = undefined; + return removedPolicies; + } + sendRequest(httpClient, request) { + const policies = this.getOrderedPolicies(); + const pipeline = policies.reduceRight((next, policy) => { + return (req) => { + return policy.sendRequest(req, next); + }; + }, (req) => httpClient.sendRequest(req)); + return pipeline(request); + } + getOrderedPolicies() { + if (!this._orderedPolicies) { + this._orderedPolicies = this.orderPolicies(); + } + return this._orderedPolicies; + } + clone() { + return new HttpPipeline(this._policies); + } + static create() { + return new HttpPipeline(); + } + orderPolicies() { + /** + * The goal of this method is to reliably order pipeline policies + * based on their declared requirements when they were added. + * + * Order is first determined by phase: + * + * 1. Serialize Phase + * 2. Policies not in a phase + * 3. Deserialize Phase + * 4. Retry Phase + * 5. Sign Phase + * + * Within each phase, policies are executed in the order + * they were added unless they were specified to execute + * before/after other policies or after a particular phase. + * + * To determine the final order, we will walk the policy list + * in phase order multiple times until all dependencies are + * satisfied. + * + * `afterPolicies` are the set of policies that must be + * executed before a given policy. This requirement is + * considered satisfied when each of the listed policies + * have been scheduled. + * + * `beforePolicies` are the set of policies that must be + * executed after a given policy. Since this dependency + * can be expressed by converting it into a equivalent + * `afterPolicies` declarations, they are normalized + * into that form for simplicity. + * + * An `afterPhase` dependency is considered satisfied when all + * policies in that phase have scheduled. + * + */ + const result = []; + // Track all policies we know about. + const policyMap = new Map(); + function createPhase(name) { + return { + name, + policies: new Set(), + hasRun: false, + hasAfterPolicies: false, + }; + } + // Track policies for each phase. + const serializePhase = createPhase("Serialize"); + const noPhase = createPhase("None"); + const deserializePhase = createPhase("Deserialize"); + const retryPhase = createPhase("Retry"); + const signPhase = createPhase("Sign"); + // a list of phases in order + const orderedPhases = [serializePhase, noPhase, deserializePhase, retryPhase, signPhase]; + // Small helper function to map phase name to each Phase + function getPhase(phase) { + if (phase === "Retry") { + return retryPhase; + } + else if (phase === "Serialize") { + return serializePhase; + } + else if (phase === "Deserialize") { + return deserializePhase; + } + else if (phase === "Sign") { + return signPhase; + } + else { + return noPhase; + } + } + // First walk each policy and create a node to track metadata. + for (const descriptor of this._policies) { + const policy = descriptor.policy; + const options = descriptor.options; + const policyName = policy.name; + if (policyMap.has(policyName)) { + throw new Error("Duplicate policy names not allowed in pipeline"); + } + const node = { + policy, + dependsOn: new Set(), + dependants: new Set(), + }; + if (options.afterPhase) { + node.afterPhase = getPhase(options.afterPhase); + node.afterPhase.hasAfterPolicies = true; + } + policyMap.set(policyName, node); + const phase = getPhase(options.phase); + phase.policies.add(node); + } + // Now that each policy has a node, connect dependency references. + for (const descriptor of this._policies) { + const { policy, options } = descriptor; + const policyName = policy.name; + const node = policyMap.get(policyName); + if (!node) { + throw new Error(`Missing node for policy ${policyName}`); + } + if (options.afterPolicies) { + for (const afterPolicyName of options.afterPolicies) { + const afterNode = policyMap.get(afterPolicyName); + if (afterNode) { + // Linking in both directions helps later + // when we want to notify dependants. + node.dependsOn.add(afterNode); + afterNode.dependants.add(node); + } + } + } + if (options.beforePolicies) { + for (const beforePolicyName of options.beforePolicies) { + const beforeNode = policyMap.get(beforePolicyName); + if (beforeNode) { + // To execute before another node, make it + // depend on the current node. + beforeNode.dependsOn.add(node); + node.dependants.add(beforeNode); + } + } + } + } + function walkPhase(phase) { + phase.hasRun = true; + // Sets iterate in insertion order + for (const node of phase.policies) { + if (node.afterPhase && (!node.afterPhase.hasRun || node.afterPhase.policies.size)) { + // If this node is waiting on a phase to complete, + // we need to skip it for now. + // Even if the phase is empty, we should wait for it + // to be walked to avoid re-ordering policies. + continue; + } + if (node.dependsOn.size === 0) { + // If there's nothing else we're waiting for, we can + // add this policy to the result list. + result.push(node.policy); + // Notify anything that depends on this policy that + // the policy has been scheduled. + for (const dependant of node.dependants) { + dependant.dependsOn.delete(node); + } + policyMap.delete(node.policy.name); + phase.policies.delete(node); + } + } + } + function walkPhases() { + for (const phase of orderedPhases) { + walkPhase(phase); + // if the phase isn't complete + if (phase.policies.size > 0 && phase !== noPhase) { + if (!noPhase.hasRun) { + // Try running noPhase to see if that unblocks this phase next tick. + // This can happen if a phase that happens before noPhase + // is waiting on a noPhase policy to complete. + walkPhase(noPhase); + } + // Don't proceed to the next phase until this phase finishes. + return; + } + if (phase.hasAfterPolicies) { + // Run any policies unblocked by this phase + walkPhase(noPhase); + } + } + } + // Iterate until we've put every node in the result list. + let iteration = 0; + while (policyMap.size > 0) { + iteration++; + const initialResultLength = result.length; + // Keep walking each phase in order until we can order every node. + walkPhases(); + // The result list *should* get at least one larger each time + // after the first full pass. + // Otherwise, we're going to loop forever. + if (result.length <= initialResultLength && iteration > 1) { + throw new Error("Cannot satisfy policy dependencies due to requirements cycle."); + } + } + return result; + } +} +/** + * Creates a totally empty pipeline. + * Useful for testing or creating a custom one. + */ +function createEmptyPipeline() { + return HttpPipeline.create(); +} + +// Copyright (c) Microsoft Corporation. +const logger = logger$1.createClientLogger("core-rest-pipeline"); + +// Copyright (c) Microsoft Corporation. +const RedactedString = "REDACTED"; +// Make sure this list is up-to-date with the one under core/logger/Readme#Keyconcepts +const defaultAllowedHeaderNames = [ + "x-ms-client-request-id", + "x-ms-return-client-request-id", + "x-ms-useragent", + "x-ms-correlation-request-id", + "x-ms-request-id", + "client-request-id", + "ms-cv", + "return-client-request-id", + "traceparent", + "Access-Control-Allow-Credentials", + "Access-Control-Allow-Headers", + "Access-Control-Allow-Methods", + "Access-Control-Allow-Origin", + "Access-Control-Expose-Headers", + "Access-Control-Max-Age", + "Access-Control-Request-Headers", + "Access-Control-Request-Method", + "Origin", + "Accept", + "Accept-Encoding", + "Cache-Control", + "Connection", + "Content-Length", + "Content-Type", + "Date", + "ETag", + "Expires", + "If-Match", + "If-Modified-Since", + "If-None-Match", + "If-Unmodified-Since", + "Last-Modified", + "Pragma", + "Request-Id", + "Retry-After", + "Server", + "Transfer-Encoding", + "User-Agent", + "WWW-Authenticate", +]; +const defaultAllowedQueryParameters = ["api-version"]; +/** + * @internal + */ +class Sanitizer { + constructor({ additionalAllowedHeaderNames: allowedHeaderNames = [], additionalAllowedQueryParameters: allowedQueryParameters = [], } = {}) { + allowedHeaderNames = defaultAllowedHeaderNames.concat(allowedHeaderNames); + allowedQueryParameters = defaultAllowedQueryParameters.concat(allowedQueryParameters); + this.allowedHeaderNames = new Set(allowedHeaderNames.map((n) => n.toLowerCase())); + this.allowedQueryParameters = new Set(allowedQueryParameters.map((p) => p.toLowerCase())); + } + sanitize(obj) { + const seen = new Set(); + return JSON.stringify(obj, (key, value) => { + // Ensure Errors include their interesting non-enumerable members + if (value instanceof Error) { + return Object.assign(Object.assign({}, value), { name: value.name, message: value.message }); + } + if (key === "headers") { + return this.sanitizeHeaders(value); + } + else if (key === "url") { + return this.sanitizeUrl(value); + } + else if (key === "query") { + return this.sanitizeQuery(value); + } + else if (key === "body") { + // Don't log the request body + return undefined; + } + else if (key === "response") { + // Don't log response again + return undefined; + } + else if (key === "operationSpec") { + // When using sendOperationRequest, the request carries a massive + // field with the autorest spec. No need to log it. + return undefined; + } + else if (Array.isArray(value) || coreUtil.isObject(value)) { + if (seen.has(value)) { + return "[Circular]"; + } + seen.add(value); + } + return value; + }, 2); + } + sanitizeHeaders(obj) { + const sanitized = {}; + for (const key of Object.keys(obj)) { + if (this.allowedHeaderNames.has(key.toLowerCase())) { + sanitized[key] = obj[key]; + } + else { + sanitized[key] = RedactedString; + } + } + return sanitized; + } + sanitizeQuery(value) { + if (typeof value !== "object" || value === null) { + return value; + } + const sanitized = {}; + for (const k of Object.keys(value)) { + if (this.allowedQueryParameters.has(k.toLowerCase())) { + sanitized[k] = value[k]; + } + else { + sanitized[k] = RedactedString; + } + } + return sanitized; + } + sanitizeUrl(value) { + if (typeof value !== "string" || value === null) { + return value; + } + const url = new URL(value); + if (!url.search) { + return value; + } + for (const [key] of url.searchParams) { + if (!this.allowedQueryParameters.has(key.toLowerCase())) { + url.searchParams.set(key, RedactedString); + } + } + return url.toString(); + } +} + +// Copyright (c) Microsoft Corporation. +/** + * The programmatic identifier of the logPolicy. + */ +const logPolicyName = "logPolicy"; +/** + * A policy that logs all requests and responses. + * @param options - Options to configure logPolicy. + */ +function logPolicy(options = {}) { + var _a; + const logger$1 = (_a = options.logger) !== null && _a !== void 0 ? _a : logger.info; + const sanitizer = new Sanitizer({ + additionalAllowedHeaderNames: options.additionalAllowedHeaderNames, + additionalAllowedQueryParameters: options.additionalAllowedQueryParameters, + }); + return { + name: logPolicyName, + async sendRequest(request, next) { + if (!logger$1.enabled) { + return next(request); + } + logger$1(`Request: ${sanitizer.sanitize(request)}`); + const response = await next(request); + logger$1(`Response status code: ${response.status}`); + logger$1(`Headers: ${sanitizer.sanitize(response.headers)}`); + return response; + }, + }; +} + +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. +/** + * The programmatic identifier of the redirectPolicy. + */ +const redirectPolicyName = "redirectPolicy"; +/** + * Methods that are allowed to follow redirects 301 and 302 + */ +const allowedRedirect = ["GET", "HEAD"]; +/** + * A policy to follow Location headers from the server in order + * to support server-side redirection. + * In the browser, this policy is not used. + * @param options - Options to control policy behavior. + */ +function redirectPolicy(options = {}) { + const { maxRetries = 20 } = options; + return { + name: redirectPolicyName, + async sendRequest(request, next) { + const response = await next(request); + return handleRedirect(next, response, maxRetries); + }, + }; +} +async function handleRedirect(next, response, maxRetries, currentRetries = 0) { + const { request, status, headers } = response; + const locationHeader = headers.get("location"); + if (locationHeader && + (status === 300 || + (status === 301 && allowedRedirect.includes(request.method)) || + (status === 302 && allowedRedirect.includes(request.method)) || + (status === 303 && request.method === "POST") || + status === 307) && + currentRetries < maxRetries) { + const url = new URL(locationHeader, request.url); + request.url = url.toString(); + // POST request with Status code 303 should be converted into a + // redirected GET request if the redirect url is present in the location header + if (status === 303) { + request.method = "GET"; + request.headers.delete("Content-Length"); + delete request.body; + } + request.headers.delete("Authorization"); + const res = await next(request); + return handleRedirect(next, res, maxRetries, currentRetries + 1); + } + return response; +} + +// Copyright (c) Microsoft Corporation. +/** + * @internal + */ +function getHeaderName() { + return "User-Agent"; +} +/** + * @internal + */ +function setPlatformSpecificData(map) { + map.set("Node", process.version); + map.set("OS", `(${os__namespace.arch()}-${os__namespace.type()}-${os__namespace.release()})`); +} + +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. +const SDK_VERSION = "1.12.0"; +const DEFAULT_RETRY_POLICY_COUNT = 3; + +// Copyright (c) Microsoft Corporation. +function getUserAgentString(telemetryInfo) { + const parts = []; + for (const [key, value] of telemetryInfo) { + const token = value ? `${key}/${value}` : key; + parts.push(token); + } + return parts.join(" "); +} +/** + * @internal + */ +function getUserAgentHeaderName() { + return getHeaderName(); +} +/** + * @internal + */ +function getUserAgentValue(prefix) { + const runtimeInfo = new Map(); + runtimeInfo.set("core-rest-pipeline", SDK_VERSION); + setPlatformSpecificData(runtimeInfo); + const defaultAgent = getUserAgentString(runtimeInfo); + const userAgentValue = prefix ? `${prefix} ${defaultAgent}` : defaultAgent; + return userAgentValue; +} + +// Copyright (c) Microsoft Corporation. +const UserAgentHeaderName = getUserAgentHeaderName(); +/** + * The programmatic identifier of the userAgentPolicy. + */ +const userAgentPolicyName = "userAgentPolicy"; +/** + * A policy that sets the User-Agent header (or equivalent) to reflect + * the library version. + * @param options - Options to customize the user agent value. + */ +function userAgentPolicy(options = {}) { + const userAgentValue = getUserAgentValue(options.userAgentPrefix); + return { + name: userAgentPolicyName, + async sendRequest(request, next) { + if (!request.headers.has(UserAgentHeaderName)) { + request.headers.set(UserAgentHeaderName, userAgentValue); + } + return next(request); + }, + }; +} + +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. +/** + * The programmatic identifier of the decompressResponsePolicy. + */ +const decompressResponsePolicyName = "decompressResponsePolicy"; +/** + * A policy to enable response decompression according to Accept-Encoding header + * https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Accept-Encoding + */ +function decompressResponsePolicy() { + return { + name: decompressResponsePolicyName, + async sendRequest(request, next) { + // HEAD requests have no body + if (request.method !== "HEAD") { + request.headers.set("Accept-Encoding", "gzip,deflate"); + } + return next(request); + }, + }; +} + +// Copyright (c) Microsoft Corporation. +const StandardAbortMessage = "The operation was aborted."; +/** + * A wrapper for setTimeout that resolves a promise after delayInMs milliseconds. + * @param delayInMs - The number of milliseconds to be delayed. + * @param value - The value to be resolved with after a timeout of t milliseconds. + * @param options - The options for delay - currently abort options + * - abortSignal - The abortSignal associated with containing operation. + * - abortErrorMsg - The abort error message associated with containing operation. + * @returns Resolved promise + */ +function delay(delayInMs, value, options) { + return new Promise((resolve, reject) => { + let timer = undefined; + let onAborted = undefined; + const rejectOnAbort = () => { + return reject(new abortController.AbortError((options === null || options === void 0 ? void 0 : options.abortErrorMsg) ? options === null || options === void 0 ? void 0 : options.abortErrorMsg : StandardAbortMessage)); + }; + const removeListeners = () => { + if ((options === null || options === void 0 ? void 0 : options.abortSignal) && onAborted) { + options.abortSignal.removeEventListener("abort", onAborted); + } + }; + onAborted = () => { + if (timer) { + clearTimeout(timer); + } + removeListeners(); + return rejectOnAbort(); + }; + if ((options === null || options === void 0 ? void 0 : options.abortSignal) && options.abortSignal.aborted) { + return rejectOnAbort(); + } + timer = setTimeout(() => { + removeListeners(); + resolve(value); + }, delayInMs); + if (options === null || options === void 0 ? void 0 : options.abortSignal) { + options.abortSignal.addEventListener("abort", onAborted); + } + }); +} +/** + * @internal + * @returns the parsed value or undefined if the parsed value is invalid. + */ +function parseHeaderValueAsNumber(response, headerName) { + const value = response.headers.get(headerName); + if (!value) + return; + const valueAsNum = Number(value); + if (Number.isNaN(valueAsNum)) + return; + return valueAsNum; +} + +// Copyright (c) Microsoft Corporation. +/** + * The header that comes back from Azure services representing + * the amount of time (minimum) to wait to retry (in seconds or timestamp after which we can retry). + */ +const RetryAfterHeader = "Retry-After"; +/** + * The headers that come back from Azure services representing + * the amount of time (minimum) to wait to retry. + * + * "retry-after-ms", "x-ms-retry-after-ms" : milliseconds + * "Retry-After" : seconds or timestamp + */ +const AllRetryAfterHeaders = ["retry-after-ms", "x-ms-retry-after-ms", RetryAfterHeader]; +/** + * A response is a throttling retry response if it has a throttling status code (429 or 503), + * as long as one of the [ "Retry-After" or "retry-after-ms" or "x-ms-retry-after-ms" ] headers has a valid value. + * + * Returns the `retryAfterInMs` value if the response is a throttling retry response. + * If not throttling retry response, returns `undefined`. + * + * @internal + */ +function getRetryAfterInMs(response) { + if (!(response && [429, 503].includes(response.status))) + return undefined; + try { + // Headers: "retry-after-ms", "x-ms-retry-after-ms", "Retry-After" + for (const header of AllRetryAfterHeaders) { + const retryAfterValue = parseHeaderValueAsNumber(response, header); + if (retryAfterValue === 0 || retryAfterValue) { + // "Retry-After" header ==> seconds + // "retry-after-ms", "x-ms-retry-after-ms" headers ==> milli-seconds + const multiplyingFactor = header === RetryAfterHeader ? 1000 : 1; + return retryAfterValue * multiplyingFactor; // in milli-seconds + } + } + // RetryAfterHeader ("Retry-After") has a special case where it might be formatted as a date instead of a number of seconds + const retryAfterHeader = response.headers.get(RetryAfterHeader); + if (!retryAfterHeader) + return; + const date = Date.parse(retryAfterHeader); + const diff = date - Date.now(); + // negative diff would mean a date in the past, so retry asap with 0 milliseconds + return Number.isFinite(diff) ? Math.max(0, diff) : undefined; + } + catch (e) { + return undefined; + } +} +/** + * A response is a retry response if it has a throttling status code (429 or 503), + * as long as one of the [ "Retry-After" or "retry-after-ms" or "x-ms-retry-after-ms" ] headers has a valid value. + */ +function isThrottlingRetryResponse(response) { + return Number.isFinite(getRetryAfterInMs(response)); +} +function throttlingRetryStrategy() { + return { + name: "throttlingRetryStrategy", + retry({ response }) { + const retryAfterInMs = getRetryAfterInMs(response); + if (!Number.isFinite(retryAfterInMs)) { + return { skipStrategy: true }; + } + return { + retryAfterInMs, + }; + }, + }; +} + +// Copyright (c) Microsoft Corporation. +// intervals are in milliseconds +const DEFAULT_CLIENT_RETRY_INTERVAL = 1000; +const DEFAULT_CLIENT_MAX_RETRY_INTERVAL = 1000 * 64; +/** + * A retry strategy that retries with an exponentially increasing delay in these two cases: + * - When there are errors in the underlying transport layer (e.g. DNS lookup failures). + * - Or otherwise if the outgoing request fails (408, greater or equal than 500, except for 501 and 505). + */ +function exponentialRetryStrategy(options = {}) { + var _a, _b; + const retryInterval = (_a = options.retryDelayInMs) !== null && _a !== void 0 ? _a : DEFAULT_CLIENT_RETRY_INTERVAL; + const maxRetryInterval = (_b = options.maxRetryDelayInMs) !== null && _b !== void 0 ? _b : DEFAULT_CLIENT_MAX_RETRY_INTERVAL; + let retryAfterInMs = retryInterval; + return { + name: "exponentialRetryStrategy", + retry({ retryCount, response, responseError }) { + const matchedSystemError = isSystemError(responseError); + const ignoreSystemErrors = matchedSystemError && options.ignoreSystemErrors; + const isExponential = isExponentialRetryResponse(response); + const ignoreExponentialResponse = isExponential && options.ignoreHttpStatusCodes; + const unknownResponse = response && (isThrottlingRetryResponse(response) || !isExponential); + if (unknownResponse || ignoreExponentialResponse || ignoreSystemErrors) { + return { skipStrategy: true }; + } + if (responseError && !matchedSystemError && !isExponential) { + return { errorToThrow: responseError }; + } + // Exponentially increase the delay each time + const exponentialDelay = retryAfterInMs * Math.pow(2, retryCount); + // Don't let the delay exceed the maximum + const clampedExponentialDelay = Math.min(maxRetryInterval, exponentialDelay); + // Allow the final value to have some "jitter" (within 50% of the delay size) so + // that retries across multiple clients don't occur simultaneously. + retryAfterInMs = + clampedExponentialDelay / 2 + coreUtil.getRandomIntegerInclusive(0, clampedExponentialDelay / 2); + return { retryAfterInMs }; + }, + }; +} +/** + * A response is a retry response if it has status codes: + * - 408, or + * - Greater or equal than 500, except for 501 and 505. + */ +function isExponentialRetryResponse(response) { + return Boolean(response && + response.status !== undefined && + (response.status >= 500 || response.status === 408) && + response.status !== 501 && + response.status !== 505); +} +/** + * Determines whether an error from a pipeline response was triggered in the network layer. + */ +function isSystemError(err) { + if (!err) { + return false; + } + return (err.code === "ETIMEDOUT" || + err.code === "ESOCKETTIMEDOUT" || + err.code === "ECONNREFUSED" || + err.code === "ECONNRESET" || + err.code === "ENOENT"); +} + +// Copyright (c) Microsoft Corporation. +const retryPolicyLogger = logger$1.createClientLogger("core-rest-pipeline retryPolicy"); +/** + * The programmatic identifier of the retryPolicy. + */ +const retryPolicyName = "retryPolicy"; +/** + * retryPolicy is a generic policy to enable retrying requests when certain conditions are met + */ +function retryPolicy(strategies, options = { maxRetries: DEFAULT_RETRY_POLICY_COUNT }) { + const logger = options.logger || retryPolicyLogger; + return { + name: retryPolicyName, + async sendRequest(request, next) { + var _a, _b; + let response; + let responseError; + let retryCount = -1; + // eslint-disable-next-line no-constant-condition + retryRequest: while (true) { + retryCount += 1; + response = undefined; + responseError = undefined; + try { + logger.info(`Retry ${retryCount}: Attempting to send request`, request.requestId); + response = await next(request); + logger.info(`Retry ${retryCount}: Received a response from request`, request.requestId); + } + catch (e) { + logger.error(`Retry ${retryCount}: Received an error from request`, request.requestId); + // RestErrors are valid targets for the retry strategies. + // If none of the retry strategies can work with them, they will be thrown later in this policy. + // If the received error is not a RestError, it is immediately thrown. + responseError = e; + if (!e || responseError.name !== "RestError") { + throw e; + } + response = responseError.response; + } + if ((_a = request.abortSignal) === null || _a === void 0 ? void 0 : _a.aborted) { + logger.error(`Retry ${retryCount}: Request aborted.`); + const abortError = new abortController.AbortError(); + throw abortError; + } + if (retryCount >= ((_b = options.maxRetries) !== null && _b !== void 0 ? _b : DEFAULT_RETRY_POLICY_COUNT)) { + logger.info(`Retry ${retryCount}: Maximum retries reached. Returning the last received response, or throwing the last received error.`); + if (responseError) { + throw responseError; + } + else if (response) { + return response; + } + else { + throw new Error("Maximum retries reached with no response or error to throw"); + } + } + logger.info(`Retry ${retryCount}: Processing ${strategies.length} retry strategies.`); + strategiesLoop: for (const strategy of strategies) { + const strategyLogger = strategy.logger || retryPolicyLogger; + strategyLogger.info(`Retry ${retryCount}: Processing retry strategy ${strategy.name}.`); + const modifiers = strategy.retry({ + retryCount, + response, + responseError, + }); + if (modifiers.skipStrategy) { + strategyLogger.info(`Retry ${retryCount}: Skipped.`); + continue strategiesLoop; + } + const { errorToThrow, retryAfterInMs, redirectTo } = modifiers; + if (errorToThrow) { + strategyLogger.error(`Retry ${retryCount}: Retry strategy ${strategy.name} throws error:`, errorToThrow); + throw errorToThrow; + } + if (retryAfterInMs || retryAfterInMs === 0) { + strategyLogger.info(`Retry ${retryCount}: Retry strategy ${strategy.name} retries after ${retryAfterInMs}`); + await delay(retryAfterInMs, undefined, { abortSignal: request.abortSignal }); + continue retryRequest; + } + if (redirectTo) { + strategyLogger.info(`Retry ${retryCount}: Retry strategy ${strategy.name} redirects to ${redirectTo}`); + request.url = redirectTo; + continue retryRequest; + } + } + if (responseError) { + logger.info(`None of the retry strategies could work with the received error. Throwing it.`); + throw responseError; + } + if (response) { + logger.info(`None of the retry strategies could work with the received response. Returning it.`); + return response; + } + // If all the retries skip and there's no response, + // we're still in the retry loop, so a new request will be sent + // until `maxRetries` is reached. + } + }, + }; +} + +// Copyright (c) Microsoft Corporation. +/** + * Name of the {@link defaultRetryPolicy} + */ +const defaultRetryPolicyName = "defaultRetryPolicy"; +/** + * A policy that retries according to three strategies: + * - When the server sends a 429 response with a Retry-After header. + * - When there are errors in the underlying transport layer (e.g. DNS lookup failures). + * - Or otherwise if the outgoing request fails, it will retry with an exponentially increasing delay. + */ +function defaultRetryPolicy(options = {}) { + var _a; + return { + name: defaultRetryPolicyName, + sendRequest: retryPolicy([throttlingRetryStrategy(), exponentialRetryStrategy(options)], { + maxRetries: (_a = options.maxRetries) !== null && _a !== void 0 ? _a : DEFAULT_RETRY_POLICY_COUNT, + }).sendRequest, + }; +} + +// Copyright (c) Microsoft Corporation. +/** + * The programmatic identifier of the formDataPolicy. + */ +const formDataPolicyName = "formDataPolicy"; +/** + * A policy that encodes FormData on the request into the body. + */ +function formDataPolicy() { + return { + name: formDataPolicyName, + async sendRequest(request, next) { + if (request.formData) { + const contentType = request.headers.get("Content-Type"); + if (contentType && contentType.indexOf("application/x-www-form-urlencoded") !== -1) { + request.body = wwwFormUrlEncode(request.formData); + request.formData = undefined; + } + else { + await prepareFormData(request.formData, request); + } + } + return next(request); + }, + }; +} +function wwwFormUrlEncode(formData) { + const urlSearchParams = new URLSearchParams(); + for (const [key, value] of Object.entries(formData)) { + if (Array.isArray(value)) { + for (const subValue of value) { + urlSearchParams.append(key, subValue.toString()); + } + } + else { + urlSearchParams.append(key, value.toString()); + } + } + return urlSearchParams.toString(); +} +async function prepareFormData(formData, request) { + const requestForm = new FormData__default["default"](); + for (const formKey of Object.keys(formData)) { + const formValue = formData[formKey]; + if (Array.isArray(formValue)) { + for (const subValue of formValue) { + requestForm.append(formKey, subValue); + } + } + else { + requestForm.append(formKey, formValue); + } + } + request.body = requestForm; + request.formData = undefined; + const contentType = request.headers.get("Content-Type"); + if (contentType && contentType.indexOf("multipart/form-data") !== -1) { + request.headers.set("Content-Type", `multipart/form-data; boundary=${requestForm.getBoundary()}`); + } + try { + const contentLength = await new Promise((resolve, reject) => { + requestForm.getLength((err, length) => { + if (err) { + reject(err); + } + else { + resolve(length); + } + }); + }); + request.headers.set("Content-Length", contentLength); + } + catch (e) { + // ignore setting the length if this fails + } +} + +// Copyright (c) Microsoft Corporation. +const HTTPS_PROXY = "HTTPS_PROXY"; +const HTTP_PROXY = "HTTP_PROXY"; +const ALL_PROXY = "ALL_PROXY"; +const NO_PROXY = "NO_PROXY"; +/** + * The programmatic identifier of the proxyPolicy. + */ +const proxyPolicyName = "proxyPolicy"; +/** + * Stores the patterns specified in NO_PROXY environment variable. + * @internal + */ +const globalNoProxyList = []; +let noProxyListLoaded = false; +/** A cache of whether a host should bypass the proxy. */ +const globalBypassedMap = new Map(); +function getEnvironmentValue(name) { + if (process.env[name]) { + return process.env[name]; + } + else if (process.env[name.toLowerCase()]) { + return process.env[name.toLowerCase()]; + } + return undefined; +} +function loadEnvironmentProxyValue() { + if (!process) { + return undefined; + } + const httpsProxy = getEnvironmentValue(HTTPS_PROXY); + const allProxy = getEnvironmentValue(ALL_PROXY); + const httpProxy = getEnvironmentValue(HTTP_PROXY); + return httpsProxy || allProxy || httpProxy; +} +/** + * Check whether the host of a given `uri` matches any pattern in the no proxy list. + * If there's a match, any request sent to the same host shouldn't have the proxy settings set. + * This implementation is a port of https://github.com/Azure/azure-sdk-for-net/blob/8cca811371159e527159c7eb65602477898683e2/sdk/core/Azure.Core/src/Pipeline/Internal/HttpEnvironmentProxy.cs#L210 + */ +function isBypassed(uri, noProxyList, bypassedMap) { + if (noProxyList.length === 0) { + return false; + } + const host = new URL(uri).hostname; + if (bypassedMap === null || bypassedMap === void 0 ? void 0 : bypassedMap.has(host)) { + return bypassedMap.get(host); + } + let isBypassedFlag = false; + for (const pattern of noProxyList) { + if (pattern[0] === ".") { + // This should match either domain it self or any subdomain or host + // .foo.com will match foo.com it self or *.foo.com + if (host.endsWith(pattern)) { + isBypassedFlag = true; + } + else { + if (host.length === pattern.length - 1 && host === pattern.slice(1)) { + isBypassedFlag = true; + } + } + } + else { + if (host === pattern) { + isBypassedFlag = true; + } + } + } + bypassedMap === null || bypassedMap === void 0 ? void 0 : bypassedMap.set(host, isBypassedFlag); + return isBypassedFlag; +} +function loadNoProxy() { + const noProxy = getEnvironmentValue(NO_PROXY); + noProxyListLoaded = true; + if (noProxy) { + return noProxy + .split(",") + .map((item) => item.trim()) + .filter((item) => item.length); + } + return []; +} +/** + * This method converts a proxy url into `ProxySettings` for use with ProxyPolicy. + * If no argument is given, it attempts to parse a proxy URL from the environment + * variables `HTTPS_PROXY` or `HTTP_PROXY`. + * @param proxyUrl - The url of the proxy to use. May contain authentication information. + */ +function getDefaultProxySettings(proxyUrl) { + if (!proxyUrl) { + proxyUrl = loadEnvironmentProxyValue(); + if (!proxyUrl) { + return undefined; + } + } + const parsedUrl = new URL(proxyUrl); + const schema = parsedUrl.protocol ? parsedUrl.protocol + "//" : ""; + return { + host: schema + parsedUrl.hostname, + port: Number.parseInt(parsedUrl.port || "80"), + username: parsedUrl.username, + password: parsedUrl.password, + }; +} +/** + * @internal + */ +function getProxyAgentOptions(proxySettings, { headers, tlsSettings }) { + let parsedProxyUrl; + try { + parsedProxyUrl = new URL(proxySettings.host); + } + catch (_error) { + throw new Error(`Expecting a valid host string in proxy settings, but found "${proxySettings.host}".`); + } + if (tlsSettings) { + logger.warning("TLS settings are not supported in combination with custom Proxy, certificates provided to the client will be ignored."); + } + const proxyAgentOptions = { + hostname: parsedProxyUrl.hostname, + port: proxySettings.port, + protocol: parsedProxyUrl.protocol, + headers: headers.toJSON(), + }; + if (proxySettings.username && proxySettings.password) { + proxyAgentOptions.auth = `${proxySettings.username}:${proxySettings.password}`; + } + else if (proxySettings.username) { + proxyAgentOptions.auth = `${proxySettings.username}`; + } + return proxyAgentOptions; +} +function setProxyAgentOnRequest(request, cachedAgents) { + // Custom Agent should take precedence so if one is present + // we should skip to avoid overwriting it. + if (request.agent) { + return; + } + const url = new URL(request.url); + const isInsecure = url.protocol !== "https:"; + const proxySettings = request.proxySettings; + if (proxySettings) { + if (isInsecure) { + if (!cachedAgents.httpProxyAgent) { + const proxyAgentOptions = getProxyAgentOptions(proxySettings, request); + cachedAgents.httpProxyAgent = new httpProxyAgent.HttpProxyAgent(proxyAgentOptions); + } + request.agent = cachedAgents.httpProxyAgent; + } + else { + if (!cachedAgents.httpsProxyAgent) { + const proxyAgentOptions = getProxyAgentOptions(proxySettings, request); + cachedAgents.httpsProxyAgent = new httpsProxyAgent.HttpsProxyAgent(proxyAgentOptions); + } + request.agent = cachedAgents.httpsProxyAgent; + } + } +} +/** + * A policy that allows one to apply proxy settings to all requests. + * If not passed static settings, they will be retrieved from the HTTPS_PROXY + * or HTTP_PROXY environment variables. + * @param proxySettings - ProxySettings to use on each request. + * @param options - additional settings, for example, custom NO_PROXY patterns + */ +function proxyPolicy(proxySettings = getDefaultProxySettings(), options) { + if (!noProxyListLoaded) { + globalNoProxyList.push(...loadNoProxy()); + } + const cachedAgents = {}; + return { + name: proxyPolicyName, + async sendRequest(request, next) { + var _a; + if (!request.proxySettings && + !isBypassed(request.url, (_a = options === null || options === void 0 ? void 0 : options.customNoProxyList) !== null && _a !== void 0 ? _a : globalNoProxyList, (options === null || options === void 0 ? void 0 : options.customNoProxyList) ? undefined : globalBypassedMap)) { + request.proxySettings = proxySettings; + } + if (request.proxySettings) { + setProxyAgentOnRequest(request, cachedAgents); + } + return next(request); + }, + }; +} + +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. +/** + * The programmatic identifier of the setClientRequestIdPolicy. + */ +const setClientRequestIdPolicyName = "setClientRequestIdPolicy"; +/** + * Each PipelineRequest gets a unique id upon creation. + * This policy passes that unique id along via an HTTP header to enable better + * telemetry and tracing. + * @param requestIdHeaderName - The name of the header to pass the request ID to. + */ +function setClientRequestIdPolicy(requestIdHeaderName = "x-ms-client-request-id") { + return { + name: setClientRequestIdPolicyName, + async sendRequest(request, next) { + if (!request.headers.has(requestIdHeaderName)) { + request.headers.set(requestIdHeaderName, request.requestId); + } + return next(request); + }, + }; +} + +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. +/** + * Name of the TLS Policy + */ +const tlsPolicyName = "tlsPolicy"; +/** + * Gets a pipeline policy that adds the client certificate to the HttpClient agent for authentication. + */ +function tlsPolicy(tlsSettings) { + return { + name: tlsPolicyName, + sendRequest: async (req, next) => { + // Users may define a request tlsSettings, honor those over the client level one + if (!req.tlsSettings) { + req.tlsSettings = tlsSettings; + } + return next(req); + }, + }; +} + +// Copyright (c) Microsoft Corporation. +const custom = util.inspect.custom; + +// Copyright (c) Microsoft Corporation. +const errorSanitizer = new Sanitizer(); +/** + * A custom error type for failed pipeline requests. + */ +class RestError extends Error { + constructor(message, options = {}) { + super(message); + this.name = "RestError"; + this.code = options.code; + this.statusCode = options.statusCode; + this.request = options.request; + this.response = options.response; + Object.setPrototypeOf(this, RestError.prototype); + } + /** + * Logging method for util.inspect in Node + */ + [custom]() { + return `RestError: ${this.message} \n ${errorSanitizer.sanitize(this)}`; + } +} +/** + * Something went wrong when making the request. + * This means the actual request failed for some reason, + * such as a DNS issue or the connection being lost. + */ +RestError.REQUEST_SEND_ERROR = "REQUEST_SEND_ERROR"; +/** + * This means that parsing the response from the server failed. + * It may have been malformed. + */ +RestError.PARSE_ERROR = "PARSE_ERROR"; +/** + * Typeguard for RestError + * @param e - Something caught by a catch clause. + */ +function isRestError(e) { + if (e instanceof RestError) { + return true; + } + return coreUtil.isError(e) && e.name === "RestError"; +} + +// Copyright (c) Microsoft Corporation. +/** + * The programmatic identifier of the tracingPolicy. + */ +const tracingPolicyName = "tracingPolicy"; +/** + * A simple policy to create OpenTelemetry Spans for each request made by the pipeline + * that has SpanOptions with a parent. + * Requests made without a parent Span will not be recorded. + * @param options - Options to configure the telemetry logged by the tracing policy. + */ +function tracingPolicy(options = {}) { + const userAgent = getUserAgentValue(options.userAgentPrefix); + const tracingClient = tryCreateTracingClient(); + return { + name: tracingPolicyName, + async sendRequest(request, next) { + var _a, _b; + if (!tracingClient || !((_a = request.tracingOptions) === null || _a === void 0 ? void 0 : _a.tracingContext)) { + return next(request); + } + const { span, tracingContext } = (_b = tryCreateSpan(tracingClient, request, userAgent)) !== null && _b !== void 0 ? _b : {}; + if (!span || !tracingContext) { + return next(request); + } + try { + const response = await tracingClient.withContext(tracingContext, next, request); + tryProcessResponse(span, response); + return response; + } + catch (err) { + tryProcessError(span, err); + throw err; + } + }, + }; +} +function tryCreateTracingClient() { + try { + return coreTracing.createTracingClient({ + namespace: "", + packageName: "@azure/core-rest-pipeline", + packageVersion: SDK_VERSION, + }); + } + catch (e) { + logger.warning(`Error when creating the TracingClient: ${coreUtil.getErrorMessage(e)}`); + return undefined; + } +} +function tryCreateSpan(tracingClient, request, userAgent) { + try { + // As per spec, we do not need to differentiate between HTTP and HTTPS in span name. + const { span, updatedOptions } = tracingClient.startSpan(`HTTP ${request.method}`, { tracingOptions: request.tracingOptions }, { + spanKind: "client", + spanAttributes: { + "http.method": request.method, + "http.url": request.url, + requestId: request.requestId, + }, + }); + // If the span is not recording, don't do any more work. + if (!span.isRecording()) { + span.end(); + return undefined; + } + if (userAgent) { + span.setAttribute("http.user_agent", userAgent); + } + // set headers + const headers = tracingClient.createRequestHeaders(updatedOptions.tracingOptions.tracingContext); + for (const [key, value] of Object.entries(headers)) { + request.headers.set(key, value); + } + return { span, tracingContext: updatedOptions.tracingOptions.tracingContext }; + } + catch (e) { + logger.warning(`Skipping creating a tracing span due to an error: ${coreUtil.getErrorMessage(e)}`); + return undefined; + } +} +function tryProcessError(span, error) { + try { + span.setStatus({ + status: "error", + error: coreUtil.isError(error) ? error : undefined, + }); + if (isRestError(error) && error.statusCode) { + span.setAttribute("http.status_code", error.statusCode); + } + span.end(); + } + catch (e) { + logger.warning(`Skipping tracing span processing due to an error: ${coreUtil.getErrorMessage(e)}`); + } +} +function tryProcessResponse(span, response) { + try { + span.setAttribute("http.status_code", response.status); + const serviceRequestId = response.headers.get("x-ms-request-id"); + if (serviceRequestId) { + span.setAttribute("serviceRequestId", serviceRequestId); + } + span.setStatus({ + status: "success", + }); + span.end(); + } + catch (e) { + logger.warning(`Skipping tracing span processing due to an error: ${coreUtil.getErrorMessage(e)}`); + } +} + +// Copyright (c) Microsoft Corporation. +/** + * Create a new pipeline with a default set of customizable policies. + * @param options - Options to configure a custom pipeline. + */ +function createPipelineFromOptions(options) { + var _a; + const pipeline = createEmptyPipeline(); + if (coreUtil.isNode) { + if (options.tlsOptions) { + pipeline.addPolicy(tlsPolicy(options.tlsOptions)); + } + pipeline.addPolicy(proxyPolicy(options.proxyOptions)); + pipeline.addPolicy(decompressResponsePolicy()); + } + pipeline.addPolicy(formDataPolicy()); + pipeline.addPolicy(userAgentPolicy(options.userAgentOptions)); + pipeline.addPolicy(setClientRequestIdPolicy((_a = options.telemetryOptions) === null || _a === void 0 ? void 0 : _a.clientRequestIdHeaderName)); + pipeline.addPolicy(defaultRetryPolicy(options.retryOptions), { phase: "Retry" }); + pipeline.addPolicy(tracingPolicy(options.userAgentOptions), { afterPhase: "Retry" }); + if (coreUtil.isNode) { + // Both XHR and Fetch expect to handle redirects automatically, + // so only include this policy when we're in Node. + pipeline.addPolicy(redirectPolicy(options.redirectOptions), { afterPhase: "Retry" }); + } + pipeline.addPolicy(logPolicy(options.loggingOptions), { afterPhase: "Sign" }); + return pipeline; +} + +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. +function normalizeName(name) { + return name.toLowerCase(); +} +function* headerIterator(map) { + for (const entry of map.values()) { + yield [entry.name, entry.value]; + } +} +class HttpHeadersImpl { + constructor(rawHeaders) { + this._headersMap = new Map(); + if (rawHeaders) { + for (const headerName of Object.keys(rawHeaders)) { + this.set(headerName, rawHeaders[headerName]); + } + } + } + /** + * Set a header in this collection with the provided name and value. The name is + * case-insensitive. + * @param name - The name of the header to set. This value is case-insensitive. + * @param value - The value of the header to set. + */ + set(name, value) { + this._headersMap.set(normalizeName(name), { name, value: String(value) }); + } + /** + * Get the header value for the provided header name, or undefined if no header exists in this + * collection with the provided name. + * @param name - The name of the header. This value is case-insensitive. + */ + get(name) { + var _a; + return (_a = this._headersMap.get(normalizeName(name))) === null || _a === void 0 ? void 0 : _a.value; + } + /** + * Get whether or not this header collection contains a header entry for the provided header name. + * @param name - The name of the header to set. This value is case-insensitive. + */ + has(name) { + return this._headersMap.has(normalizeName(name)); + } + /** + * Remove the header with the provided headerName. + * @param name - The name of the header to remove. + */ + delete(name) { + this._headersMap.delete(normalizeName(name)); + } + /** + * Get the JSON object representation of this HTTP header collection. + */ + toJSON(options = {}) { + const result = {}; + if (options.preserveCase) { + for (const entry of this._headersMap.values()) { + result[entry.name] = entry.value; + } + } + else { + for (const [normalizedName, entry] of this._headersMap) { + result[normalizedName] = entry.value; + } + } + return result; + } + /** + * Get the string representation of this HTTP header collection. + */ + toString() { + return JSON.stringify(this.toJSON({ preserveCase: true })); + } + /** + * Iterate over tuples of header [name, value] pairs. + */ + [Symbol.iterator]() { + return headerIterator(this._headersMap); + } +} +/** + * Creates an object that satisfies the `HttpHeaders` interface. + * @param rawHeaders - A simple object representing initial headers + */ +function createHttpHeaders(rawHeaders) { + return new HttpHeadersImpl(rawHeaders); +} + +// Copyright (c) Microsoft Corporation. +const DEFAULT_TLS_SETTINGS = {}; +function isReadableStream(body) { + return body && typeof body.pipe === "function"; +} +function isStreamComplete(stream) { + return new Promise((resolve) => { + stream.on("close", resolve); + stream.on("end", resolve); + stream.on("error", resolve); + }); +} +function isArrayBuffer(body) { + return body && typeof body.byteLength === "number"; +} +class ReportTransform extends stream.Transform { + // eslint-disable-next-line @typescript-eslint/ban-types + _transform(chunk, _encoding, callback) { + this.push(chunk); + this.loadedBytes += chunk.length; + try { + this.progressCallback({ loadedBytes: this.loadedBytes }); + callback(); + } + catch (e) { + callback(e); + } + } + constructor(progressCallback) { + super(); + this.loadedBytes = 0; + this.progressCallback = progressCallback; + } +} +/** + * A HttpClient implementation that uses Node's "https" module to send HTTPS requests. + * @internal + */ +class NodeHttpClient { + constructor() { + this.cachedHttpsAgents = new WeakMap(); + } + /** + * Makes a request over an underlying transport layer and returns the response. + * @param request - The request to be made. + */ + async sendRequest(request) { + var _a, _b, _c; + const abortController$1 = new abortController.AbortController(); + let abortListener; + if (request.abortSignal) { + if (request.abortSignal.aborted) { + throw new abortController.AbortError("The operation was aborted."); + } + abortListener = (event) => { + if (event.type === "abort") { + abortController$1.abort(); + } + }; + request.abortSignal.addEventListener("abort", abortListener); + } + if (request.timeout > 0) { + setTimeout(() => { + abortController$1.abort(); + }, request.timeout); + } + const acceptEncoding = request.headers.get("Accept-Encoding"); + const shouldDecompress = (acceptEncoding === null || acceptEncoding === void 0 ? void 0 : acceptEncoding.includes("gzip")) || (acceptEncoding === null || acceptEncoding === void 0 ? void 0 : acceptEncoding.includes("deflate")); + let body = typeof request.body === "function" ? request.body() : request.body; + if (body && !request.headers.has("Content-Length")) { + const bodyLength = getBodyLength(body); + if (bodyLength !== null) { + request.headers.set("Content-Length", bodyLength); + } + } + let responseStream; + try { + if (body && request.onUploadProgress) { + const onUploadProgress = request.onUploadProgress; + const uploadReportStream = new ReportTransform(onUploadProgress); + uploadReportStream.on("error", (e) => { + logger.error("Error in upload progress", e); + }); + if (isReadableStream(body)) { + body.pipe(uploadReportStream); + } + else { + uploadReportStream.end(body); + } + body = uploadReportStream; + } + const res = await this.makeRequest(request, abortController$1, body); + const headers = getResponseHeaders(res); + const status = (_a = res.statusCode) !== null && _a !== void 0 ? _a : 0; + const response = { + status, + headers, + request, + }; + // Responses to HEAD must not have a body. + // If they do return a body, that body must be ignored. + if (request.method === "HEAD") { + // call resume() and not destroy() to avoid closing the socket + // and losing keep alive + res.resume(); + return response; + } + responseStream = shouldDecompress ? getDecodedResponseStream(res, headers) : res; + const onDownloadProgress = request.onDownloadProgress; + if (onDownloadProgress) { + const downloadReportStream = new ReportTransform(onDownloadProgress); + downloadReportStream.on("error", (e) => { + logger.error("Error in download progress", e); + }); + responseStream.pipe(downloadReportStream); + responseStream = downloadReportStream; + } + if ( + // Value of POSITIVE_INFINITY in streamResponseStatusCodes is considered as any status code + ((_b = request.streamResponseStatusCodes) === null || _b === void 0 ? void 0 : _b.has(Number.POSITIVE_INFINITY)) || + ((_c = request.streamResponseStatusCodes) === null || _c === void 0 ? void 0 : _c.has(response.status))) { + response.readableStreamBody = responseStream; + } + else { + response.bodyAsText = await streamToText(responseStream); + } + return response; + } + finally { + // clean up event listener + if (request.abortSignal && abortListener) { + let uploadStreamDone = Promise.resolve(); + if (isReadableStream(body)) { + uploadStreamDone = isStreamComplete(body); + } + let downloadStreamDone = Promise.resolve(); + if (isReadableStream(responseStream)) { + downloadStreamDone = isStreamComplete(responseStream); + } + Promise.all([uploadStreamDone, downloadStreamDone]) + .then(() => { + var _a; + // eslint-disable-next-line promise/always-return + if (abortListener) { + (_a = request.abortSignal) === null || _a === void 0 ? void 0 : _a.removeEventListener("abort", abortListener); + } + }) + .catch((e) => { + logger.warning("Error when cleaning up abortListener on httpRequest", e); + }); + } + } + } + makeRequest(request, abortController$1, body) { + var _a; + const url = new URL(request.url); + const isInsecure = url.protocol !== "https:"; + if (isInsecure && !request.allowInsecureConnection) { + throw new Error(`Cannot connect to ${request.url} while allowInsecureConnection is false.`); + } + const agent = (_a = request.agent) !== null && _a !== void 0 ? _a : this.getOrCreateAgent(request, isInsecure); + const options = { + agent, + hostname: url.hostname, + path: `${url.pathname}${url.search}`, + port: url.port, + method: request.method, + headers: request.headers.toJSON({ preserveCase: true }), + }; + return new Promise((resolve, reject) => { + const req = isInsecure ? http__namespace.request(options, resolve) : https__namespace.request(options, resolve); + req.once("error", (err) => { + var _a; + reject(new RestError(err.message, { code: (_a = err.code) !== null && _a !== void 0 ? _a : RestError.REQUEST_SEND_ERROR, request })); + }); + abortController$1.signal.addEventListener("abort", () => { + const abortError = new abortController.AbortError("The operation was aborted."); + req.destroy(abortError); + reject(abortError); + }); + if (body && isReadableStream(body)) { + body.pipe(req); + } + else if (body) { + if (typeof body === "string" || Buffer.isBuffer(body)) { + req.end(body); + } + else if (isArrayBuffer(body)) { + req.end(ArrayBuffer.isView(body) ? Buffer.from(body.buffer) : Buffer.from(body)); + } + else { + logger.error("Unrecognized body type", body); + reject(new RestError("Unrecognized body type")); + } + } + else { + // streams don't like "undefined" being passed as data + req.end(); + } + }); + } + getOrCreateAgent(request, isInsecure) { + var _a; + const disableKeepAlive = request.disableKeepAlive; + // Handle Insecure requests first + if (isInsecure) { + if (disableKeepAlive) { + // keepAlive:false is the default so we don't need a custom Agent + return http__namespace.globalAgent; + } + if (!this.cachedHttpAgent) { + // If there is no cached agent create a new one and cache it. + this.cachedHttpAgent = new http__namespace.Agent({ keepAlive: true }); + } + return this.cachedHttpAgent; + } + else { + if (disableKeepAlive && !request.tlsSettings) { + // When there are no tlsSettings and keepAlive is false + // we don't need a custom agent + return https__namespace.globalAgent; + } + // We use the tlsSettings to index cached clients + const tlsSettings = (_a = request.tlsSettings) !== null && _a !== void 0 ? _a : DEFAULT_TLS_SETTINGS; + // Get the cached agent or create a new one with the + // provided values for keepAlive and tlsSettings + let agent = this.cachedHttpsAgents.get(tlsSettings); + if (agent && agent.options.keepAlive === !disableKeepAlive) { + return agent; + } + logger.info("No cached TLS Agent exist, creating a new Agent"); + agent = new https__namespace.Agent(Object.assign({ + // keepAlive is true if disableKeepAlive is false. + keepAlive: !disableKeepAlive }, tlsSettings)); + this.cachedHttpsAgents.set(tlsSettings, agent); + return agent; + } + } +} +function getResponseHeaders(res) { + const headers = createHttpHeaders(); + for (const header of Object.keys(res.headers)) { + const value = res.headers[header]; + if (Array.isArray(value)) { + if (value.length > 0) { + headers.set(header, value[0]); + } + } + else if (value) { + headers.set(header, value); + } + } + return headers; +} +function getDecodedResponseStream(stream, headers) { + const contentEncoding = headers.get("Content-Encoding"); + if (contentEncoding === "gzip") { + const unzip = zlib__namespace.createGunzip(); + stream.pipe(unzip); + return unzip; + } + else if (contentEncoding === "deflate") { + const inflate = zlib__namespace.createInflate(); + stream.pipe(inflate); + return inflate; + } + return stream; +} +function streamToText(stream) { + return new Promise((resolve, reject) => { + const buffer = []; + stream.on("data", (chunk) => { + if (Buffer.isBuffer(chunk)) { + buffer.push(chunk); + } + else { + buffer.push(Buffer.from(chunk)); + } + }); + stream.on("end", () => { + resolve(Buffer.concat(buffer).toString("utf8")); + }); + stream.on("error", (e) => { + if (e && (e === null || e === void 0 ? void 0 : e.name) === "AbortError") { + reject(e); + } + else { + reject(new RestError(`Error reading response as text: ${e.message}`, { + code: RestError.PARSE_ERROR, + })); + } + }); + }); +} +/** @internal */ +function getBodyLength(body) { + if (!body) { + return 0; + } + else if (Buffer.isBuffer(body)) { + return body.length; + } + else if (isReadableStream(body)) { + return null; + } + else if (isArrayBuffer(body)) { + return body.byteLength; + } + else if (typeof body === "string") { + return Buffer.from(body).length; + } + else { + return null; + } +} +/** + * Create a new HttpClient instance for the NodeJS environment. + * @internal + */ +function createNodeHttpClient() { + return new NodeHttpClient(); +} + +// Copyright (c) Microsoft Corporation. +/** + * Create the correct HttpClient for the current environment. + */ +function createDefaultHttpClient() { + return createNodeHttpClient(); +} + +// Copyright (c) Microsoft Corporation. +class PipelineRequestImpl { + constructor(options) { + var _a, _b, _c, _d, _e, _f, _g; + this.url = options.url; + this.body = options.body; + this.headers = (_a = options.headers) !== null && _a !== void 0 ? _a : createHttpHeaders(); + this.method = (_b = options.method) !== null && _b !== void 0 ? _b : "GET"; + this.timeout = (_c = options.timeout) !== null && _c !== void 0 ? _c : 0; + this.formData = options.formData; + this.disableKeepAlive = (_d = options.disableKeepAlive) !== null && _d !== void 0 ? _d : false; + this.proxySettings = options.proxySettings; + this.streamResponseStatusCodes = options.streamResponseStatusCodes; + this.withCredentials = (_e = options.withCredentials) !== null && _e !== void 0 ? _e : false; + this.abortSignal = options.abortSignal; + this.tracingOptions = options.tracingOptions; + this.onUploadProgress = options.onUploadProgress; + this.onDownloadProgress = options.onDownloadProgress; + this.requestId = options.requestId || coreUtil.randomUUID(); + this.allowInsecureConnection = (_f = options.allowInsecureConnection) !== null && _f !== void 0 ? _f : false; + this.enableBrowserStreams = (_g = options.enableBrowserStreams) !== null && _g !== void 0 ? _g : false; + } +} +/** + * Creates a new pipeline request with the given options. + * This method is to allow for the easy setting of default values and not required. + * @param options - The options to create the request with. + */ +function createPipelineRequest(options) { + return new PipelineRequestImpl(options); +} + +// Copyright (c) Microsoft Corporation. +/** + * The programmatic identifier of the exponentialRetryPolicy. + */ +const exponentialRetryPolicyName = "exponentialRetryPolicy"; +/** + * A policy that attempts to retry requests while introducing an exponentially increasing delay. + * @param options - Options that configure retry logic. + */ +function exponentialRetryPolicy(options = {}) { + var _a; + return retryPolicy([ + exponentialRetryStrategy(Object.assign(Object.assign({}, options), { ignoreSystemErrors: true })), + ], { + maxRetries: (_a = options.maxRetries) !== null && _a !== void 0 ? _a : DEFAULT_RETRY_POLICY_COUNT, + }); +} + +// Copyright (c) Microsoft Corporation. +/** + * Name of the {@link systemErrorRetryPolicy} + */ +const systemErrorRetryPolicyName = "systemErrorRetryPolicy"; +/** + * A retry policy that specifically seeks to handle errors in the + * underlying transport layer (e.g. DNS lookup failures) rather than + * retryable error codes from the server itself. + * @param options - Options that customize the policy. + */ +function systemErrorRetryPolicy(options = {}) { + var _a; + return { + name: systemErrorRetryPolicyName, + sendRequest: retryPolicy([ + exponentialRetryStrategy(Object.assign(Object.assign({}, options), { ignoreHttpStatusCodes: true })), + ], { + maxRetries: (_a = options.maxRetries) !== null && _a !== void 0 ? _a : DEFAULT_RETRY_POLICY_COUNT, + }).sendRequest, + }; +} + +// Copyright (c) Microsoft Corporation. +/** + * Name of the {@link throttlingRetryPolicy} + */ +const throttlingRetryPolicyName = "throttlingRetryPolicy"; +/** + * A policy that retries when the server sends a 429 response with a Retry-After header. + * + * To learn more, please refer to + * https://docs.microsoft.com/en-us/azure/azure-resource-manager/resource-manager-request-limits, + * https://docs.microsoft.com/en-us/azure/azure-subscription-service-limits and + * https://docs.microsoft.com/en-us/azure/virtual-machines/troubleshooting/troubleshooting-throttling-errors + * + * @param options - Options that configure retry logic. + */ +function throttlingRetryPolicy(options = {}) { + var _a; + return { + name: throttlingRetryPolicyName, + sendRequest: retryPolicy([throttlingRetryStrategy()], { + maxRetries: (_a = options.maxRetries) !== null && _a !== void 0 ? _a : DEFAULT_RETRY_POLICY_COUNT, + }).sendRequest, + }; +} + +// Copyright (c) Microsoft Corporation. +// Default options for the cycler if none are provided +const DEFAULT_CYCLER_OPTIONS = { + forcedRefreshWindowInMs: 1000, + retryIntervalInMs: 3000, + refreshWindowInMs: 1000 * 60 * 2, // Start refreshing 2m before expiry +}; +/** + * Converts an an unreliable access token getter (which may resolve with null) + * into an AccessTokenGetter by retrying the unreliable getter in a regular + * interval. + * + * @param getAccessToken - A function that produces a promise of an access token that may fail by returning null. + * @param retryIntervalInMs - The time (in milliseconds) to wait between retry attempts. + * @param refreshTimeout - The timestamp after which the refresh attempt will fail, throwing an exception. + * @returns - A promise that, if it resolves, will resolve with an access token. + */ +async function beginRefresh(getAccessToken, retryIntervalInMs, refreshTimeout) { + // This wrapper handles exceptions gracefully as long as we haven't exceeded + // the timeout. + async function tryGetAccessToken() { + if (Date.now() < refreshTimeout) { + try { + return await getAccessToken(); + } + catch (_a) { + return null; + } + } + else { + const finalToken = await getAccessToken(); + // Timeout is up, so throw if it's still null + if (finalToken === null) { + throw new Error("Failed to refresh access token."); + } + return finalToken; + } + } + let token = await tryGetAccessToken(); + while (token === null) { + await delay(retryIntervalInMs); + token = await tryGetAccessToken(); + } + return token; +} +/** + * Creates a token cycler from a credential, scopes, and optional settings. + * + * A token cycler represents a way to reliably retrieve a valid access token + * from a TokenCredential. It will handle initializing the token, refreshing it + * when it nears expiration, and synchronizes refresh attempts to avoid + * concurrency hazards. + * + * @param credential - the underlying TokenCredential that provides the access + * token + * @param tokenCyclerOptions - optionally override default settings for the cycler + * + * @returns - a function that reliably produces a valid access token + */ +function createTokenCycler(credential, tokenCyclerOptions) { + let refreshWorker = null; + let token = null; + let tenantId; + const options = Object.assign(Object.assign({}, DEFAULT_CYCLER_OPTIONS), tokenCyclerOptions); + /** + * This little holder defines several predicates that we use to construct + * the rules of refreshing the token. + */ + const cycler = { + /** + * Produces true if a refresh job is currently in progress. + */ + get isRefreshing() { + return refreshWorker !== null; + }, + /** + * Produces true if the cycler SHOULD refresh (we are within the refresh + * window and not already refreshing) + */ + get shouldRefresh() { + var _a; + return (!cycler.isRefreshing && + ((_a = token === null || token === void 0 ? void 0 : token.expiresOnTimestamp) !== null && _a !== void 0 ? _a : 0) - options.refreshWindowInMs < Date.now()); + }, + /** + * Produces true if the cycler MUST refresh (null or nearly-expired + * token). + */ + get mustRefresh() { + return (token === null || token.expiresOnTimestamp - options.forcedRefreshWindowInMs < Date.now()); + }, + }; + /** + * Starts a refresh job or returns the existing job if one is already + * running. + */ + function refresh(scopes, getTokenOptions) { + var _a; + if (!cycler.isRefreshing) { + // We bind `scopes` here to avoid passing it around a lot + const tryGetAccessToken = () => credential.getToken(scopes, getTokenOptions); + // Take advantage of promise chaining to insert an assignment to `token` + // before the refresh can be considered done. + refreshWorker = beginRefresh(tryGetAccessToken, options.retryIntervalInMs, + // If we don't have a token, then we should timeout immediately + (_a = token === null || token === void 0 ? void 0 : token.expiresOnTimestamp) !== null && _a !== void 0 ? _a : Date.now()) + .then((_token) => { + refreshWorker = null; + token = _token; + tenantId = getTokenOptions.tenantId; + return token; + }) + .catch((reason) => { + // We also should reset the refresher if we enter a failed state. All + // existing awaiters will throw, but subsequent requests will start a + // new retry chain. + refreshWorker = null; + token = null; + tenantId = undefined; + throw reason; + }); + } + return refreshWorker; + } + return async (scopes, tokenOptions) => { + // + // Simple rules: + // - If we MUST refresh, then return the refresh task, blocking + // the pipeline until a token is available. + // - If we SHOULD refresh, then run refresh but don't return it + // (we can still use the cached token). + // - Return the token, since it's fine if we didn't return in + // step 1. + // + // If the tenantId passed in token options is different to the one we have + // Or if we are in claim challenge and the token was rejected and a new access token need to be issued, we need to + // refresh the token with the new tenantId or token. + const mustRefresh = tenantId !== tokenOptions.tenantId || Boolean(tokenOptions.claims) || cycler.mustRefresh; + if (mustRefresh) + return refresh(scopes, tokenOptions); + if (cycler.shouldRefresh) { + refresh(scopes, tokenOptions); + } + return token; + }; +} + +// Copyright (c) Microsoft Corporation. +/** + * The programmatic identifier of the bearerTokenAuthenticationPolicy. + */ +const bearerTokenAuthenticationPolicyName = "bearerTokenAuthenticationPolicy"; +/** + * Default authorize request handler + */ +async function defaultAuthorizeRequest(options) { + const { scopes, getAccessToken, request } = options; + const getTokenOptions = { + abortSignal: request.abortSignal, + tracingOptions: request.tracingOptions, + }; + const accessToken = await getAccessToken(scopes, getTokenOptions); + if (accessToken) { + options.request.headers.set("Authorization", `Bearer ${accessToken.token}`); + } +} +/** + * We will retrieve the challenge only if the response status code was 401, + * and if the response contained the header "WWW-Authenticate" with a non-empty value. + */ +function getChallenge(response) { + const challenge = response.headers.get("WWW-Authenticate"); + if (response.status === 401 && challenge) { + return challenge; + } + return; +} +/** + * A policy that can request a token from a TokenCredential implementation and + * then apply it to the Authorization header of a request as a Bearer token. + */ +function bearerTokenAuthenticationPolicy(options) { + var _a; + const { credential, scopes, challengeCallbacks } = options; + const logger$1 = options.logger || logger; + const callbacks = Object.assign({ authorizeRequest: (_a = challengeCallbacks === null || challengeCallbacks === void 0 ? void 0 : challengeCallbacks.authorizeRequest) !== null && _a !== void 0 ? _a : defaultAuthorizeRequest, authorizeRequestOnChallenge: challengeCallbacks === null || challengeCallbacks === void 0 ? void 0 : challengeCallbacks.authorizeRequestOnChallenge }, challengeCallbacks); + // This function encapsulates the entire process of reliably retrieving the token + // The options are left out of the public API until there's demand to configure this. + // Remember to extend `BearerTokenAuthenticationPolicyOptions` with `TokenCyclerOptions` + // in order to pass through the `options` object. + const getAccessToken = credential + ? createTokenCycler(credential /* , options */) + : () => Promise.resolve(null); + return { + name: bearerTokenAuthenticationPolicyName, + /** + * If there's no challenge parameter: + * - It will try to retrieve the token using the cache, or the credential's getToken. + * - Then it will try the next policy with or without the retrieved token. + * + * It uses the challenge parameters to: + * - Skip a first attempt to get the token from the credential if there's no cached token, + * since it expects the token to be retrievable only after the challenge. + * - Prepare the outgoing request if the `prepareRequest` method has been provided. + * - Send an initial request to receive the challenge if it fails. + * - Process a challenge if the response contains it. + * - Retrieve a token with the challenge information, then re-send the request. + */ + async sendRequest(request, next) { + if (!request.url.toLowerCase().startsWith("https://")) { + throw new Error("Bearer token authentication is not permitted for non-TLS protected (non-https) URLs."); + } + await callbacks.authorizeRequest({ + scopes: Array.isArray(scopes) ? scopes : [scopes], + request, + getAccessToken, + logger: logger$1, + }); + let response; + let error; + try { + response = await next(request); + } + catch (err) { + error = err; + response = err.response; + } + if (callbacks.authorizeRequestOnChallenge && + (response === null || response === void 0 ? void 0 : response.status) === 401 && + getChallenge(response)) { + // processes challenge + const shouldSendRequest = await callbacks.authorizeRequestOnChallenge({ + scopes: Array.isArray(scopes) ? scopes : [scopes], + request, + response, + getAccessToken, + logger: logger$1, + }); + if (shouldSendRequest) { + return next(request); + } + } + if (error) { + throw error; + } + else { + return response; + } + }, + }; +} + +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. +/** + * The programmatic identifier of the ndJsonPolicy. + */ +const ndJsonPolicyName = "ndJsonPolicy"; +/** + * ndJsonPolicy is a policy used to control keep alive settings for every request. + */ +function ndJsonPolicy() { + return { + name: ndJsonPolicyName, + async sendRequest(request, next) { + // There currently isn't a good way to bypass the serializer + if (typeof request.body === "string" && request.body.startsWith("[")) { + const body = JSON.parse(request.body); + if (Array.isArray(body)) { + request.body = body.map((item) => JSON.stringify(item) + "\n").join(""); + } + } + return next(request); + }, + }; +} + +// Copyright (c) Microsoft Corporation. +/** + * The programmatic identifier of the auxiliaryAuthenticationHeaderPolicy. + */ +const auxiliaryAuthenticationHeaderPolicyName = "auxiliaryAuthenticationHeaderPolicy"; +const AUTHORIZATION_AUXILIARY_HEADER = "x-ms-authorization-auxiliary"; +async function sendAuthorizeRequest(options) { + var _a, _b; + const { scopes, getAccessToken, request } = options; + const getTokenOptions = { + abortSignal: request.abortSignal, + tracingOptions: request.tracingOptions, + }; + return (_b = (_a = (await getAccessToken(scopes, getTokenOptions))) === null || _a === void 0 ? void 0 : _a.token) !== null && _b !== void 0 ? _b : ""; +} +/** + * A policy for external tokens to `x-ms-authorization-auxiliary` header. + * This header will be used when creating a cross-tenant application we may need to handle authentication requests + * for resources that are in different tenants. + * You could see [ARM docs](https://learn.microsoft.com/en-us/azure/azure-resource-manager/management/authenticate-multi-tenant) for a rundown of how this feature works + */ +function auxiliaryAuthenticationHeaderPolicy(options) { + const { credentials, scopes } = options; + const logger$1 = options.logger || logger; + const tokenCyclerMap = new WeakMap(); + return { + name: auxiliaryAuthenticationHeaderPolicyName, + async sendRequest(request, next) { + if (!request.url.toLowerCase().startsWith("https://")) { + throw new Error("Bearer token authentication for auxiliary header is not permitted for non-TLS protected (non-https) URLs."); + } + if (!credentials || credentials.length === 0) { + logger$1.info(`${auxiliaryAuthenticationHeaderPolicyName} header will not be set due to empty credentials.`); + return next(request); + } + const tokenPromises = []; + for (const credential of credentials) { + let getAccessToken = tokenCyclerMap.get(credential); + if (!getAccessToken) { + getAccessToken = createTokenCycler(credential); + tokenCyclerMap.set(credential, getAccessToken); + } + tokenPromises.push(sendAuthorizeRequest({ + scopes: Array.isArray(scopes) ? scopes : [scopes], + request, + getAccessToken, + logger: logger$1, + })); + } + const auxiliaryTokens = (await Promise.all(tokenPromises)).filter((token) => Boolean(token)); + if (auxiliaryTokens.length === 0) { + logger$1.warning(`None of the auxiliary tokens are valid. ${AUTHORIZATION_AUXILIARY_HEADER} header will not be set.`); + return next(request); + } + request.headers.set(AUTHORIZATION_AUXILIARY_HEADER, auxiliaryTokens.map((token) => `Bearer ${token}`).join(", ")); + return next(request); + }, + }; +} + +exports.RestError = RestError; +exports.auxiliaryAuthenticationHeaderPolicy = auxiliaryAuthenticationHeaderPolicy; +exports.auxiliaryAuthenticationHeaderPolicyName = auxiliaryAuthenticationHeaderPolicyName; +exports.bearerTokenAuthenticationPolicy = bearerTokenAuthenticationPolicy; +exports.bearerTokenAuthenticationPolicyName = bearerTokenAuthenticationPolicyName; +exports.createDefaultHttpClient = createDefaultHttpClient; +exports.createEmptyPipeline = createEmptyPipeline; +exports.createHttpHeaders = createHttpHeaders; +exports.createPipelineFromOptions = createPipelineFromOptions; +exports.createPipelineRequest = createPipelineRequest; +exports.decompressResponsePolicy = decompressResponsePolicy; +exports.decompressResponsePolicyName = decompressResponsePolicyName; +exports.defaultRetryPolicy = defaultRetryPolicy; +exports.exponentialRetryPolicy = exponentialRetryPolicy; +exports.exponentialRetryPolicyName = exponentialRetryPolicyName; +exports.formDataPolicy = formDataPolicy; +exports.formDataPolicyName = formDataPolicyName; +exports.getDefaultProxySettings = getDefaultProxySettings; +exports.isRestError = isRestError; +exports.logPolicy = logPolicy; +exports.logPolicyName = logPolicyName; +exports.ndJsonPolicy = ndJsonPolicy; +exports.ndJsonPolicyName = ndJsonPolicyName; +exports.proxyPolicy = proxyPolicy; +exports.proxyPolicyName = proxyPolicyName; +exports.redirectPolicy = redirectPolicy; +exports.redirectPolicyName = redirectPolicyName; +exports.retryPolicy = retryPolicy; +exports.setClientRequestIdPolicy = setClientRequestIdPolicy; +exports.setClientRequestIdPolicyName = setClientRequestIdPolicyName; +exports.systemErrorRetryPolicy = systemErrorRetryPolicy; +exports.systemErrorRetryPolicyName = systemErrorRetryPolicyName; +exports.throttlingRetryPolicy = throttlingRetryPolicy; +exports.throttlingRetryPolicyName = throttlingRetryPolicyName; +exports.tlsPolicy = tlsPolicy; +exports.tlsPolicyName = tlsPolicyName; +exports.tracingPolicy = tracingPolicy; +exports.tracingPolicyName = tracingPolicyName; +exports.userAgentPolicy = userAgentPolicy; +exports.userAgentPolicyName = userAgentPolicyName; +//# sourceMappingURL=index.js.map + + +/***/ }), + +/***/ 4175: +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ value: true })); + +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. +/** @internal */ +const knownContextKeys = { + span: Symbol.for("@azure/core-tracing span"), + namespace: Symbol.for("@azure/core-tracing namespace"), +}; +/** + * Creates a new {@link TracingContext} with the given options. + * @param options - A set of known keys that may be set on the context. + * @returns A new {@link TracingContext} with the given options. + * + * @internal + */ +function createTracingContext(options = {}) { + let context = new TracingContextImpl(options.parentContext); + if (options.span) { + context = context.setValue(knownContextKeys.span, options.span); + } + if (options.namespace) { + context = context.setValue(knownContextKeys.namespace, options.namespace); + } + return context; +} +/** @internal */ +class TracingContextImpl { + constructor(initialContext) { + this._contextMap = + initialContext instanceof TracingContextImpl + ? new Map(initialContext._contextMap) + : new Map(); + } + setValue(key, value) { + const newContext = new TracingContextImpl(this); + newContext._contextMap.set(key, value); + return newContext; + } + getValue(key) { + return this._contextMap.get(key); + } + deleteValue(key) { + const newContext = new TracingContextImpl(this); + newContext._contextMap.delete(key); + return newContext; + } +} + +// Copyright (c) Microsoft Corporation. +function createDefaultTracingSpan() { + return { + end: () => { + // noop + }, + isRecording: () => false, + recordException: () => { + // noop + }, + setAttribute: () => { + // noop + }, + setStatus: () => { + // noop + }, + }; +} +function createDefaultInstrumenter() { + return { + createRequestHeaders: () => { + return {}; + }, + parseTraceparentHeader: () => { + return undefined; + }, + startSpan: (_name, spanOptions) => { + return { + span: createDefaultTracingSpan(), + tracingContext: createTracingContext({ parentContext: spanOptions.tracingContext }), + }; + }, + withContext(_context, callback, ...callbackArgs) { + return callback(...callbackArgs); + }, + }; +} +/** @internal */ +let instrumenterImplementation; +/** + * Extends the Azure SDK with support for a given instrumenter implementation. + * + * @param instrumenter - The instrumenter implementation to use. + */ +function useInstrumenter(instrumenter) { + instrumenterImplementation = instrumenter; +} +/** + * Gets the currently set instrumenter, a No-Op instrumenter by default. + * + * @returns The currently set instrumenter + */ +function getInstrumenter() { + if (!instrumenterImplementation) { + instrumenterImplementation = createDefaultInstrumenter(); + } + return instrumenterImplementation; +} + +// Copyright (c) Microsoft Corporation. +/** + * Creates a new tracing client. + * + * @param options - Options used to configure the tracing client. + * @returns - An instance of {@link TracingClient}. + */ +function createTracingClient(options) { + const { namespace, packageName, packageVersion } = options; + function startSpan(name, operationOptions, spanOptions) { + var _a; + const startSpanResult = getInstrumenter().startSpan(name, Object.assign(Object.assign({}, spanOptions), { packageName: packageName, packageVersion: packageVersion, tracingContext: (_a = operationOptions === null || operationOptions === void 0 ? void 0 : operationOptions.tracingOptions) === null || _a === void 0 ? void 0 : _a.tracingContext })); + let tracingContext = startSpanResult.tracingContext; + const span = startSpanResult.span; + if (!tracingContext.getValue(knownContextKeys.namespace)) { + tracingContext = tracingContext.setValue(knownContextKeys.namespace, namespace); + } + span.setAttribute("az.namespace", tracingContext.getValue(knownContextKeys.namespace)); + const updatedOptions = Object.assign({}, operationOptions, { + tracingOptions: Object.assign(Object.assign({}, operationOptions === null || operationOptions === void 0 ? void 0 : operationOptions.tracingOptions), { tracingContext }), + }); + return { + span, + updatedOptions, + }; + } + async function withSpan(name, operationOptions, callback, spanOptions) { + const { span, updatedOptions } = startSpan(name, operationOptions, spanOptions); + try { + const result = await withContext(updatedOptions.tracingOptions.tracingContext, () => Promise.resolve(callback(updatedOptions, span))); + span.setStatus({ status: "success" }); + return result; + } + catch (err) { + span.setStatus({ status: "error", error: err }); + throw err; + } + finally { + span.end(); + } + } + function withContext(context, callback, ...callbackArgs) { + return getInstrumenter().withContext(context, callback, ...callbackArgs); + } + /** + * Parses a traceparent header value into a span identifier. + * + * @param traceparentHeader - The traceparent header to parse. + * @returns An implementation-specific identifier for the span. + */ + function parseTraceparentHeader(traceparentHeader) { + return getInstrumenter().parseTraceparentHeader(traceparentHeader); + } + /** + * Creates a set of request headers to propagate tracing information to a backend. + * + * @param tracingContext - The context containing the span to serialize. + * @returns The set of headers to add to a request. + */ + function createRequestHeaders(tracingContext) { + return getInstrumenter().createRequestHeaders(tracingContext); + } + return { + startSpan, + withSpan, + withContext, + parseTraceparentHeader, + createRequestHeaders, + }; +} + +exports.createTracingClient = createTracingClient; +exports.useInstrumenter = useInstrumenter; +//# sourceMappingURL=index.js.map + + +/***/ }), + +/***/ 1333: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ value: true })); + +var abortController = __nccwpck_require__(2557); +var crypto = __nccwpck_require__(6113); + +// Copyright (c) Microsoft Corporation. +/** + * Creates an abortable promise. + * @param buildPromise - A function that takes the resolve and reject functions as parameters. + * @param options - The options for the abortable promise. + * @returns A promise that can be aborted. + */ +function createAbortablePromise(buildPromise, options) { + const { cleanupBeforeAbort, abortSignal, abortErrorMsg } = options !== null && options !== void 0 ? options : {}; + return new Promise((resolve, reject) => { + function rejectOnAbort() { + reject(new abortController.AbortError(abortErrorMsg !== null && abortErrorMsg !== void 0 ? abortErrorMsg : "The operation was aborted.")); + } + function removeListeners() { + abortSignal === null || abortSignal === void 0 ? void 0 : abortSignal.removeEventListener("abort", onAbort); + } + function onAbort() { + cleanupBeforeAbort === null || cleanupBeforeAbort === void 0 ? void 0 : cleanupBeforeAbort(); + removeListeners(); + rejectOnAbort(); + } + if (abortSignal === null || abortSignal === void 0 ? void 0 : abortSignal.aborted) { + return rejectOnAbort(); + } + try { + buildPromise((x) => { + removeListeners(); + resolve(x); + }, (x) => { + removeListeners(); + reject(x); + }); + } + catch (err) { + reject(err); + } + abortSignal === null || abortSignal === void 0 ? void 0 : abortSignal.addEventListener("abort", onAbort); + }); +} + +// Copyright (c) Microsoft Corporation. +const StandardAbortMessage = "The delay was aborted."; +/** + * A wrapper for setTimeout that resolves a promise after timeInMs milliseconds. + * @param timeInMs - The number of milliseconds to be delayed. + * @param options - The options for delay - currently abort options + * @returns Promise that is resolved after timeInMs + */ +function delay(timeInMs, options) { + let token; + const { abortSignal, abortErrorMsg } = options !== null && options !== void 0 ? options : {}; + return createAbortablePromise((resolve) => { + token = setTimeout(resolve, timeInMs); + }, { + cleanupBeforeAbort: () => clearTimeout(token), + abortSignal, + abortErrorMsg: abortErrorMsg !== null && abortErrorMsg !== void 0 ? abortErrorMsg : StandardAbortMessage, + }); +} + +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. +/** + * Returns a random integer value between a lower and upper bound, + * inclusive of both bounds. + * Note that this uses Math.random and isn't secure. If you need to use + * this for any kind of security purpose, find a better source of random. + * @param min - The smallest integer value allowed. + * @param max - The largest integer value allowed. + */ +function getRandomIntegerInclusive(min, max) { + // Make sure inputs are integers. + min = Math.ceil(min); + max = Math.floor(max); + // Pick a random offset from zero to the size of the range. + // Since Math.random() can never return 1, we have to make the range one larger + // in order to be inclusive of the maximum value after we take the floor. + const offset = Math.floor(Math.random() * (max - min + 1)); + return offset + min; +} + +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. +/** + * Helper to determine when an input is a generic JS object. + * @returns true when input is an object type that is not null, Array, RegExp, or Date. + */ +function isObject(input) { + return (typeof input === "object" && + input !== null && + !Array.isArray(input) && + !(input instanceof RegExp) && + !(input instanceof Date)); +} + +// Copyright (c) Microsoft Corporation. +/** + * Typeguard for an error object shape (has name and message) + * @param e - Something caught by a catch clause. + */ +function isError(e) { + if (isObject(e)) { + const hasName = typeof e.name === "string"; + const hasMessage = typeof e.message === "string"; + return hasName && hasMessage; + } + return false; +} +/** + * Given what is thought to be an error object, return the message if possible. + * If the message is missing, returns a stringified version of the input. + * @param e - Something thrown from a try block + * @returns The error message or a string of the input + */ +function getErrorMessage(e) { + if (isError(e)) { + return e.message; + } + else { + let stringified; + try { + if (typeof e === "object" && e) { + stringified = JSON.stringify(e); + } + else { + stringified = String(e); + } + } + catch (err) { + stringified = "[unable to stringify input]"; + } + return `Unknown error ${stringified}`; + } +} + +// Copyright (c) Microsoft Corporation. +/** + * Generates a SHA-256 HMAC signature. + * @param key - The HMAC key represented as a base64 string, used to generate the cryptographic HMAC hash. + * @param stringToSign - The data to be signed. + * @param encoding - The textual encoding to use for the returned HMAC digest. + */ +async function computeSha256Hmac(key, stringToSign, encoding) { + const decodedKey = Buffer.from(key, "base64"); + return crypto.createHmac("sha256", decodedKey).update(stringToSign).digest(encoding); +} +/** + * Generates a SHA-256 hash. + * @param content - The data to be included in the hash. + * @param encoding - The textual encoding to use for the returned hash. + */ +async function computeSha256Hash(content, encoding) { + return crypto.createHash("sha256").update(content).digest(encoding); +} + +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. +/** + * Helper TypeGuard that checks if something is defined or not. + * @param thing - Anything + */ +function isDefined(thing) { + return typeof thing !== "undefined" && thing !== null; +} +/** + * Helper TypeGuard that checks if the input is an object with the specified properties. + * @param thing - Anything. + * @param properties - The name of the properties that should appear in the object. + */ +function isObjectWithProperties(thing, properties) { + if (!isDefined(thing) || typeof thing !== "object") { + return false; + } + for (const property of properties) { + if (!objectHasProperty(thing, property)) { + return false; + } + } + return true; +} +/** + * Helper TypeGuard that checks if the input is an object with the specified property. + * @param thing - Any object. + * @param property - The name of the property that should appear in the object. + */ +function objectHasProperty(thing, property) { + return (isDefined(thing) && typeof thing === "object" && property in thing); +} + +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. +/* + * NOTE: When moving this file, please update "react-native" section in package.json. + */ +/** + * Generated Universally Unique Identifier + * + * @returns RFC4122 v4 UUID. + */ +function generateUUID() { + let uuid = ""; + for (let i = 0; i < 32; i++) { + // Generate a random number between 0 and 15 + const randomNumber = Math.floor(Math.random() * 16); + // Set the UUID version to 4 in the 13th position + if (i === 12) { + uuid += "4"; + } + else if (i === 16) { + // Set the UUID variant to "10" in the 17th position + uuid += (randomNumber & 0x3) | 0x8; + } + else { + // Add a random hexadecimal digit to the UUID string + uuid += randomNumber.toString(16); + } + // Add hyphens to the UUID string at the appropriate positions + if (i === 7 || i === 11 || i === 15 || i === 19) { + uuid += "-"; + } + } + return uuid; +} + +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. +var _a$1; +// NOTE: This is a workaround until we can use `globalThis.crypto.randomUUID` in Node.js 19+. +let uuidFunction = typeof ((_a$1 = globalThis === null || globalThis === void 0 ? void 0 : globalThis.crypto) === null || _a$1 === void 0 ? void 0 : _a$1.randomUUID) === "function" + ? globalThis.crypto.randomUUID.bind(globalThis.crypto) + : crypto.randomUUID; +// Not defined in earlier versions of Node.js 14 +if (!uuidFunction) { + uuidFunction = generateUUID; +} +/** + * Generated Universally Unique Identifier + * + * @returns RFC4122 v4 UUID. + */ +function randomUUID() { + return uuidFunction(); +} + +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. +var _a, _b, _c, _d; +/** + * A constant that indicates whether the environment the code is running is a Web Browser. + */ +// eslint-disable-next-line @azure/azure-sdk/ts-no-window +const isBrowser = typeof window !== "undefined" && typeof window.document !== "undefined"; +/** + * A constant that indicates whether the environment the code is running is a Web Worker. + */ +const isWebWorker = typeof self === "object" && + typeof (self === null || self === void 0 ? void 0 : self.importScripts) === "function" && + (((_a = self.constructor) === null || _a === void 0 ? void 0 : _a.name) === "DedicatedWorkerGlobalScope" || + ((_b = self.constructor) === null || _b === void 0 ? void 0 : _b.name) === "ServiceWorkerGlobalScope" || + ((_c = self.constructor) === null || _c === void 0 ? void 0 : _c.name) === "SharedWorkerGlobalScope"); +/** + * A constant that indicates whether the environment the code is running is Node.JS. + */ +const isNode = typeof process !== "undefined" && Boolean(process.version) && Boolean((_d = process.versions) === null || _d === void 0 ? void 0 : _d.node); +/** + * A constant that indicates whether the environment the code is running is Deno. + */ +const isDeno = typeof Deno !== "undefined" && + typeof Deno.version !== "undefined" && + typeof Deno.version.deno !== "undefined"; +/** + * A constant that indicates whether the environment the code is running is Bun.sh. + */ +const isBun = typeof Bun !== "undefined" && typeof Bun.version !== "undefined"; +/** + * A constant that indicates whether the environment the code is running is in React-Native. + */ +// https://github.com/facebook/react-native/blob/main/packages/react-native/Libraries/Core/setUpNavigator.js +const isReactNative = typeof navigator !== "undefined" && (navigator === null || navigator === void 0 ? void 0 : navigator.product) === "ReactNative"; + +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. +/** + * The helper that transforms bytes with specific character encoding into string + * @param bytes - the uint8array bytes + * @param format - the format we use to encode the byte + * @returns a string of the encoded string + */ +function uint8ArrayToString(bytes, format) { + switch (format) { + case "utf-8": + return uint8ArrayToUtf8String(bytes); + case "base64": + return uint8ArrayToBase64(bytes); + case "base64url": + return uint8ArrayToBase64Url(bytes); + } +} +/** + * The helper that transforms string to specific character encoded bytes array. + * @param value - the string to be converted + * @param format - the format we use to decode the value + * @returns a uint8array + */ +function stringToUint8Array(value, format) { + switch (format) { + case "utf-8": + return utf8StringToUint8Array(value); + case "base64": + return base64ToUint8Array(value); + case "base64url": + return base64UrlToUint8Array(value); + } +} +/** + * Decodes a Uint8Array into a Base64 string. + * @internal + */ +function uint8ArrayToBase64(bytes) { + return Buffer.from(bytes).toString("base64"); +} +/** + * Decodes a Uint8Array into a Base64Url string. + * @internal + */ +function uint8ArrayToBase64Url(bytes) { + return Buffer.from(bytes).toString("base64url"); +} +/** + * Decodes a Uint8Array into a javascript string. + * @internal + */ +function uint8ArrayToUtf8String(bytes) { + return Buffer.from(bytes).toString("utf-8"); +} +/** + * Encodes a JavaScript string into a Uint8Array. + * @internal + */ +function utf8StringToUint8Array(value) { + return Buffer.from(value); +} +/** + * Encodes a Base64 string into a Uint8Array. + * @internal + */ +function base64ToUint8Array(value) { + return Buffer.from(value, "base64"); +} +/** + * Encodes a Base64Url string into a Uint8Array. + * @internal + */ +function base64UrlToUint8Array(value) { + return Buffer.from(value, "base64url"); +} + +exports.computeSha256Hash = computeSha256Hash; +exports.computeSha256Hmac = computeSha256Hmac; +exports.createAbortablePromise = createAbortablePromise; +exports.delay = delay; +exports.getErrorMessage = getErrorMessage; +exports.getRandomIntegerInclusive = getRandomIntegerInclusive; +exports.isBrowser = isBrowser; +exports.isBun = isBun; +exports.isDefined = isDefined; +exports.isDeno = isDeno; +exports.isError = isError; +exports.isNode = isNode; +exports.isObject = isObject; +exports.isObjectWithProperties = isObjectWithProperties; +exports.isReactNative = isReactNative; +exports.isWebWorker = isWebWorker; +exports.objectHasProperty = objectHasProperty; +exports.randomUUID = randomUUID; +exports.stringToUint8Array = stringToUint8Array; +exports.uint8ArrayToString = uint8ArrayToString; +//# sourceMappingURL=index.js.map + + +/***/ }), + +/***/ 3084: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ value: true })); + +var msalNode = __nccwpck_require__(2884); +var logger$o = __nccwpck_require__(3233); +var msalCommon = __nccwpck_require__(5728); +var abortController = __nccwpck_require__(2557); +var coreUtil = __nccwpck_require__(1333); +var uuid = __nccwpck_require__(5840); +var coreClient = __nccwpck_require__(9729); +var coreRestPipeline = __nccwpck_require__(8121); +var coreTracing = __nccwpck_require__(4175); +var fs = __nccwpck_require__(7147); +var os = __nccwpck_require__(2037); +var path = __nccwpck_require__(1017); +var promises = __nccwpck_require__(3292); +var https = __nccwpck_require__(5687); +var child_process = __nccwpck_require__(2081); +var crypto = __nccwpck_require__(6113); +var util = __nccwpck_require__(3837); +var http = __nccwpck_require__(3685); +var open = __nccwpck_require__(5768); +var stoppable = __nccwpck_require__(4477); + +function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; } + +function _interopNamespace(e) { + if (e && e.__esModule) return e; + var n = Object.create(null); + if (e) { + Object.keys(e).forEach(function (k) { + if (k !== 'default') { + var d = Object.getOwnPropertyDescriptor(e, k); + Object.defineProperty(n, k, d.get ? d : { + enumerable: true, + get: function () { return e[k]; } + }); + } + }); + } + n["default"] = e; + return Object.freeze(n); +} + +var msalNode__namespace = /*#__PURE__*/_interopNamespace(msalNode); +var msalCommon__namespace = /*#__PURE__*/_interopNamespace(msalCommon); +var fs__default = /*#__PURE__*/_interopDefaultLegacy(fs); +var os__default = /*#__PURE__*/_interopDefaultLegacy(os); +var path__default = /*#__PURE__*/_interopDefaultLegacy(path); +var https__default = /*#__PURE__*/_interopDefaultLegacy(https); +var child_process__default = /*#__PURE__*/_interopDefaultLegacy(child_process); +var child_process__namespace = /*#__PURE__*/_interopNamespace(child_process); +var http__default = /*#__PURE__*/_interopDefaultLegacy(http); +var open__default = /*#__PURE__*/_interopDefaultLegacy(open); +var stoppable__default = /*#__PURE__*/_interopDefaultLegacy(stoppable); + +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. +function isErrorResponse(errorResponse) { + return (errorResponse && + typeof errorResponse.error === "string" && + typeof errorResponse.error_description === "string"); +} +/** + * The Error.name value of an CredentialUnavailable + */ +const CredentialUnavailableErrorName = "CredentialUnavailableError"; +/** + * This signifies that the credential that was tried in a chained credential + * was not available to be used as the credential. Rather than treating this as + * an error that should halt the chain, it's caught and the chain continues + */ +class CredentialUnavailableError extends Error { + constructor(message) { + super(message); + this.name = CredentialUnavailableErrorName; + } +} +/** + * The Error.name value of an AuthenticationError + */ +const AuthenticationErrorName = "AuthenticationError"; +/** + * Provides details about a failure to authenticate with Azure Active + * Directory. The `errorResponse` field contains more details about + * the specific failure. + */ +class AuthenticationError extends Error { + // eslint-disable-next-line @typescript-eslint/ban-types + constructor(statusCode, errorBody) { + let errorResponse = { + error: "unknown", + errorDescription: "An unknown error occurred and no additional details are available.", + }; + if (isErrorResponse(errorBody)) { + errorResponse = convertOAuthErrorResponseToErrorResponse(errorBody); + } + else if (typeof errorBody === "string") { + try { + // Most error responses will contain JSON-formatted error details + // in the response body + const oauthErrorResponse = JSON.parse(errorBody); + errorResponse = convertOAuthErrorResponseToErrorResponse(oauthErrorResponse); + } + catch (e) { + if (statusCode === 400) { + errorResponse = { + error: "authority_not_found", + errorDescription: "The specified authority URL was not found.", + }; + } + else { + errorResponse = { + error: "unknown_error", + errorDescription: `An unknown error has occurred. Response body:\n\n${errorBody}`, + }; + } + } + } + else { + errorResponse = { + error: "unknown_error", + errorDescription: "An unknown error occurred and no additional details are available.", + }; + } + super(`${errorResponse.error} Status code: ${statusCode}\nMore details:\n${errorResponse.errorDescription}`); + this.statusCode = statusCode; + this.errorResponse = errorResponse; + // Ensure that this type reports the correct name + this.name = AuthenticationErrorName; + } +} +/** + * The Error.name value of an AggregateAuthenticationError + */ +const AggregateAuthenticationErrorName = "AggregateAuthenticationError"; +/** + * Provides an `errors` array containing {@link AuthenticationError} instance + * for authentication failures from credentials in a {@link ChainedTokenCredential}. + */ +class AggregateAuthenticationError extends Error { + constructor(errors, errorMessage) { + const errorDetail = errors.join("\n"); + super(`${errorMessage}\n${errorDetail}`); + this.errors = errors; + // Ensure that this type reports the correct name + this.name = AggregateAuthenticationErrorName; + } +} +function convertOAuthErrorResponseToErrorResponse(errorBody) { + return { + error: errorBody.error, + errorDescription: errorBody.error_description, + correlationId: errorBody.correlation_id, + errorCodes: errorBody.error_codes, + timestamp: errorBody.timestamp, + traceId: errorBody.trace_id, + }; +} +/** + * Error used to enforce authentication after trying to retrieve a token silently. + */ +class AuthenticationRequiredError extends Error { + constructor( + /** + * Optional parameters. A message can be specified. The {@link GetTokenOptions} of the request can also be specified to more easily associate the error with the received parameters. + */ + options) { + super(options.message); + this.scopes = options.scopes; + this.getTokenOptions = options.getTokenOptions; + this.name = "AuthenticationRequiredError"; + } +} + +// Copyright (c) Microsoft Corporation. +/** + * The AzureLogger used for all clients within the identity package + */ +const logger$n = logger$o.createClientLogger("identity"); +/** + * Separates a list of environment variable names into a plain object with two arrays: an array of missing environment variables and another array with assigned environment variables. + * @param supportedEnvVars - List of environment variable names + */ +function processEnvVars(supportedEnvVars) { + return supportedEnvVars.reduce((acc, envVariable) => { + if (process.env[envVariable]) { + acc.assigned.push(envVariable); + } + else { + acc.missing.push(envVariable); + } + return acc; + }, { missing: [], assigned: [] }); +} +/** + * Formatting the success event on the credentials + */ +function formatSuccess(scope) { + return `SUCCESS. Scopes: ${Array.isArray(scope) ? scope.join(", ") : scope}.`; +} +/** + * Formatting the success event on the credentials + */ +function formatError(scope, error) { + let message = "ERROR."; + if (scope === null || scope === void 0 ? void 0 : scope.length) { + message += ` Scopes: ${Array.isArray(scope) ? scope.join(", ") : scope}.`; + } + return `${message} Error message: ${typeof error === "string" ? error : error.message}.`; +} +/** + * Generates a CredentialLoggerInstance. + * + * It logs with the format: + * + * `[title] => [message]` + * + */ +function credentialLoggerInstance(title, parent, log = logger$n) { + const fullTitle = parent ? `${parent.fullTitle} ${title}` : title; + function info(message) { + log.info(`${fullTitle} =>`, message); + } + function warning(message) { + log.warning(`${fullTitle} =>`, message); + } + function verbose(message) { + log.verbose(`${fullTitle} =>`, message); + } + return { + title, + fullTitle, + info, + warning, + verbose, + }; +} +/** + * Generates a CredentialLogger, which is a logger declared at the credential's constructor, and used at any point in the credential. + * It has all the properties of a CredentialLoggerInstance, plus other logger instances, one per method. + * + * It logs with the format: + * + * `[title] => [message]` + * `[title] => getToken() => [message]` + * + */ +function credentialLogger(title, log = logger$n) { + const credLogger = credentialLoggerInstance(title, undefined, log); + return Object.assign(Object.assign({}, credLogger), { parent: log, getToken: credentialLoggerInstance("=> getToken()", credLogger, log) }); +} + +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. +/** + * Current version of the `@azure/identity` package. + */ +const SDK_VERSION = `3.3.0`; +/** + * The default client ID for authentication + * @internal + */ +// TODO: temporary - this is the Azure CLI clientID - we'll replace it when +// Developer Sign On application is available +// https://github.com/Azure/azure-sdk-for-net/blob/main/sdk/identity/Azure.Identity/src/Constants.cs#L9 +const DeveloperSignOnClientId = "04b07795-8ddb-461a-bbee-02f9e1bf7b46"; +/** + * The default tenant for authentication + * @internal + */ +const DefaultTenantId = "common"; +/** + * A list of known Azure authority hosts + */ +exports.AzureAuthorityHosts = void 0; +(function (AzureAuthorityHosts) { + /** + * China-based Azure Authority Host + */ + AzureAuthorityHosts["AzureChina"] = "https://login.chinacloudapi.cn"; + /** + * Germany-based Azure Authority Host + */ + AzureAuthorityHosts["AzureGermany"] = "https://login.microsoftonline.de"; + /** + * US Government Azure Authority Host + */ + AzureAuthorityHosts["AzureGovernment"] = "https://login.microsoftonline.us"; + /** + * Public Cloud Azure Authority Host + */ + AzureAuthorityHosts["AzurePublicCloud"] = "https://login.microsoftonline.com"; +})(exports.AzureAuthorityHosts || (exports.AzureAuthorityHosts = {})); +/** + * The default authority host. + */ +const DefaultAuthorityHost = exports.AzureAuthorityHosts.AzurePublicCloud; +/** + * Allow acquiring tokens for any tenant for multi-tentant auth. + */ +const ALL_TENANTS = ["*"]; +const CACHE_CAE_SUFFIX = ".cae"; +const CACHE_NON_CAE_SUFFIX = ".nocae"; + +// Copyright (c) Microsoft Corporation. +/** + * Latest AuthenticationRecord version + * @internal + */ +const LatestAuthenticationRecordVersion = "1.0"; +/** + * Ensures the validity of the MSAL token + * @internal + */ +function ensureValidMsalToken(scopes, logger, msalToken, getTokenOptions) { + const error = (message) => { + logger.getToken.info(message); + return new AuthenticationRequiredError({ + scopes: Array.isArray(scopes) ? scopes : [scopes], + getTokenOptions, + message, + }); + }; + if (!msalToken) { + throw error("No response"); + } + if (!msalToken.expiresOn) { + throw error(`Response had no "expiresOn" property.`); + } + if (!msalToken.accessToken) { + throw error(`Response had no "accessToken" property.`); + } +} +/** + * Generates a valid authority by combining a host with a tenantId. + * @internal + */ +function getAuthority(tenantId, host) { + if (!host) { + host = DefaultAuthorityHost; + } + if (new RegExp(`${tenantId}/?$`).test(host)) { + return host; + } + if (host.endsWith("/")) { + return host + tenantId; + } + else { + return `${host}/${tenantId}`; + } +} +/** + * Generates the known authorities. + * If the Tenant Id is `adfs`, the authority can't be validated since the format won't match the expected one. + * For that reason, we have to force MSAL to disable validating the authority + * by sending it within the known authorities in the MSAL configuration. + * @internal + */ +function getKnownAuthorities(tenantId, authorityHost, disableInstanceDiscovery) { + if ((tenantId === "adfs" && authorityHost) || disableInstanceDiscovery) { + return [authorityHost]; + } + return []; +} +/** + * Generates a logger that can be passed to the MSAL clients. + * @param logger - The logger of the credential. + * @internal + */ +const defaultLoggerCallback = (logger, platform = coreUtil.isNode ? "Node" : "Browser") => (level, message, containsPii) => { + if (containsPii) { + return; + } + switch (level) { + case msalCommon__namespace.LogLevel.Error: + logger.info(`MSAL ${platform} V2 error: ${message}`); + return; + case msalCommon__namespace.LogLevel.Info: + logger.info(`MSAL ${platform} V2 info message: ${message}`); + return; + case msalCommon__namespace.LogLevel.Verbose: + logger.info(`MSAL ${platform} V2 verbose message: ${message}`); + return; + case msalCommon__namespace.LogLevel.Warning: + logger.info(`MSAL ${platform} V2 warning: ${message}`); + return; + } +}; +/** + * @internal + */ +function getMSALLogLevel(logLevel) { + switch (logLevel) { + case "error": + return msalCommon__namespace.LogLevel.Error; + case "info": + return msalCommon__namespace.LogLevel.Info; + case "verbose": + return msalCommon__namespace.LogLevel.Verbose; + case "warning": + return msalCommon__namespace.LogLevel.Warning; + default: + // default msal logging level should be Info + return msalCommon__namespace.LogLevel.Info; + } +} +/** + * The common utility functions for the MSAL clients. + * Defined as a class so that the classes extending this one can have access to its methods and protected properties. + * + * It keeps track of a logger and an in-memory copy of the AuthenticationRecord. + * + * @internal + */ +class MsalBaseUtilities { + constructor(options) { + this.logger = options.logger; + this.account = options.authenticationRecord; + } + /** + * Generates a UUID + */ + generateUuid() { + return uuid.v4(); + } + /** + * Handles the MSAL authentication result. + * If the result has an account, we update the local account reference. + * If the token received is invalid, an error will be thrown depending on what's missing. + */ + handleResult(scopes, clientId, result, getTokenOptions) { + if (result === null || result === void 0 ? void 0 : result.account) { + this.account = msalToPublic(clientId, result.account); + } + ensureValidMsalToken(scopes, this.logger, result, getTokenOptions); + this.logger.getToken.info(formatSuccess(scopes)); + return { + token: result.accessToken, + expiresOnTimestamp: result.expiresOn.getTime(), + }; + } + /** + * Handles MSAL errors. + */ + handleError(scopes, error, getTokenOptions) { + if (error.name === "AuthError" || + error.name === "ClientAuthError" || + error.name === "BrowserAuthError") { + const msalError = error; + switch (msalError.errorCode) { + case "endpoints_resolution_error": + this.logger.info(formatError(scopes, error.message)); + return new CredentialUnavailableError(error.message); + case "device_code_polling_cancelled": + return new abortController.AbortError("The authentication has been aborted by the caller."); + case "consent_required": + case "interaction_required": + case "login_required": + this.logger.info(formatError(scopes, `Authentication returned errorCode ${msalError.errorCode}`)); + break; + default: + this.logger.info(formatError(scopes, `Failed to acquire token: ${error.message}`)); + break; + } + } + if (error.name === "ClientConfigurationError" || + error.name === "BrowserConfigurationAuthError" || + error.name === "AbortError") { + return error; + } + return new AuthenticationRequiredError({ scopes, getTokenOptions, message: error.message }); + } +} +// transformations.ts +function publicToMsal(account) { + const [environment] = account.authority.match(/([a-z]*\.[a-z]*\.[a-z]*)/) || [""]; + return Object.assign(Object.assign({}, account), { localAccountId: account.homeAccountId, environment }); +} +function msalToPublic(clientId, account) { + const record = { + authority: getAuthority(account.tenantId, account.environment), + homeAccountId: account.homeAccountId, + tenantId: account.tenantId || DefaultTenantId, + username: account.username, + clientId, + version: LatestAuthenticationRecordVersion, + }; + return record; +} +/** + * Serializes an `AuthenticationRecord` into a string. + * + * The output of a serialized authentication record will contain the following properties: + * + * - "authority" + * - "homeAccountId" + * - "clientId" + * - "tenantId" + * - "username" + * - "version" + * + * To later convert this string to a serialized `AuthenticationRecord`, please use the exported function `deserializeAuthenticationRecord()`. + */ +function serializeAuthenticationRecord(record) { + return JSON.stringify(record); +} +/** + * Deserializes a previously serialized authentication record from a string into an object. + * + * The input string must contain the following properties: + * + * - "authority" + * - "homeAccountId" + * - "clientId" + * - "tenantId" + * - "username" + * - "version" + * + * If the version we receive is unsupported, an error will be thrown. + * + * At the moment, the only available version is: "1.0", which is always set when the authentication record is serialized. + * + * @param serializedRecord - Authentication record previously serialized into string. + * @returns AuthenticationRecord. + */ +function deserializeAuthenticationRecord(serializedRecord) { + const parsed = JSON.parse(serializedRecord); + if (parsed.version && parsed.version !== LatestAuthenticationRecordVersion) { + throw Error("Unsupported AuthenticationRecord version"); + } + return parsed; +} + +// Copyright (c) Microsoft Corporation. +function createConfigurationErrorMessage(tenantId) { + return `The current credential is not configured to acquire tokens for tenant ${tenantId}. To enable acquiring tokens for this tenant add it to the AdditionallyAllowedTenants on the credential options, or add "*" to AdditionallyAllowedTenants to allow acquiring tokens for any tenant.`; +} +/** + * Of getToken contains a tenantId, this functions allows picking this tenantId as the appropriate for authentication, + * unless multitenant authentication has been disabled through the AZURE_IDENTITY_DISABLE_MULTITENANTAUTH (on Node.js), + * or unless the original tenant Id is `adfs`. + * @internal + */ +function processMultiTenantRequest(tenantId, getTokenOptions, additionallyAllowedTenantIds = [], logger) { + var _a; + let resolvedTenantId; + if (process.env.AZURE_IDENTITY_DISABLE_MULTITENANTAUTH) { + resolvedTenantId = tenantId; + } + else if (tenantId === "adfs") { + resolvedTenantId = tenantId; + } + else { + resolvedTenantId = (_a = getTokenOptions === null || getTokenOptions === void 0 ? void 0 : getTokenOptions.tenantId) !== null && _a !== void 0 ? _a : tenantId; + } + if (tenantId && + resolvedTenantId !== tenantId && + !additionallyAllowedTenantIds.includes("*") && + !additionallyAllowedTenantIds.some((t) => t.localeCompare(resolvedTenantId) === 0)) { + const message = createConfigurationErrorMessage(tenantId); + logger === null || logger === void 0 ? void 0 : logger.info(message); + throw new CredentialUnavailableError(message); + } + return resolvedTenantId; +} + +// Copyright (c) Microsoft Corporation. +/** + * @internal + */ +function checkTenantId(logger, tenantId) { + if (!tenantId.match(/^[0-9a-zA-Z-.:/]+$/)) { + const error = new Error("Invalid tenant id provided. You can locate your tenant id by following the instructions listed here: https://docs.microsoft.com/partner-center/find-ids-and-domain-names."); + logger.info(formatError("", error)); + throw error; + } +} +/** + * @internal + */ +function resolveTenantId(logger, tenantId, clientId) { + if (tenantId) { + checkTenantId(logger, tenantId); + return tenantId; + } + if (!clientId) { + clientId = DeveloperSignOnClientId; + } + if (clientId !== DeveloperSignOnClientId) { + return "common"; + } + return "organizations"; +} +/** + * @internal + */ +function resolveAddionallyAllowedTenantIds(additionallyAllowedTenants) { + if (!additionallyAllowedTenants || additionallyAllowedTenants.length === 0) { + return []; + } + if (additionallyAllowedTenants.includes("*")) { + return ALL_TENANTS; + } + return additionallyAllowedTenants; +} + +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. +function getIdentityTokenEndpointSuffix(tenantId) { + if (tenantId === "adfs") { + return "oauth2/token"; + } + else { + return "oauth2/v2.0/token"; + } +} + +// Copyright (c) Microsoft Corporation. +/** + * Creates a span using the global tracer. + * @internal + */ +const tracingClient = coreTracing.createTracingClient({ + namespace: "Microsoft.AAD", + packageName: "@azure/identity", + packageVersion: SDK_VERSION, +}); + +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. +const DefaultScopeSuffix = "/.default"; +const imdsHost = "http://169.254.169.254"; +const imdsEndpointPath = "/metadata/identity/oauth2/token"; +const imdsApiVersion = "2018-02-01"; +const azureArcAPIVersion = "2019-11-01"; +const azureFabricVersion = "2019-07-01-preview"; + +// Copyright (c) Microsoft Corporation. +/** + * Most MSIs send requests to the IMDS endpoint, or a similar endpoint. + * These are GET requests that require sending a `resource` parameter on the query. + * This resource can be derived from the scopes received through the getToken call, as long as only one scope is received. + * Multiple scopes assume that the resulting token will have access to multiple resources, which won't be the case. + * + * For that reason, when we encounter multiple scopes, we return undefined. + * It's up to the individual MSI implementations to throw the errors (which helps us provide less generic errors). + */ +function mapScopesToResource(scopes) { + let scope = ""; + if (Array.isArray(scopes)) { + if (scopes.length !== 1) { + return; + } + scope = scopes[0]; + } + else if (typeof scopes === "string") { + scope = scopes; + } + if (!scope.endsWith(DefaultScopeSuffix)) { + return scope; + } + return scope.substr(0, scope.lastIndexOf(DefaultScopeSuffix)); +} +/** + * Given a token response, return the expiration timestamp as the number of milliseconds from the Unix epoch. + * @param body - A parsed response body from the authentication endpoint. + */ +function parseExpirationTimestamp(body) { + if (typeof body.expires_on === "number") { + return body.expires_on * 1000; + } + if (typeof body.expires_on === "string") { + const asNumber = +body.expires_on; + if (!isNaN(asNumber)) { + return asNumber * 1000; + } + const asDate = Date.parse(body.expires_on); + if (!isNaN(asDate)) { + return asDate; + } + } + if (typeof body.expires_in === "number") { + return Date.now() + body.expires_in * 1000; + } + throw new Error(`Failed to parse token expiration from body. expires_in="${body.expires_in}", expires_on="${body.expires_on}"`); +} + +// Copyright (c) Microsoft Corporation. +const noCorrelationId = "noCorrelationId"; +/** + * @internal + */ +function getIdentityClientAuthorityHost(options) { + // The authorityHost can come from options or from the AZURE_AUTHORITY_HOST environment variable. + let authorityHost = options === null || options === void 0 ? void 0 : options.authorityHost; + // The AZURE_AUTHORITY_HOST environment variable can only be provided in Node.js. + if (coreUtil.isNode) { + authorityHost = authorityHost !== null && authorityHost !== void 0 ? authorityHost : process.env.AZURE_AUTHORITY_HOST; + } + // If the authorityHost is not provided, we use the default one from the public cloud: https://login.microsoftonline.com + return authorityHost !== null && authorityHost !== void 0 ? authorityHost : DefaultAuthorityHost; +} +/** + * The network module used by the Identity credentials. + * + * It allows for credentials to abort any pending request independently of the MSAL flow, + * by calling to the `abortRequests()` method. + * + */ +class IdentityClient extends coreClient.ServiceClient { + constructor(options) { + var _a, _b; + const packageDetails = `azsdk-js-identity/${SDK_VERSION}`; + const userAgentPrefix = ((_a = options === null || options === void 0 ? void 0 : options.userAgentOptions) === null || _a === void 0 ? void 0 : _a.userAgentPrefix) + ? `${options.userAgentOptions.userAgentPrefix} ${packageDetails}` + : `${packageDetails}`; + const baseUri = getIdentityClientAuthorityHost(options); + if (!baseUri.startsWith("https:")) { + throw new Error("The authorityHost address must use the 'https' protocol."); + } + super(Object.assign(Object.assign({ requestContentType: "application/json; charset=utf-8", retryOptions: { + maxRetries: 3, + } }, options), { userAgentOptions: { + userAgentPrefix, + }, baseUri })); + this.authorityHost = baseUri; + this.abortControllers = new Map(); + this.allowLoggingAccountIdentifiers = (_b = options === null || options === void 0 ? void 0 : options.loggingOptions) === null || _b === void 0 ? void 0 : _b.allowLoggingAccountIdentifiers; + // used for WorkloadIdentity + this.tokenCredentialOptions = Object.assign({}, options); + } + async sendTokenRequest(request) { + logger$n.info(`IdentityClient: sending token request to [${request.url}]`); + const response = await this.sendRequest(request); + if (response.bodyAsText && (response.status === 200 || response.status === 201)) { + const parsedBody = JSON.parse(response.bodyAsText); + if (!parsedBody.access_token) { + return null; + } + this.logIdentifiers(response); + const token = { + accessToken: { + token: parsedBody.access_token, + expiresOnTimestamp: parseExpirationTimestamp(parsedBody), + }, + refreshToken: parsedBody.refresh_token, + }; + logger$n.info(`IdentityClient: [${request.url}] token acquired, expires on ${token.accessToken.expiresOnTimestamp}`); + return token; + } + else { + const error = new AuthenticationError(response.status, response.bodyAsText); + logger$n.warning(`IdentityClient: authentication error. HTTP status: ${response.status}, ${error.errorResponse.errorDescription}`); + throw error; + } + } + async refreshAccessToken(tenantId, clientId, scopes, refreshToken, clientSecret, options = {}) { + if (refreshToken === undefined) { + return null; + } + logger$n.info(`IdentityClient: refreshing access token with client ID: ${clientId}, scopes: ${scopes} started`); + const refreshParams = { + grant_type: "refresh_token", + client_id: clientId, + refresh_token: refreshToken, + scope: scopes, + }; + if (clientSecret !== undefined) { + refreshParams.client_secret = clientSecret; + } + const query = new URLSearchParams(refreshParams); + return tracingClient.withSpan("IdentityClient.refreshAccessToken", options, async (updatedOptions) => { + try { + const urlSuffix = getIdentityTokenEndpointSuffix(tenantId); + const request = coreRestPipeline.createPipelineRequest({ + url: `${this.authorityHost}/${tenantId}/${urlSuffix}`, + method: "POST", + body: query.toString(), + abortSignal: options.abortSignal, + headers: coreRestPipeline.createHttpHeaders({ + Accept: "application/json", + "Content-Type": "application/x-www-form-urlencoded", + }), + tracingOptions: updatedOptions.tracingOptions, + }); + const response = await this.sendTokenRequest(request); + logger$n.info(`IdentityClient: refreshed token for client ID: ${clientId}`); + return response; + } + catch (err) { + if (err.name === AuthenticationErrorName && + err.errorResponse.error === "interaction_required") { + // It's likely that the refresh token has expired, so + // return null so that the credential implementation will + // initiate the authentication flow again. + logger$n.info(`IdentityClient: interaction required for client ID: ${clientId}`); + return null; + } + else { + logger$n.warning(`IdentityClient: failed refreshing token for client ID: ${clientId}: ${err}`); + throw err; + } + } + }); + } + // Here is a custom layer that allows us to abort requests that go through MSAL, + // since MSAL doesn't allow us to pass options all the way through. + generateAbortSignal(correlationId) { + const controller = new abortController.AbortController(); + const controllers = this.abortControllers.get(correlationId) || []; + controllers.push(controller); + this.abortControllers.set(correlationId, controllers); + const existingOnAbort = controller.signal.onabort; + controller.signal.onabort = (...params) => { + this.abortControllers.set(correlationId, undefined); + if (existingOnAbort) { + existingOnAbort(...params); + } + }; + return controller.signal; + } + abortRequests(correlationId) { + const key = correlationId || noCorrelationId; + const controllers = [ + ...(this.abortControllers.get(key) || []), + // MSAL passes no correlation ID to the get requests... + ...(this.abortControllers.get(noCorrelationId) || []), + ]; + if (!controllers.length) { + return; + } + for (const controller of controllers) { + controller.abort(); + } + this.abortControllers.set(key, undefined); + } + getCorrelationId(options) { + var _a; + const parameter = (_a = options === null || options === void 0 ? void 0 : options.body) === null || _a === void 0 ? void 0 : _a.split("&").map((part) => part.split("=")).find(([key]) => key === "client-request-id"); + return parameter && parameter.length ? parameter[1] || noCorrelationId : noCorrelationId; + } + // The MSAL network module methods follow + async sendGetRequestAsync(url, options) { + const request = coreRestPipeline.createPipelineRequest({ + url, + method: "GET", + body: options === null || options === void 0 ? void 0 : options.body, + headers: coreRestPipeline.createHttpHeaders(options === null || options === void 0 ? void 0 : options.headers), + abortSignal: this.generateAbortSignal(noCorrelationId), + }); + const response = await this.sendRequest(request); + this.logIdentifiers(response); + return { + body: response.bodyAsText ? JSON.parse(response.bodyAsText) : undefined, + headers: response.headers.toJSON(), + status: response.status, + }; + } + async sendPostRequestAsync(url, options) { + const request = coreRestPipeline.createPipelineRequest({ + url, + method: "POST", + body: options === null || options === void 0 ? void 0 : options.body, + headers: coreRestPipeline.createHttpHeaders(options === null || options === void 0 ? void 0 : options.headers), + // MSAL doesn't send the correlation ID on the get requests. + abortSignal: this.generateAbortSignal(this.getCorrelationId(options)), + }); + const response = await this.sendRequest(request); + this.logIdentifiers(response); + return { + body: response.bodyAsText ? JSON.parse(response.bodyAsText) : undefined, + headers: response.headers.toJSON(), + status: response.status, + }; + } + /** + * + * @internal + */ + getTokenCredentialOptions() { + return this.tokenCredentialOptions; + } + /** + * If allowLoggingAccountIdentifiers was set on the constructor options + * we try to log the account identifiers by parsing the received access token. + * + * The account identifiers we try to log are: + * - `appid`: The application or Client Identifier. + * - `upn`: User Principal Name. + * - It might not be available in some authentication scenarios. + * - If it's not available, we put a placeholder: "No User Principal Name available". + * - `tid`: Tenant Identifier. + * - `oid`: Object Identifier of the authenticated user. + */ + logIdentifiers(response) { + if (!this.allowLoggingAccountIdentifiers || !response.bodyAsText) { + return; + } + const unavailableUpn = "No User Principal Name available"; + try { + const parsed = response.parsedBody || JSON.parse(response.bodyAsText); + const accessToken = parsed.access_token; + if (!accessToken) { + // Without an access token allowLoggingAccountIdentifiers isn't useful. + return; + } + const base64Metadata = accessToken.split(".")[1]; + const { appid, upn, tid, oid } = JSON.parse(Buffer.from(base64Metadata, "base64").toString("utf8")); + logger$n.info(`[Authenticated account] Client ID: ${appid}. Tenant ID: ${tid}. User Principal Name: ${upn || unavailableUpn}. Object ID (user): ${oid}`); + } + catch (e) { + logger$n.warning("allowLoggingAccountIdentifiers was set, but we couldn't log the account information. Error:", e.message); + } + } +} + +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. +/** + * Helps specify a regional authority, or "AutoDiscoverRegion" to auto-detect the region. + */ +var RegionalAuthority; +(function (RegionalAuthority) { + /** Instructs MSAL to attempt to discover the region */ + RegionalAuthority["AutoDiscoverRegion"] = "AutoDiscoverRegion"; + /** Uses the {@link RegionalAuthority} for the Azure 'westus' region. */ + RegionalAuthority["USWest"] = "westus"; + /** Uses the {@link RegionalAuthority} for the Azure 'westus2' region. */ + RegionalAuthority["USWest2"] = "westus2"; + /** Uses the {@link RegionalAuthority} for the Azure 'centralus' region. */ + RegionalAuthority["USCentral"] = "centralus"; + /** Uses the {@link RegionalAuthority} for the Azure 'eastus' region. */ + RegionalAuthority["USEast"] = "eastus"; + /** Uses the {@link RegionalAuthority} for the Azure 'eastus2' region. */ + RegionalAuthority["USEast2"] = "eastus2"; + /** Uses the {@link RegionalAuthority} for the Azure 'northcentralus' region. */ + RegionalAuthority["USNorthCentral"] = "northcentralus"; + /** Uses the {@link RegionalAuthority} for the Azure 'southcentralus' region. */ + RegionalAuthority["USSouthCentral"] = "southcentralus"; + /** Uses the {@link RegionalAuthority} for the Azure 'westcentralus' region. */ + RegionalAuthority["USWestCentral"] = "westcentralus"; + /** Uses the {@link RegionalAuthority} for the Azure 'canadacentral' region. */ + RegionalAuthority["CanadaCentral"] = "canadacentral"; + /** Uses the {@link RegionalAuthority} for the Azure 'canadaeast' region. */ + RegionalAuthority["CanadaEast"] = "canadaeast"; + /** Uses the {@link RegionalAuthority} for the Azure 'brazilsouth' region. */ + RegionalAuthority["BrazilSouth"] = "brazilsouth"; + /** Uses the {@link RegionalAuthority} for the Azure 'northeurope' region. */ + RegionalAuthority["EuropeNorth"] = "northeurope"; + /** Uses the {@link RegionalAuthority} for the Azure 'westeurope' region. */ + RegionalAuthority["EuropeWest"] = "westeurope"; + /** Uses the {@link RegionalAuthority} for the Azure 'uksouth' region. */ + RegionalAuthority["UKSouth"] = "uksouth"; + /** Uses the {@link RegionalAuthority} for the Azure 'ukwest' region. */ + RegionalAuthority["UKWest"] = "ukwest"; + /** Uses the {@link RegionalAuthority} for the Azure 'francecentral' region. */ + RegionalAuthority["FranceCentral"] = "francecentral"; + /** Uses the {@link RegionalAuthority} for the Azure 'francesouth' region. */ + RegionalAuthority["FranceSouth"] = "francesouth"; + /** Uses the {@link RegionalAuthority} for the Azure 'switzerlandnorth' region. */ + RegionalAuthority["SwitzerlandNorth"] = "switzerlandnorth"; + /** Uses the {@link RegionalAuthority} for the Azure 'switzerlandwest' region. */ + RegionalAuthority["SwitzerlandWest"] = "switzerlandwest"; + /** Uses the {@link RegionalAuthority} for the Azure 'germanynorth' region. */ + RegionalAuthority["GermanyNorth"] = "germanynorth"; + /** Uses the {@link RegionalAuthority} for the Azure 'germanywestcentral' region. */ + RegionalAuthority["GermanyWestCentral"] = "germanywestcentral"; + /** Uses the {@link RegionalAuthority} for the Azure 'norwaywest' region. */ + RegionalAuthority["NorwayWest"] = "norwaywest"; + /** Uses the {@link RegionalAuthority} for the Azure 'norwayeast' region. */ + RegionalAuthority["NorwayEast"] = "norwayeast"; + /** Uses the {@link RegionalAuthority} for the Azure 'eastasia' region. */ + RegionalAuthority["AsiaEast"] = "eastasia"; + /** Uses the {@link RegionalAuthority} for the Azure 'southeastasia' region. */ + RegionalAuthority["AsiaSouthEast"] = "southeastasia"; + /** Uses the {@link RegionalAuthority} for the Azure 'japaneast' region. */ + RegionalAuthority["JapanEast"] = "japaneast"; + /** Uses the {@link RegionalAuthority} for the Azure 'japanwest' region. */ + RegionalAuthority["JapanWest"] = "japanwest"; + /** Uses the {@link RegionalAuthority} for the Azure 'australiaeast' region. */ + RegionalAuthority["AustraliaEast"] = "australiaeast"; + /** Uses the {@link RegionalAuthority} for the Azure 'australiasoutheast' region. */ + RegionalAuthority["AustraliaSouthEast"] = "australiasoutheast"; + /** Uses the {@link RegionalAuthority} for the Azure 'australiacentral' region. */ + RegionalAuthority["AustraliaCentral"] = "australiacentral"; + /** Uses the {@link RegionalAuthority} for the Azure 'australiacentral2' region. */ + RegionalAuthority["AustraliaCentral2"] = "australiacentral2"; + /** Uses the {@link RegionalAuthority} for the Azure 'centralindia' region. */ + RegionalAuthority["IndiaCentral"] = "centralindia"; + /** Uses the {@link RegionalAuthority} for the Azure 'southindia' region. */ + RegionalAuthority["IndiaSouth"] = "southindia"; + /** Uses the {@link RegionalAuthority} for the Azure 'westindia' region. */ + RegionalAuthority["IndiaWest"] = "westindia"; + /** Uses the {@link RegionalAuthority} for the Azure 'koreasouth' region. */ + RegionalAuthority["KoreaSouth"] = "koreasouth"; + /** Uses the {@link RegionalAuthority} for the Azure 'koreacentral' region. */ + RegionalAuthority["KoreaCentral"] = "koreacentral"; + /** Uses the {@link RegionalAuthority} for the Azure 'uaecentral' region. */ + RegionalAuthority["UAECentral"] = "uaecentral"; + /** Uses the {@link RegionalAuthority} for the Azure 'uaenorth' region. */ + RegionalAuthority["UAENorth"] = "uaenorth"; + /** Uses the {@link RegionalAuthority} for the Azure 'southafricanorth' region. */ + RegionalAuthority["SouthAfricaNorth"] = "southafricanorth"; + /** Uses the {@link RegionalAuthority} for the Azure 'southafricawest' region. */ + RegionalAuthority["SouthAfricaWest"] = "southafricawest"; + /** Uses the {@link RegionalAuthority} for the Azure 'chinanorth' region. */ + RegionalAuthority["ChinaNorth"] = "chinanorth"; + /** Uses the {@link RegionalAuthority} for the Azure 'chinaeast' region. */ + RegionalAuthority["ChinaEast"] = "chinaeast"; + /** Uses the {@link RegionalAuthority} for the Azure 'chinanorth2' region. */ + RegionalAuthority["ChinaNorth2"] = "chinanorth2"; + /** Uses the {@link RegionalAuthority} for the Azure 'chinaeast2' region. */ + RegionalAuthority["ChinaEast2"] = "chinaeast2"; + /** Uses the {@link RegionalAuthority} for the Azure 'germanycentral' region. */ + RegionalAuthority["GermanyCentral"] = "germanycentral"; + /** Uses the {@link RegionalAuthority} for the Azure 'germanynortheast' region. */ + RegionalAuthority["GermanyNorthEast"] = "germanynortheast"; + /** Uses the {@link RegionalAuthority} for the Azure 'usgovvirginia' region. */ + RegionalAuthority["GovernmentUSVirginia"] = "usgovvirginia"; + /** Uses the {@link RegionalAuthority} for the Azure 'usgoviowa' region. */ + RegionalAuthority["GovernmentUSIowa"] = "usgoviowa"; + /** Uses the {@link RegionalAuthority} for the Azure 'usgovarizona' region. */ + RegionalAuthority["GovernmentUSArizona"] = "usgovarizona"; + /** Uses the {@link RegionalAuthority} for the Azure 'usgovtexas' region. */ + RegionalAuthority["GovernmentUSTexas"] = "usgovtexas"; + /** Uses the {@link RegionalAuthority} for the Azure 'usdodeast' region. */ + RegionalAuthority["GovernmentUSDodEast"] = "usdodeast"; + /** Uses the {@link RegionalAuthority} for the Azure 'usdodcentral' region. */ + RegionalAuthority["GovernmentUSDodCentral"] = "usdodcentral"; +})(RegionalAuthority || (RegionalAuthority = {})); + +// Copyright (c) Microsoft Corporation. +/** + * The current persistence provider, undefined by default. + * @internal + */ +let persistenceProvider = undefined; +/** + * An object that allows setting the persistence provider. + * @internal + */ +const msalNodeFlowCacheControl = { + setPersistence(pluginProvider) { + persistenceProvider = pluginProvider; + }, +}; +/** + * MSAL partial base client for Node.js. + * + * It completes the input configuration with some default values. + * It also provides with utility protected methods that can be used from any of the clients, + * which includes handlers for successful responses and errors. + * + * @internal + */ +class MsalNode extends MsalBaseUtilities { + constructor(options) { + var _a, _b, _c, _d; + super(options); + // protected publicApp: msalNode.PublicClientApplication | undefined; + // protected publicAppCae: msalNode.PublicClientApplication | undefined; + // protected confidentialApp: msalNode.ConfidentialClientApplication | undefined; + // protected confidentialAppCae: msalNode.ConfidentialClientApplication | undefined; + this.app = {}; + this.caeApp = {}; + this.requiresConfidential = false; + this.msalConfig = this.defaultNodeMsalConfig(options); + this.tenantId = resolveTenantId(options.logger, options.tenantId, options.clientId); + this.additionallyAllowedTenantIds = resolveAddionallyAllowedTenantIds((_a = options === null || options === void 0 ? void 0 : options.tokenCredentialOptions) === null || _a === void 0 ? void 0 : _a.additionallyAllowedTenants); + this.clientId = this.msalConfig.auth.clientId; + if (options === null || options === void 0 ? void 0 : options.getAssertion) { + this.getAssertion = options.getAssertion; + } + // If persistence has been configured + if (persistenceProvider !== undefined && ((_b = options.tokenCachePersistenceOptions) === null || _b === void 0 ? void 0 : _b.enabled)) { + const nonCaeOptions = Object.assign({ name: `${options.tokenCachePersistenceOptions.name}.${CACHE_NON_CAE_SUFFIX}` }, options.tokenCachePersistenceOptions); + const caeOptions = Object.assign({ name: `${options.tokenCachePersistenceOptions.name}.${CACHE_CAE_SUFFIX}` }, options.tokenCachePersistenceOptions); + this.createCachePlugin = () => persistenceProvider(nonCaeOptions); + this.createCachePluginCae = () => persistenceProvider(caeOptions); + } + else if ((_c = options.tokenCachePersistenceOptions) === null || _c === void 0 ? void 0 : _c.enabled) { + throw new Error([ + "Persistent token caching was requested, but no persistence provider was configured.", + "You must install the identity-cache-persistence plugin package (`npm install --save @azure/identity-cache-persistence`)", + "and enable it by importing `useIdentityPlugin` from `@azure/identity` and calling", + "`useIdentityPlugin(cachePersistencePlugin)` before using `tokenCachePersistenceOptions`.", + ].join(" ")); + } + this.azureRegion = (_d = options.regionalAuthority) !== null && _d !== void 0 ? _d : process.env.AZURE_REGIONAL_AUTHORITY_NAME; + if (this.azureRegion === RegionalAuthority.AutoDiscoverRegion) { + this.azureRegion = "AUTO_DISCOVER"; + } + } + /** + * Generates a MSAL configuration that generally works for Node.js + */ + defaultNodeMsalConfig(options) { + var _a; + const clientId = options.clientId || DeveloperSignOnClientId; + const tenantId = resolveTenantId(options.logger, options.tenantId, options.clientId); + this.authorityHost = options.authorityHost || process.env.AZURE_AUTHORITY_HOST; + const authority = getAuthority(tenantId, this.authorityHost); + this.identityClient = new IdentityClient(Object.assign(Object.assign({}, options.tokenCredentialOptions), { authorityHost: authority, loggingOptions: options.loggingOptions })); + const clientCapabilities = []; + return { + auth: { + clientId, + authority, + knownAuthorities: getKnownAuthorities(tenantId, authority, options.disableInstanceDiscovery), + clientCapabilities, + }, + // Cache is defined in this.prepare(); + system: { + networkClient: this.identityClient, + loggerOptions: { + loggerCallback: defaultLoggerCallback(options.logger), + logLevel: getMSALLogLevel(logger$o.getLogLevel()), + piiLoggingEnabled: (_a = options.loggingOptions) === null || _a === void 0 ? void 0 : _a.enableUnsafeSupportLogging, + }, + }, + }; + } + getApp(appType, enableCae) { + const app = enableCae ? this.caeApp : this.app; + if (appType === "publicFirst") { + return (app.public || app.confidential); + } + else if (appType === "confidentialFirst") { + return (app.confidential || app.public); + } + else if (appType === "confidential") { + return app.confidential; + } + else { + return app.public; + } + } + /** + * Prepares the MSAL applications. + */ + async init(options) { + if (options === null || options === void 0 ? void 0 : options.abortSignal) { + options.abortSignal.addEventListener("abort", () => { + // This will abort any pending request in the IdentityClient, + // based on the received or generated correlationId + this.identityClient.abortRequests(options.correlationId); + }); + } + const app = (options === null || options === void 0 ? void 0 : options.enableCae) ? this.caeApp : this.app; + if (options === null || options === void 0 ? void 0 : options.enableCae) { + this.msalConfig.auth.clientCapabilities = ["cp1"]; + } + if (app.public || app.confidential) { + return; + } + if ((options === null || options === void 0 ? void 0 : options.enableCae) && this.createCachePluginCae !== undefined) { + this.msalConfig.cache = { + cachePlugin: await this.createCachePluginCae(), + }; + } + if (this.createCachePlugin !== undefined) { + this.msalConfig.cache = { + cachePlugin: await this.createCachePlugin(), + }; + } + if (options === null || options === void 0 ? void 0 : options.enableCae) { + this.caeApp.public = new msalNode__namespace.PublicClientApplication(this.msalConfig); + } + else { + this.app.public = new msalNode__namespace.PublicClientApplication(this.msalConfig); + } + if (this.getAssertion) { + this.msalConfig.auth.clientAssertion = await this.getAssertion(); + } + // The confidential client requires either a secret, assertion or certificate. + if (this.msalConfig.auth.clientSecret || + this.msalConfig.auth.clientAssertion || + this.msalConfig.auth.clientCertificate) { + if (options === null || options === void 0 ? void 0 : options.enableCae) { + this.caeApp.confidential = new msalNode__namespace.ConfidentialClientApplication(this.msalConfig); + } + else { + this.app.confidential = new msalNode__namespace.ConfidentialClientApplication(this.msalConfig); + } + } + else { + if (this.requiresConfidential) { + throw new Error("Unable to generate the MSAL confidential client. Missing either the client's secret, certificate or assertion."); + } + } + } + /** + * Allows the cancellation of a MSAL request. + */ + withCancellation(promise, abortSignal, onCancel) { + return new Promise((resolve, reject) => { + promise + .then((msalToken) => { + return resolve(msalToken); + }) + .catch(reject); + if (abortSignal) { + abortSignal.addEventListener("abort", () => { + onCancel === null || onCancel === void 0 ? void 0 : onCancel(); + }); + } + }); + } + /** + * Returns the existing account, attempts to load the account from MSAL. + */ + async getActiveAccount(enableCae = false) { + if (this.account) { + return this.account; + } + const cache = this.getApp("confidentialFirst", enableCae).getTokenCache(); + const accountsByTenant = await (cache === null || cache === void 0 ? void 0 : cache.getAllAccounts()); + if (!accountsByTenant) { + return; + } + if (accountsByTenant.length === 1) { + this.account = msalToPublic(this.clientId, accountsByTenant[0]); + } + else { + this.logger + .info(`More than one account was found authenticated for this Client ID and Tenant ID. +However, no "authenticationRecord" has been provided for this credential, +therefore we're unable to pick between these accounts. +A new login attempt will be requested, to ensure the correct account is picked. +To work with multiple accounts for the same Client ID and Tenant ID, please provide an "authenticationRecord" when initializing a credential to prevent this from happening.`); + return; + } + return this.account; + } + /** + * Attempts to retrieve a token from cache. + */ + async getTokenSilent(scopes, options) { + var _a, _b, _c; + await this.getActiveAccount(options === null || options === void 0 ? void 0 : options.enableCae); + if (!this.account) { + throw new AuthenticationRequiredError({ + scopes, + getTokenOptions: options, + message: "Silent authentication failed. We couldn't retrieve an active account from the cache.", + }); + } + const silentRequest = { + // To be able to re-use the account, the Token Cache must also have been provided. + account: publicToMsal(this.account), + correlationId: options === null || options === void 0 ? void 0 : options.correlationId, + scopes, + authority: options === null || options === void 0 ? void 0 : options.authority, + claims: options === null || options === void 0 ? void 0 : options.claims, + }; + try { + this.logger.info("Attempting to acquire token silently"); + /** + * The following code to retrieve all accounts is done as a workaround in an attempt to force the + * refresh of the token cache with the token and the account passed in through the + * `authenticationRecord` parameter. See issue - https://github.com/Azure/azure-sdk-for-js/issues/24349#issuecomment-1496715651 + * This workaround serves as a workaround for silent authentication not happening when authenticationRecord is passed. + */ + await ((_a = this.getApp("publicFirst", options === null || options === void 0 ? void 0 : options.enableCae)) === null || _a === void 0 ? void 0 : _a.getTokenCache().getAllAccounts()); + const response = (_c = (await ((_b = this.getApp("confidential", options === null || options === void 0 ? void 0 : options.enableCae)) === null || _b === void 0 ? void 0 : _b.acquireTokenSilent(silentRequest)))) !== null && _c !== void 0 ? _c : (await this.getApp("public", options === null || options === void 0 ? void 0 : options.enableCae).acquireTokenSilent(silentRequest)); + return this.handleResult(scopes, this.clientId, response || undefined); + } + catch (err) { + throw this.handleError(scopes, err, options); + } + } + /** + * Wrapper around each MSAL flow get token operation: doGetToken. + * If disableAutomaticAuthentication is sent through the constructor, it will prevent MSAL from requesting the user input. + */ + async getToken(scopes, options = {}) { + const tenantId = processMultiTenantRequest(this.tenantId, options, this.additionallyAllowedTenantIds) || + this.tenantId; + options.authority = getAuthority(tenantId, this.authorityHost); + options.correlationId = (options === null || options === void 0 ? void 0 : options.correlationId) || this.generateUuid(); + await this.init(options); + try { + // MSAL now caches tokens based on their claims, + // so now one has to keep track fo claims in order to retrieve the newer tokens from acquireTokenSilent + // This update happened on PR: https://github.com/AzureAD/microsoft-authentication-library-for-js/pull/4533 + const optionsClaims = options.claims; + if (optionsClaims) { + this.cachedClaims = optionsClaims; + } + if (this.cachedClaims && !optionsClaims) { + options.claims = this.cachedClaims; + } + // We don't return the promise since we want to catch errors right here. + return await this.getTokenSilent(scopes, options); + } + catch (err) { + if (err.name !== "AuthenticationRequiredError") { + throw err; + } + if (options === null || options === void 0 ? void 0 : options.disableAutomaticAuthentication) { + throw new AuthenticationRequiredError({ + scopes, + getTokenOptions: options, + message: "Automatic authentication has been disabled. You may call the authentication() method.", + }); + } + this.logger.info(`Silent authentication failed, falling back to interactive method.`); + return this.doGetToken(scopes, options); + } + } +} + +// Copyright (c) Microsoft Corporation. +const CommonTenantId = "common"; +const AzureAccountClientId = "aebc6443-996d-45c2-90f0-388ff96faa56"; // VSC: 'aebc6443-996d-45c2-90f0-388ff96faa56' +const logger$m = credentialLogger("VisualStudioCodeCredential"); +let findCredentials = undefined; +const vsCodeCredentialControl = { + setVsCodeCredentialFinder(finder) { + findCredentials = finder; + }, +}; +// Map of unsupported Tenant IDs and the errors we will be throwing. +const unsupportedTenantIds = { + adfs: "The VisualStudioCodeCredential does not support authentication with ADFS tenants.", +}; +function checkUnsupportedTenant(tenantId) { + // If the Tenant ID isn't supported, we throw. + const unsupportedTenantError = unsupportedTenantIds[tenantId]; + if (unsupportedTenantError) { + throw new CredentialUnavailableError(unsupportedTenantError); + } +} +const mapVSCodeAuthorityHosts = { + AzureCloud: exports.AzureAuthorityHosts.AzurePublicCloud, + AzureChina: exports.AzureAuthorityHosts.AzureChina, + AzureGermanCloud: exports.AzureAuthorityHosts.AzureGermany, + AzureUSGovernment: exports.AzureAuthorityHosts.AzureGovernment, +}; +/** + * Attempts to load a specific property from the VSCode configurations of the current OS. + * If it fails at any point, returns undefined. + */ +function getPropertyFromVSCode(property) { + const settingsPath = ["User", "settings.json"]; + // Eventually we can add more folders for more versions of VSCode. + const vsCodeFolder = "Code"; + const homedir = os__default["default"].homedir(); + function loadProperty(...pathSegments) { + const fullPath = path__default["default"].join(...pathSegments, vsCodeFolder, ...settingsPath); + const settings = JSON.parse(fs__default["default"].readFileSync(fullPath, { encoding: "utf8" })); + return settings[property]; + } + try { + let appData; + switch (process.platform) { + case "win32": + appData = process.env.APPDATA; + return appData ? loadProperty(appData) : undefined; + case "darwin": + return loadProperty(homedir, "Library", "Application Support"); + case "linux": + return loadProperty(homedir, ".config"); + default: + return; + } + } + catch (e) { + logger$m.info(`Failed to load the Visual Studio Code configuration file. Error: ${e.message}`); + return; + } +} +/** + * Connects to Azure using the credential provided by the VSCode extension 'Azure Account'. + * Once the user has logged in via the extension, this credential can share the same refresh token + * that is cached by the extension. + * + * It's a [known issue](https://github.com/Azure/azure-sdk-for-js/issues/20500) that this credential doesn't + * work with [Azure Account extension](https://marketplace.visualstudio.com/items?itemName=ms-vscode.azure-account) + * versions newer than **0.9.11**. A long-term fix to this problem is in progress. In the meantime, consider + * authenticating with {@link AzureCliCredential}. + */ +class VisualStudioCodeCredential { + /** + * Creates an instance of VisualStudioCodeCredential to use for automatically authenticating via VSCode. + * + * **Note**: `VisualStudioCodeCredential` is provided by a plugin package: + * `@azure/identity-vscode`. If this package is not installed and registered + * using the plugin API (`useIdentityPlugin`), then authentication using + * `VisualStudioCodeCredential` will not be available. + * + * @param options - Options for configuring the client which makes the authentication request. + */ + constructor(options) { + // We want to make sure we use the one assigned by the user on the VSCode settings. + // Or just `AzureCloud` by default. + this.cloudName = (getPropertyFromVSCode("azure.cloud") || "AzureCloud"); + // Picking an authority host based on the cloud name. + const authorityHost = mapVSCodeAuthorityHosts[this.cloudName]; + this.identityClient = new IdentityClient(Object.assign({ authorityHost }, options)); + if (options && options.tenantId) { + checkTenantId(logger$m, options.tenantId); + this.tenantId = options.tenantId; + } + else { + this.tenantId = CommonTenantId; + } + this.additionallyAllowedTenantIds = resolveAddionallyAllowedTenantIds(options === null || options === void 0 ? void 0 : options.additionallyAllowedTenants); + checkUnsupportedTenant(this.tenantId); + } + /** + * Runs preparations for any further getToken request. + */ + async prepare() { + // Attempts to load the tenant from the VSCode configuration file. + const settingsTenant = getPropertyFromVSCode("azure.tenant"); + if (settingsTenant) { + this.tenantId = settingsTenant; + } + checkUnsupportedTenant(this.tenantId); + } + /** + * Runs preparations for any further getToken, but only once. + */ + prepareOnce() { + if (!this.preparePromise) { + this.preparePromise = this.prepare(); + } + return this.preparePromise; + } + /** + * Returns the token found by searching VSCode's authentication cache or + * returns null if no token could be found. + * + * @param scopes - The list of scopes for which the token will have access. + * @param options - The options used to configure any requests this + * `TokenCredential` implementation might make. + */ + async getToken(scopes, options) { + var _a, _b; + await this.prepareOnce(); + const tenantId = processMultiTenantRequest(this.tenantId, options, this.additionallyAllowedTenantIds, logger$m) || this.tenantId; + if (findCredentials === undefined) { + throw new CredentialUnavailableError([ + "No implementation of `VisualStudioCodeCredential` is available.", + "You must install the identity-vscode plugin package (`npm install --save-dev @azure/identity-vscode`)", + "and enable it by importing `useIdentityPlugin` from `@azure/identity` and calling", + "`useIdentityPlugin(vsCodePlugin)` before creating a `VisualStudioCodeCredential`.", + "To troubleshoot, visit https://aka.ms/azsdk/js/identity/vscodecredential/troubleshoot.", + ].join(" ")); + } + let scopeString = typeof scopes === "string" ? scopes : scopes.join(" "); + // Check to make sure the scope we get back is a valid scope + if (!scopeString.match(/^[0-9a-zA-Z-.:/]+$/)) { + const error = new Error("Invalid scope was specified by the user or calling client"); + logger$m.getToken.info(formatError(scopes, error)); + throw error; + } + if (scopeString.indexOf("offline_access") < 0) { + scopeString += " offline_access"; + } + // findCredentials returns an array similar to: + // [ + // { + // account: "", + // password: "", + // }, + // /* ... */ + // ] + const credentials = await findCredentials(); + // If we can't find the credential based on the name, we'll pick the first one available. + const { password: refreshToken } = (_b = (_a = credentials.find(({ account }) => account === this.cloudName)) !== null && _a !== void 0 ? _a : credentials[0]) !== null && _b !== void 0 ? _b : {}; + if (refreshToken) { + const tokenResponse = await this.identityClient.refreshAccessToken(tenantId, AzureAccountClientId, scopeString, refreshToken, undefined); + if (tokenResponse) { + logger$m.getToken.info(formatSuccess(scopes)); + return tokenResponse.accessToken; + } + else { + const error = new CredentialUnavailableError("Could not retrieve the token associated with Visual Studio Code. Have you connected using the 'Azure Account' extension recently? To troubleshoot, visit https://aka.ms/azsdk/js/identity/vscodecredential/troubleshoot."); + logger$m.getToken.info(formatError(scopes, error)); + throw error; + } + } + else { + const error = new CredentialUnavailableError("Could not retrieve the token associated with Visual Studio Code. Did you connect using the 'Azure Account' extension? To troubleshoot, visit https://aka.ms/azsdk/js/identity/vscodecredential/troubleshoot."); + logger$m.getToken.info(formatError(scopes, error)); + throw error; + } + } +} + +// Copyright (c) Microsoft Corporation. +/** + * The context passed to an Identity plugin. This contains objects that + * plugins can use to set backend implementations. + * @internal + */ +const pluginContext = { + cachePluginControl: msalNodeFlowCacheControl, + vsCodeCredentialControl: vsCodeCredentialControl, +}; +/** + * Extend Azure Identity with additional functionality. Pass a plugin from + * a plugin package, such as: + * + * - `@azure/identity-cache-persistence`: provides persistent token caching + * - `@azure/identity-vscode`: provides the dependencies of + * `VisualStudioCodeCredential` and enables it + * + * Example: + * + * ```javascript + * import { cachePersistencePlugin } from "@azure/identity-cache-persistence"; + * + * import { useIdentityPlugin, DefaultAzureCredential } from "@azure/identity"; + * useIdentityPlugin(cachePersistencePlugin); + * + * // The plugin has the capability to extend `DefaultAzureCredential` and to + * // add middleware to the underlying credentials, such as persistence. + * const credential = new DefaultAzureCredential({ + * tokenCachePersistenceOptions: { + * enabled: true + * } + * }); + * ``` + * + * @param plugin - the plugin to register + */ +function useIdentityPlugin(plugin) { + plugin(pluginContext); +} + +// Copyright (c) Microsoft Corporation. +const msiName$6 = "ManagedIdentityCredential - AppServiceMSI 2017"; +const logger$l = credentialLogger(msiName$6); +/** + * Generates the options used on the request for an access token. + */ +function prepareRequestOptions$5(scopes, clientId) { + const resource = mapScopesToResource(scopes); + if (!resource) { + throw new Error(`${msiName$6}: Multiple scopes are not supported.`); + } + const queryParameters = { + resource, + "api-version": "2017-09-01", + }; + if (clientId) { + queryParameters.clientid = clientId; + } + const query = new URLSearchParams(queryParameters); + // This error should not bubble up, since we verify that this environment variable is defined in the isAvailable() method defined below. + if (!process.env.MSI_ENDPOINT) { + throw new Error(`${msiName$6}: Missing environment variable: MSI_ENDPOINT`); + } + if (!process.env.MSI_SECRET) { + throw new Error(`${msiName$6}: Missing environment variable: MSI_SECRET`); + } + return { + url: `${process.env.MSI_ENDPOINT}?${query.toString()}`, + method: "GET", + headers: coreRestPipeline.createHttpHeaders({ + Accept: "application/json", + secret: process.env.MSI_SECRET, + }), + }; +} +/** + * Defines how to determine whether the Azure App Service MSI is available, and also how to retrieve a token from the Azure App Service MSI. + */ +const appServiceMsi2017 = { + name: "appServiceMsi2017", + async isAvailable({ scopes }) { + const resource = mapScopesToResource(scopes); + if (!resource) { + logger$l.info(`${msiName$6}: Unavailable. Multiple scopes are not supported.`); + return false; + } + const env = process.env; + const result = Boolean(env.MSI_ENDPOINT && env.MSI_SECRET); + if (!result) { + logger$l.info(`${msiName$6}: Unavailable. The environment variables needed are: MSI_ENDPOINT and MSI_SECRET.`); + } + return result; + }, + async getToken(configuration, getTokenOptions = {}) { + const { identityClient, scopes, clientId, resourceId } = configuration; + if (resourceId) { + logger$l.warning(`${msiName$6}: managed Identity by resource Id is not supported. Argument resourceId might be ignored by the service.`); + } + logger$l.info(`${msiName$6}: Using the endpoint and the secret coming form the environment variables: MSI_ENDPOINT=${process.env.MSI_ENDPOINT} and MSI_SECRET=[REDACTED].`); + const request = coreRestPipeline.createPipelineRequest(Object.assign(Object.assign({ abortSignal: getTokenOptions.abortSignal }, prepareRequestOptions$5(scopes, clientId)), { + // Generally, MSI endpoints use the HTTP protocol, without transport layer security (TLS). + allowInsecureConnection: true })); + const tokenResponse = await identityClient.sendTokenRequest(request); + return (tokenResponse && tokenResponse.accessToken) || null; + }, +}; + +// Copyright (c) Microsoft Corporation. +const msiName$5 = "ManagedIdentityCredential - CloudShellMSI"; +const logger$k = credentialLogger(msiName$5); +/** + * Generates the options used on the request for an access token. + */ +function prepareRequestOptions$4(scopes, clientId, resourceId) { + const resource = mapScopesToResource(scopes); + if (!resource) { + throw new Error(`${msiName$5}: Multiple scopes are not supported.`); + } + const body = { + resource, + }; + if (clientId) { + body.client_id = clientId; + } + if (resourceId) { + body.msi_res_id = resourceId; + } + // This error should not bubble up, since we verify that this environment variable is defined in the isAvailable() method defined below. + if (!process.env.MSI_ENDPOINT) { + throw new Error(`${msiName$5}: Missing environment variable: MSI_ENDPOINT`); + } + const params = new URLSearchParams(body); + return { + url: process.env.MSI_ENDPOINT, + method: "POST", + body: params.toString(), + headers: coreRestPipeline.createHttpHeaders({ + Accept: "application/json", + Metadata: "true", + "Content-Type": "application/x-www-form-urlencoded", + }), + }; +} +/** + * Defines how to determine whether the Azure Cloud Shell MSI is available, and also how to retrieve a token from the Azure Cloud Shell MSI. + * Since Azure Managed Identities aren't available in the Azure Cloud Shell, we log a warning for users that try to access cloud shell using user assigned identity. + */ +const cloudShellMsi = { + name: "cloudShellMsi", + async isAvailable({ scopes }) { + const resource = mapScopesToResource(scopes); + if (!resource) { + logger$k.info(`${msiName$5}: Unavailable. Multiple scopes are not supported.`); + return false; + } + const result = Boolean(process.env.MSI_ENDPOINT); + if (!result) { + logger$k.info(`${msiName$5}: Unavailable. The environment variable MSI_ENDPOINT is needed.`); + } + return result; + }, + async getToken(configuration, getTokenOptions = {}) { + const { identityClient, scopes, clientId, resourceId } = configuration; + if (clientId) { + logger$k.warning(`${msiName$5}: user-assigned identities not supported. The argument clientId might be ignored by the service.`); + } + if (resourceId) { + logger$k.warning(`${msiName$5}: user defined managed Identity by resource Id not supported. The argument resourceId might be ignored by the service.`); + } + logger$k.info(`${msiName$5}: Using the endpoint coming form the environment variable MSI_ENDPOINT = ${process.env.MSI_ENDPOINT}.`); + const request = coreRestPipeline.createPipelineRequest(Object.assign(Object.assign({ abortSignal: getTokenOptions.abortSignal }, prepareRequestOptions$4(scopes, clientId, resourceId)), { + // Generally, MSI endpoints use the HTTP protocol, without transport layer security (TLS). + allowInsecureConnection: true })); + const tokenResponse = await identityClient.sendTokenRequest(request); + return (tokenResponse && tokenResponse.accessToken) || null; + }, +}; + +// Copyright (c) Microsoft Corporation. +const msiName$4 = "ManagedIdentityCredential - IMDS"; +const logger$j = credentialLogger(msiName$4); +/** + * Generates the options used on the request for an access token. + */ +function prepareRequestOptions$3(scopes, clientId, resourceId, options) { + var _a; + const resource = mapScopesToResource(scopes); + if (!resource) { + throw new Error(`${msiName$4}: Multiple scopes are not supported.`); + } + const { skipQuery, skipMetadataHeader } = options || {}; + let query = ""; + // Pod Identity will try to process this request even if the Metadata header is missing. + // We can exclude the request query to ensure no IMDS endpoint tries to process the ping request. + if (!skipQuery) { + const queryParameters = { + resource, + "api-version": imdsApiVersion, + }; + if (clientId) { + queryParameters.client_id = clientId; + } + if (resourceId) { + queryParameters.msi_res_id = resourceId; + } + const params = new URLSearchParams(queryParameters); + query = `?${params.toString()}`; + } + const url = new URL(imdsEndpointPath, (_a = process.env.AZURE_POD_IDENTITY_AUTHORITY_HOST) !== null && _a !== void 0 ? _a : imdsHost); + const rawHeaders = { + Accept: "application/json", + Metadata: "true", + }; + // Remove the Metadata header to invoke a request error from some IMDS endpoints. + if (skipMetadataHeader) { + delete rawHeaders.Metadata; + } + return { + // In this case, the `?` should be added in the "query" variable `skipQuery` is not set. + url: `${url}${query}`, + method: "GET", + headers: coreRestPipeline.createHttpHeaders(rawHeaders), + }; +} +// 800ms -> 1600ms -> 3200ms +const imdsMsiRetryConfig = { + maxRetries: 3, + startDelayInMs: 800, + intervalIncrement: 2, +}; +/** + * Defines how to determine whether the Azure IMDS MSI is available, and also how to retrieve a token from the Azure IMDS MSI. + */ +const imdsMsi = { + name: "imdsMsi", + async isAvailable({ scopes, identityClient, clientId, resourceId, getTokenOptions = {}, }) { + const resource = mapScopesToResource(scopes); + if (!resource) { + logger$j.info(`${msiName$4}: Unavailable. Multiple scopes are not supported.`); + return false; + } + // if the PodIdentityEndpoint environment variable was set no need to probe the endpoint, it can be assumed to exist + if (process.env.AZURE_POD_IDENTITY_AUTHORITY_HOST) { + return true; + } + if (!identityClient) { + throw new Error("Missing IdentityClient"); + } + const requestOptions = prepareRequestOptions$3(resource, clientId, resourceId, { + skipMetadataHeader: true, + skipQuery: true, + }); + return tracingClient.withSpan("ManagedIdentityCredential-pingImdsEndpoint", getTokenOptions, async (options) => { + var _a; + requestOptions.tracingOptions = options.tracingOptions; + // Create a request with a timeout since we expect that + // not having a "Metadata" header should cause an error to be + // returned quickly from the endpoint, proving its availability. + const request = coreRestPipeline.createPipelineRequest(requestOptions); + // Default to 300 if the default of 0 is used. + // Negative values can still be used to disable the timeout. + request.timeout = ((_a = options.requestOptions) === null || _a === void 0 ? void 0 : _a.timeout) || 300; + // This MSI uses the imdsEndpoint to get the token, which only uses http:// + request.allowInsecureConnection = true; + try { + logger$j.info(`${msiName$4}: Pinging the Azure IMDS endpoint`); + await identityClient.sendRequest(request); + } + catch (err) { + // If the request failed, or Node.js was unable to establish a connection, + // or the host was down, we'll assume the IMDS endpoint isn't available. + if (coreUtil.isError(err)) { + logger$j.verbose(`${msiName$4}: Caught error ${err.name}: ${err.message}`); + } + logger$j.info(`${msiName$4}: The Azure IMDS endpoint is unavailable`); + return false; + } + // If we received any response, the endpoint is available + logger$j.info(`${msiName$4}: The Azure IMDS endpoint is available`); + return true; + }); + }, + async getToken(configuration, getTokenOptions = {}) { + const { identityClient, scopes, clientId, resourceId } = configuration; + if (process.env.AZURE_POD_IDENTITY_AUTHORITY_HOST) { + logger$j.info(`${msiName$4}: Using the Azure IMDS endpoint coming from the environment variable AZURE_POD_IDENTITY_AUTHORITY_HOST=${process.env.AZURE_POD_IDENTITY_AUTHORITY_HOST}.`); + } + else { + logger$j.info(`${msiName$4}: Using the default Azure IMDS endpoint ${imdsHost}.`); + } + let nextDelayInMs = imdsMsiRetryConfig.startDelayInMs; + for (let retries = 0; retries < imdsMsiRetryConfig.maxRetries; retries++) { + try { + const request = coreRestPipeline.createPipelineRequest(Object.assign(Object.assign({ abortSignal: getTokenOptions.abortSignal }, prepareRequestOptions$3(scopes, clientId, resourceId)), { allowInsecureConnection: true })); + const tokenResponse = await identityClient.sendTokenRequest(request); + return (tokenResponse && tokenResponse.accessToken) || null; + } + catch (error) { + if (error.statusCode === 404) { + await coreUtil.delay(nextDelayInMs); + nextDelayInMs *= imdsMsiRetryConfig.intervalIncrement; + continue; + } + throw error; + } + } + throw new AuthenticationError(404, `${msiName$4}: Failed to retrieve IMDS token after ${imdsMsiRetryConfig.maxRetries} retries.`); + }, +}; + +// Copyright (c) Microsoft Corporation. +const msiName$3 = "ManagedIdentityCredential - Azure Arc MSI"; +const logger$i = credentialLogger(msiName$3); +/** + * Generates the options used on the request for an access token. + */ +function prepareRequestOptions$2(scopes, clientId, resourceId) { + const resource = mapScopesToResource(scopes); + if (!resource) { + throw new Error(`${msiName$3}: Multiple scopes are not supported.`); + } + const queryParameters = { + resource, + "api-version": azureArcAPIVersion, + }; + if (clientId) { + queryParameters.client_id = clientId; + } + if (resourceId) { + queryParameters.msi_res_id = resourceId; + } + // This error should not bubble up, since we verify that this environment variable is defined in the isAvailable() method defined below. + if (!process.env.IDENTITY_ENDPOINT) { + throw new Error(`${msiName$3}: Missing environment variable: IDENTITY_ENDPOINT`); + } + const query = new URLSearchParams(queryParameters); + return coreRestPipeline.createPipelineRequest({ + // Should be similar to: http://localhost:40342/metadata/identity/oauth2/token + url: `${process.env.IDENTITY_ENDPOINT}?${query.toString()}`, + method: "GET", + headers: coreRestPipeline.createHttpHeaders({ + Accept: "application/json", + Metadata: "true", + }), + }); +} +/** + * Retrieves the file contents at the given path using promises. + * Useful since `fs`'s readFileSync locks the thread, and to avoid extra dependencies. + */ +function readFileAsync$1(path, options) { + return new Promise((resolve, reject) => fs.readFile(path, options, (err, data) => { + if (err) { + reject(err); + } + resolve(data); + })); +} +/** + * Does a request to the authentication provider that results in a file path. + */ +async function filePathRequest(identityClient, requestPrepareOptions) { + const response = await identityClient.sendRequest(coreRestPipeline.createPipelineRequest(requestPrepareOptions)); + if (response.status !== 401) { + let message = ""; + if (response.bodyAsText) { + message = ` Response: ${response.bodyAsText}`; + } + throw new AuthenticationError(response.status, `${msiName$3}: To authenticate with Azure Arc MSI, status code 401 is expected on the first request. ${message}`); + } + const authHeader = response.headers.get("www-authenticate") || ""; + try { + return authHeader.split("=").slice(1)[0]; + } + catch (e) { + throw Error(`Invalid www-authenticate header format: ${authHeader}`); + } +} +/** + * Defines how to determine whether the Azure Arc MSI is available, and also how to retrieve a token from the Azure Arc MSI. + */ +const arcMsi = { + name: "arc", + async isAvailable({ scopes }) { + const resource = mapScopesToResource(scopes); + if (!resource) { + logger$i.info(`${msiName$3}: Unavailable. Multiple scopes are not supported.`); + return false; + } + const result = Boolean(process.env.IMDS_ENDPOINT && process.env.IDENTITY_ENDPOINT); + if (!result) { + logger$i.info(`${msiName$3}: The environment variables needed are: IMDS_ENDPOINT and IDENTITY_ENDPOINT`); + } + return result; + }, + async getToken(configuration, getTokenOptions = {}) { + var _a; + const { identityClient, scopes, clientId, resourceId } = configuration; + if (clientId) { + logger$i.warning(`${msiName$3}: user-assigned identities not supported. The argument clientId might be ignored by the service.`); + } + if (resourceId) { + logger$i.warning(`${msiName$3}: user defined managed Identity by resource Id is not supported. Argument resourceId will be ignored.`); + } + logger$i.info(`${msiName$3}: Authenticating.`); + const requestOptions = Object.assign(Object.assign({ disableJsonStringifyOnBody: true, deserializationMapper: undefined, abortSignal: getTokenOptions.abortSignal }, prepareRequestOptions$2(scopes, clientId, resourceId)), { allowInsecureConnection: true }); + const filePath = await filePathRequest(identityClient, requestOptions); + if (!filePath) { + throw new Error(`${msiName$3}: Failed to find the token file.`); + } + const key = await readFileAsync$1(filePath, { encoding: "utf-8" }); + (_a = requestOptions.headers) === null || _a === void 0 ? void 0 : _a.set("Authorization", `Basic ${key}`); + const request = coreRestPipeline.createPipelineRequest(Object.assign(Object.assign({}, requestOptions), { + // Generally, MSI endpoints use the HTTP protocol, without transport layer security (TLS). + allowInsecureConnection: true })); + const tokenResponse = await identityClient.sendTokenRequest(request); + return (tokenResponse && tokenResponse.accessToken) || null; + }, +}; + +// Copyright (c) Microsoft Corporation. +/** + * MSAL client assertion client. Calls to MSAL's confidential application's `acquireTokenByClientCredential` during `doGetToken`. + * @internal + */ +class MsalClientAssertion extends MsalNode { + constructor(options) { + super(options); + this.requiresConfidential = true; + this.getAssertion = options.getAssertion; + } + async doGetToken(scopes, options = {}) { + try { + const assertion = await this.getAssertion(); + const result = await this.getApp("confidential", options.enableCae).acquireTokenByClientCredential({ + scopes, + correlationId: options.correlationId, + azureRegion: this.azureRegion, + authority: options.authority, + claims: options.claims, + clientAssertion: assertion, + }); + // The Client Credential flow does not return an account, + // so each time getToken gets called, we will have to acquire a new token through the service. + return this.handleResult(scopes, this.clientId, result || undefined); + } + catch (err) { + let err2 = err; + if (err === null || err === undefined) { + err2 = new Error(JSON.stringify(err)); + } + else { + err2 = coreUtil.isError(err) ? err : new Error(String(err)); + } + throw this.handleError(scopes, err2, options); + } + } +} + +// Copyright (c) Microsoft Corporation. +const logger$h = credentialLogger("ClientAssertionCredential"); +/** + * Authenticates a service principal with a JWT assertion. + */ +class ClientAssertionCredential { + /** + * Creates an instance of the ClientAssertionCredential with the details + * needed to authenticate against Azure Active Directory with a client + * assertion provided by the developer through the `getAssertion` function parameter. + * + * @param tenantId - The Azure Active Directory tenant (directory) ID. + * @param clientId - The client (application) ID of an App Registration in the tenant. + * @param getAssertion - A function that retrieves the assertion for the credential to use. + * @param options - Options for configuring the client which makes the authentication request. + */ + constructor(tenantId, clientId, getAssertion, options = {}) { + if (!tenantId || !clientId || !getAssertion) { + throw new Error("ClientAssertionCredential: tenantId, clientId, and clientAssertion are required parameters."); + } + this.tenantId = tenantId; + this.additionallyAllowedTenantIds = resolveAddionallyAllowedTenantIds(options === null || options === void 0 ? void 0 : options.additionallyAllowedTenants); + this.clientId = clientId; + this.options = options; + this.msalFlow = new MsalClientAssertion(Object.assign(Object.assign({}, options), { logger: logger$h, clientId: this.clientId, tenantId: this.tenantId, tokenCredentialOptions: this.options, getAssertion })); + } + /** + * Authenticates with Azure Active Directory and returns an access token if successful. + * If authentication fails, a {@link CredentialUnavailableError} will be thrown with the details of the failure. + * + * @param scopes - The list of scopes for which the token will have access. + * @param options - The options used to configure any requests this + * TokenCredential implementation might make. + */ + async getToken(scopes, options = {}) { + return tracingClient.withSpan(`${this.constructor.name}.getToken`, options, async (newOptions) => { + newOptions.tenantId = processMultiTenantRequest(this.tenantId, newOptions, this.additionallyAllowedTenantIds, logger$h); + const arrayScopes = Array.isArray(scopes) ? scopes : [scopes]; + return this.msalFlow.getToken(arrayScopes, newOptions); + }); + } +} + +// Copyright (c) Microsoft Corporation. +const credentialName$3 = "WorkloadIdentityCredential"; +/** + * Contains the list of all supported environment variable names so that an + * appropriate error message can be generated when no credentials can be + * configured. + * + * @internal + */ +const SupportedWorkloadEnvironmentVariables = [ + "AZURE_TENANT_ID", + "AZURE_CLIENT_ID", + "AZURE_FEDERATED_TOKEN_FILE", +]; +const logger$g = credentialLogger(credentialName$3); +/** + * Workload Identity authentication is a feature in Azure that allows applications running on virtual machines (VMs) + * to access other Azure resources without the need for a service principal or managed identity. With Workload Identity + * authentication, applications authenticate themselves using their own identity, rather than using a shared service + * principal or managed identity. Under the hood, Workload Identity authentication uses the concept of Service Account + * Credentials (SACs), which are automatically created by Azure and stored securely in the VM. By using Workload + * Identity authentication, you can avoid the need to manage and rotate service principals or managed identities for + * each application on each VM. Additionally, because SACs are created automatically and managed by Azure, you don't + * need to worry about storing and securing sensitive credentials themselves. + * The WorkloadIdentityCredential supports Azure workload identity authentication on Azure Kubernetes and acquires + * a token using the SACs available in the Azure Kubernetes environment. + * Refer to Azure Active Directory + * Workload Identity for more information. + */ +class WorkloadIdentityCredential { + /** + * WorkloadIdentityCredential supports Azure workload identity on Kubernetes. + * + * @param options - The identity client options to use for authentication. + */ + constructor(options) { + this.azureFederatedTokenFileContent = undefined; + this.cacheDate = undefined; + // Logging environment variables for error details + const assignedEnv = processEnvVars(SupportedWorkloadEnvironmentVariables).assigned.join(", "); + logger$g.info(`Found the following environment variables: ${assignedEnv}`); + const workloadIdentityCredentialOptions = options !== null && options !== void 0 ? options : {}; + const tenantId = workloadIdentityCredentialOptions.tenantId || process.env.AZURE_TENANT_ID; + const clientId = workloadIdentityCredentialOptions.clientId || process.env.AZURE_CLIENT_ID; + this.federatedTokenFilePath = + workloadIdentityCredentialOptions.tokenFilePath || process.env.AZURE_FEDERATED_TOKEN_FILE; + if (tenantId) { + checkTenantId(logger$g, tenantId); + } + if (clientId && tenantId && this.federatedTokenFilePath) { + logger$g.info(`Invoking ClientAssertionCredential with tenant ID: ${tenantId}, clientId: ${workloadIdentityCredentialOptions.clientId} and federated token path: [REDACTED]`); + this.client = new ClientAssertionCredential(tenantId, clientId, this.readFileContents.bind(this), options); + } + } + /** + * Authenticates with Azure Active Directory and returns an access token if successful. + * If authentication fails, a {@link CredentialUnavailableError} will be thrown with the details of the failure. + * + * @param scopes - The list of scopes for which the token will have access. + * @param options - The options used to configure any requests this + * TokenCredential implementation might make. + */ + async getToken(scopes, options) { + if (!this.client) { + const errorMessage = `${credentialName$3}: is unavailable. tenantId, clientId, and federatedTokenFilePath are required parameters. + In DefaultAzureCredential and ManagedIdentityCredential, these can be provided as environment variables - + "AZURE_TENANT_ID", + "AZURE_CLIENT_ID", + "AZURE_FEDERATED_TOKEN_FILE". See the troubleshooting guide for more information: https://aka.ms/azsdk/js/identity/workloadidentitycredential/troubleshoot `; + logger$g.info(errorMessage); + throw new CredentialUnavailableError(errorMessage); + } + logger$g.info("Invoking getToken() of Client Assertion Credential"); + return this.client.getToken(scopes, options); + } + async readFileContents() { + // Cached assertions expire after 5 minutes + if (this.cacheDate !== undefined && Date.now() - this.cacheDate >= 1000 * 60 * 5) { + this.azureFederatedTokenFileContent = undefined; + } + if (!this.federatedTokenFilePath) { + throw new CredentialUnavailableError(`${credentialName$3}: is unavailable. Invalid file path provided ${this.federatedTokenFilePath}.`); + } + if (!this.azureFederatedTokenFileContent) { + const file = await promises.readFile(this.federatedTokenFilePath, "utf8"); + const value = file.trim(); + if (!value) { + throw new CredentialUnavailableError(`${credentialName$3}: is unavailable. No content on the file ${this.federatedTokenFilePath}.`); + } + else { + this.azureFederatedTokenFileContent = value; + this.cacheDate = Date.now(); + } + } + return this.azureFederatedTokenFileContent; + } +} + +// Copyright (c) Microsoft Corporation. +const msiName$2 = "ManagedIdentityCredential - Token Exchange"; +const logger$f = credentialLogger(msiName$2); +/** + * Defines how to determine whether the token exchange MSI is available, and also how to retrieve a token from the token exchange MSI. + */ +function tokenExchangeMsi() { + return { + name: "tokenExchangeMsi", + async isAvailable({ clientId }) { + const env = process.env; + const result = Boolean((clientId || env.AZURE_CLIENT_ID) && + env.AZURE_TENANT_ID && + process.env.AZURE_FEDERATED_TOKEN_FILE); + if (!result) { + logger$f.info(`${msiName$2}: Unavailable. The environment variables needed are: AZURE_CLIENT_ID (or the client ID sent through the parameters), AZURE_TENANT_ID and AZURE_FEDERATED_TOKEN_FILE`); + } + return result; + }, + async getToken(configuration, getTokenOptions = {}) { + const { scopes, clientId } = configuration; + const identityClientTokenCredentialOptions = {}; + const workloadIdentityCredential = new WorkloadIdentityCredential(Object.assign(Object.assign({ clientId, tenantId: process.env.AZURE_TENANT_ID, tokenFilePath: process.env.AZURE_FEDERATED_TOKEN_FILE }, identityClientTokenCredentialOptions), { disableInstanceDiscovery: true })); + const token = await workloadIdentityCredential.getToken(scopes, getTokenOptions); + return token; + }, + }; +} + +// Copyright (c) Microsoft Corporation. +// This MSI can be easily tested by deploying a container to Azure Service Fabric with the Dockerfile: +// +// FROM node:12 +// RUN wget https://host.any/path/bash.sh +// CMD ["bash", "bash.sh"] +// +// Where the bash script contains: +// +// curl --insecure $IDENTITY_ENDPOINT'?api-version=2019-07-01-preview&resource=https://vault.azure.net/' -H "Secret: $IDENTITY_HEADER" +// +const msiName$1 = "ManagedIdentityCredential - Fabric MSI"; +const logger$e = credentialLogger(msiName$1); +/** + * Generates the options used on the request for an access token. + */ +function prepareRequestOptions$1(scopes, clientId, resourceId) { + const resource = mapScopesToResource(scopes); + if (!resource) { + throw new Error(`${msiName$1}: Multiple scopes are not supported.`); + } + const queryParameters = { + resource, + "api-version": azureFabricVersion, + }; + if (clientId) { + queryParameters.client_id = clientId; + } + if (resourceId) { + queryParameters.msi_res_id = resourceId; + } + const query = new URLSearchParams(queryParameters); + // This error should not bubble up, since we verify that this environment variable is defined in the isAvailable() method defined below. + if (!process.env.IDENTITY_ENDPOINT) { + throw new Error("Missing environment variable: IDENTITY_ENDPOINT"); + } + if (!process.env.IDENTITY_HEADER) { + throw new Error("Missing environment variable: IDENTITY_HEADER"); + } + return { + url: `${process.env.IDENTITY_ENDPOINT}?${query.toString()}`, + method: "GET", + headers: coreRestPipeline.createHttpHeaders({ + Accept: "application/json", + secret: process.env.IDENTITY_HEADER, + }), + }; +} +/** + * Defines how to determine whether the Azure Service Fabric MSI is available, and also how to retrieve a token from the Azure Service Fabric MSI. + */ +const fabricMsi = { + name: "fabricMsi", + async isAvailable({ scopes }) { + const resource = mapScopesToResource(scopes); + if (!resource) { + logger$e.info(`${msiName$1}: Unavailable. Multiple scopes are not supported.`); + return false; + } + const env = process.env; + const result = Boolean(env.IDENTITY_ENDPOINT && env.IDENTITY_HEADER && env.IDENTITY_SERVER_THUMBPRINT); + if (!result) { + logger$e.info(`${msiName$1}: Unavailable. The environment variables needed are: IDENTITY_ENDPOINT, IDENTITY_HEADER and IDENTITY_SERVER_THUMBPRINT`); + } + return result; + }, + async getToken(configuration, getTokenOptions = {}) { + const { scopes, identityClient, clientId, resourceId } = configuration; + if (resourceId) { + logger$e.warning(`${msiName$1}: user defined managed Identity by resource Id is not supported. Argument resourceId might be ignored by the service.`); + } + logger$e.info([ + `${msiName$1}:`, + "Using the endpoint and the secret coming from the environment variables:", + `IDENTITY_ENDPOINT=${process.env.IDENTITY_ENDPOINT},`, + "IDENTITY_HEADER=[REDACTED] and", + "IDENTITY_SERVER_THUMBPRINT=[REDACTED].", + ].join(" ")); + const request = coreRestPipeline.createPipelineRequest(Object.assign({ abortSignal: getTokenOptions.abortSignal }, prepareRequestOptions$1(scopes, clientId, resourceId))); + request.agent = new https__default["default"].Agent({ + // This is necessary because Service Fabric provides a self-signed certificate. + // The alternative path is to verify the certificate using the IDENTITY_SERVER_THUMBPRINT env variable. + rejectUnauthorized: false, + }); + const tokenResponse = await identityClient.sendTokenRequest(request); + return (tokenResponse && tokenResponse.accessToken) || null; + }, +}; + +// Copyright (c) Microsoft Corporation. +const msiName = "ManagedIdentityCredential - AppServiceMSI 2019"; +const logger$d = credentialLogger(msiName); +/** + * Generates the options used on the request for an access token. + */ +function prepareRequestOptions(scopes, clientId, resourceId) { + const resource = mapScopesToResource(scopes); + if (!resource) { + throw new Error(`${msiName}: Multiple scopes are not supported.`); + } + const queryParameters = { + resource, + "api-version": "2019-08-01", + }; + if (clientId) { + queryParameters.client_id = clientId; + } + if (resourceId) { + queryParameters.mi_res_id = resourceId; + } + const query = new URLSearchParams(queryParameters); + // This error should not bubble up, since we verify that this environment variable is defined in the isAvailable() method defined below. + if (!process.env.IDENTITY_ENDPOINT) { + throw new Error(`${msiName}: Missing environment variable: IDENTITY_ENDPOINT`); + } + if (!process.env.IDENTITY_HEADER) { + throw new Error(`${msiName}: Missing environment variable: IDENTITY_HEADER`); + } + return { + url: `${process.env.IDENTITY_ENDPOINT}?${query.toString()}`, + method: "GET", + headers: coreRestPipeline.createHttpHeaders({ + Accept: "application/json", + "X-IDENTITY-HEADER": process.env.IDENTITY_HEADER, + }), + }; +} +/** + * Defines how to determine whether the Azure App Service MSI is available, and also how to retrieve a token from the Azure App Service MSI. + */ +const appServiceMsi2019 = { + name: "appServiceMsi2019", + async isAvailable({ scopes }) { + const resource = mapScopesToResource(scopes); + if (!resource) { + logger$d.info(`${msiName}: Unavailable. Multiple scopes are not supported.`); + return false; + } + const env = process.env; + const result = Boolean(env.IDENTITY_ENDPOINT && env.IDENTITY_HEADER); + if (!result) { + logger$d.info(`${msiName}: Unavailable. The environment variables needed are: IDENTITY_ENDPOINT and IDENTITY_HEADER.`); + } + return result; + }, + async getToken(configuration, getTokenOptions = {}) { + const { identityClient, scopes, clientId, resourceId } = configuration; + logger$d.info(`${msiName}: Using the endpoint and the secret coming form the environment variables: IDENTITY_ENDPOINT=${process.env.IDENTITY_ENDPOINT} and IDENTITY_HEADER=[REDACTED].`); + const request = coreRestPipeline.createPipelineRequest(Object.assign(Object.assign({ abortSignal: getTokenOptions.abortSignal }, prepareRequestOptions(scopes, clientId, resourceId)), { + // Generally, MSI endpoints use the HTTP protocol, without transport layer security (TLS). + allowInsecureConnection: true })); + const tokenResponse = await identityClient.sendTokenRequest(request); + return (tokenResponse && tokenResponse.accessToken) || null; + }, +}; + +// Copyright (c) Microsoft Corporation. +const logger$c = credentialLogger("ManagedIdentityCredential"); +/** + * Attempts authentication using a managed identity available at the deployment environment. + * This authentication type works in Azure VMs, App Service instances, Azure Functions applications, + * Azure Kubernetes Services, Azure Service Fabric instances and inside of the Azure Cloud Shell. + * + * More information about configuring managed identities can be found here: + * https://docs.microsoft.com/en-us/azure/active-directory/managed-identities-azure-resources/overview + */ +class ManagedIdentityCredential { + /** + * @internal + * @hidden + */ + constructor(clientIdOrOptions, options) { + var _a; + this.isEndpointUnavailable = null; + this.isAppTokenProviderInitialized = false; + let _options; + if (typeof clientIdOrOptions === "string") { + this.clientId = clientIdOrOptions; + _options = options; + } + else { + this.clientId = clientIdOrOptions === null || clientIdOrOptions === void 0 ? void 0 : clientIdOrOptions.clientId; + _options = clientIdOrOptions; + } + this.resourceId = _options === null || _options === void 0 ? void 0 : _options.resourceId; + // For JavaScript users. + if (this.clientId && this.resourceId) { + throw new Error(`${ManagedIdentityCredential.name} - Client Id and Resource Id can't be provided at the same time.`); + } + this.identityClient = new IdentityClient(_options); + this.isAvailableIdentityClient = new IdentityClient(Object.assign(Object.assign({}, _options), { retryOptions: { + maxRetries: 0, + } })); + /** authority host validation and metadata discovery to be skipped in managed identity + * since this wasn't done previously before adding token cache support + */ + this.confidentialApp = new msalNode.ConfidentialClientApplication({ + auth: { + clientId: (_a = this.clientId) !== null && _a !== void 0 ? _a : DeveloperSignOnClientId, + clientSecret: "dummy-secret", + cloudDiscoveryMetadata: '{"tenant_discovery_endpoint":"https://login.microsoftonline.com/common/v2.0/.well-known/openid-configuration","api-version":"1.1","metadata":[{"preferred_network":"login.microsoftonline.com","preferred_cache":"login.windows.net","aliases":["login.microsoftonline.com","login.windows.net","login.microsoft.com","sts.windows.net"]},{"preferred_network":"login.partner.microsoftonline.cn","preferred_cache":"login.partner.microsoftonline.cn","aliases":["login.partner.microsoftonline.cn","login.chinacloudapi.cn"]},{"preferred_network":"login.microsoftonline.de","preferred_cache":"login.microsoftonline.de","aliases":["login.microsoftonline.de"]},{"preferred_network":"login.microsoftonline.us","preferred_cache":"login.microsoftonline.us","aliases":["login.microsoftonline.us","login.usgovcloudapi.net"]},{"preferred_network":"login-us.microsoftonline.com","preferred_cache":"login-us.microsoftonline.com","aliases":["login-us.microsoftonline.com"]}]}', + authorityMetadata: '{"token_endpoint":"https://login.microsoftonline.com/common/oauth2/v2.0/token","token_endpoint_auth_methods_supported":["client_secret_post","private_key_jwt","client_secret_basic"],"jwks_uri":"https://login.microsoftonline.com/common/discovery/v2.0/keys","response_modes_supported":["query","fragment","form_post"],"subject_types_supported":["pairwise"],"id_token_signing_alg_values_supported":["RS256"],"response_types_supported":["code","id_token","code id_token","id_token token"],"scopes_supported":["openid","profile","email","offline_access"],"issuer":"https://login.microsoftonline.com/{tenantid}/v2.0","request_uri_parameter_supported":false,"userinfo_endpoint":"https://graph.microsoft.com/oidc/userinfo","authorization_endpoint":"https://login.microsoftonline.com/common/oauth2/v2.0/authorize","device_authorization_endpoint":"https://login.microsoftonline.com/common/oauth2/v2.0/devicecode","http_logout_supported":true,"frontchannel_logout_supported":true,"end_session_endpoint":"https://login.microsoftonline.com/common/oauth2/v2.0/logout","claims_supported":["sub","iss","cloud_instance_name","cloud_instance_host_name","cloud_graph_host_name","msgraph_host","aud","exp","iat","auth_time","acr","nonce","preferred_username","name","tid","ver","at_hash","c_hash","email"],"kerberos_endpoint":"https://login.microsoftonline.com/common/kerberos","tenant_region_scope":null,"cloud_instance_name":"microsoftonline.com","cloud_graph_host_name":"graph.windows.net","msgraph_host":"graph.microsoft.com","rbac_url":"https://pas.windows.net"}', + clientCapabilities: [], + }, + system: { + loggerOptions: { + logLevel: getMSALLogLevel(logger$o.getLogLevel()), + }, + }, + }); + } + async cachedAvailableMSI(scopes, getTokenOptions) { + if (this.cachedMSI) { + return this.cachedMSI; + } + const MSIs = [ + arcMsi, + fabricMsi, + appServiceMsi2019, + appServiceMsi2017, + cloudShellMsi, + tokenExchangeMsi(), + imdsMsi, + ]; + for (const msi of MSIs) { + if (await msi.isAvailable({ + scopes, + identityClient: this.isAvailableIdentityClient, + clientId: this.clientId, + resourceId: this.resourceId, + getTokenOptions, + })) { + this.cachedMSI = msi; + return msi; + } + } + throw new CredentialUnavailableError(`${ManagedIdentityCredential.name} - No MSI credential available`); + } + async authenticateManagedIdentity(scopes, getTokenOptions) { + const { span, updatedOptions } = tracingClient.startSpan(`${ManagedIdentityCredential.name}.authenticateManagedIdentity`, getTokenOptions); + try { + // Determining the available MSI, and avoiding checking for other MSIs while the program is running. + const availableMSI = await this.cachedAvailableMSI(scopes, updatedOptions); + return availableMSI.getToken({ + identityClient: this.identityClient, + scopes, + clientId: this.clientId, + resourceId: this.resourceId, + }, updatedOptions); + } + catch (err) { + span.setStatus({ + status: "error", + error: err, + }); + throw err; + } + finally { + span.end(); + } + } + /** + * Authenticates with Azure Active Directory and returns an access token if successful. + * If authentication fails, a {@link CredentialUnavailableError} will be thrown with the details of the failure. + * If an unexpected error occurs, an {@link AuthenticationError} will be thrown with the details of the failure. + * + * @param scopes - The list of scopes for which the token will have access. + * @param options - The options used to configure any requests this + * TokenCredential implementation might make. + */ + async getToken(scopes, options) { + let result = null; + const { span, updatedOptions } = tracingClient.startSpan(`${ManagedIdentityCredential.name}.getToken`, options); + try { + // isEndpointAvailable can be true, false, or null, + // If it's null, it means we don't yet know whether + // the endpoint is available and need to check for it. + if (this.isEndpointUnavailable !== true) { + const availableMSI = await this.cachedAvailableMSI(scopes, updatedOptions); + if (availableMSI.name === "tokenExchangeMsi") { + result = await this.authenticateManagedIdentity(scopes, updatedOptions); + } + else { + const appTokenParameters = { + correlationId: this.identityClient.getCorrelationId(), + tenantId: (options === null || options === void 0 ? void 0 : options.tenantId) || "organizations", + scopes: Array.isArray(scopes) ? scopes : [scopes], + claims: options === null || options === void 0 ? void 0 : options.claims, + }; + // Added a check to see if SetAppTokenProvider was already defined. + this.initializeSetAppTokenProvider(); + const authenticationResult = await this.confidentialApp.acquireTokenByClientCredential(Object.assign({}, appTokenParameters)); + result = this.handleResult(scopes, authenticationResult || undefined); + } + if (result === null) { + // If authenticateManagedIdentity returns null, + // it means no MSI endpoints are available. + // If so, we avoid trying to reach to them in future requests. + this.isEndpointUnavailable = true; + // It also means that the endpoint answered with either 200 or 201 (see the sendTokenRequest method), + // yet we had no access token. For this reason, we'll throw once with a specific message: + const error = new CredentialUnavailableError("The managed identity endpoint was reached, yet no tokens were received."); + logger$c.getToken.info(formatError(scopes, error)); + throw error; + } + // Since `authenticateManagedIdentity` didn't throw, and the result was not null, + // We will assume that this endpoint is reachable from this point forward, + // and avoid pinging again to it. + this.isEndpointUnavailable = false; + } + else { + // We've previously determined that the endpoint was unavailable, + // either because it was unreachable or permanently unable to authenticate. + const error = new CredentialUnavailableError("The managed identity endpoint is not currently available"); + logger$c.getToken.info(formatError(scopes, error)); + throw error; + } + logger$c.getToken.info(formatSuccess(scopes)); + return result; + } + catch (err) { + // CredentialUnavailable errors are expected to reach here. + // We intend them to bubble up, so that DefaultAzureCredential can catch them. + if (err.name === "AuthenticationRequiredError") { + throw err; + } + // Expected errors to reach this point: + // - Errors coming from a method unexpectedly breaking. + // - When identityClient.sendTokenRequest throws, in which case + // if the status code was 400, it means that the endpoint is working, + // but no identity is available. + span.setStatus({ + status: "error", + error: err, + }); + // If either the network is unreachable, + // we can safely assume the credential is unavailable. + if (err.code === "ENETUNREACH") { + const error = new CredentialUnavailableError(`${ManagedIdentityCredential.name}: Unavailable. Network unreachable. Message: ${err.message}`); + logger$c.getToken.info(formatError(scopes, error)); + throw error; + } + // If either the host was unreachable, + // we can safely assume the credential is unavailable. + if (err.code === "EHOSTUNREACH") { + const error = new CredentialUnavailableError(`${ManagedIdentityCredential.name}: Unavailable. No managed identity endpoint found. Message: ${err.message}`); + logger$c.getToken.info(formatError(scopes, error)); + throw error; + } + // If err.statusCode has a value of 400, it comes from sendTokenRequest, + // and it means that the endpoint is working, but that no identity is available. + if (err.statusCode === 400) { + throw new CredentialUnavailableError(`${ManagedIdentityCredential.name}: The managed identity endpoint is indicating there's no available identity. Message: ${err.message}`); + } + // If the error has no status code, we can assume there was no available identity. + // This will throw silently during any ChainedTokenCredential. + if (err.statusCode === undefined) { + throw new CredentialUnavailableError(`${ManagedIdentityCredential.name}: Authentication failed. Message ${err.message}`); + } + // Any other error should break the chain. + throw new AuthenticationError(err.statusCode, { + error: `${ManagedIdentityCredential.name} authentication failed.`, + error_description: err.message, + }); + } + finally { + // Finally is always called, both if we return and if we throw in the above try/catch. + span.end(); + } + } + /** + * Handles the MSAL authentication result. + * If the result has an account, we update the local account reference. + * If the token received is invalid, an error will be thrown depending on what's missing. + */ + handleResult(scopes, result, getTokenOptions) { + this.ensureValidMsalToken(scopes, result, getTokenOptions); + logger$c.getToken.info(formatSuccess(scopes)); + return { + token: result.accessToken, + expiresOnTimestamp: result.expiresOn.getTime(), + }; + } + /** + * Ensures the validity of the MSAL token + * @internal + */ + ensureValidMsalToken(scopes, msalToken, getTokenOptions) { + const error = (message) => { + logger$c.getToken.info(message); + return new AuthenticationRequiredError({ + scopes: Array.isArray(scopes) ? scopes : [scopes], + getTokenOptions, + message, + }); + }; + if (!msalToken) { + throw error("No response"); + } + if (!msalToken.expiresOn) { + throw error(`Response had no "expiresOn" property.`); + } + if (!msalToken.accessToken) { + throw error(`Response had no "accessToken" property.`); + } + } + initializeSetAppTokenProvider() { + if (!this.isAppTokenProviderInitialized) { + this.confidentialApp.SetAppTokenProvider(async (appTokenProviderParameters) => { + logger$c.info(`SetAppTokenProvider invoked with parameters- ${JSON.stringify(appTokenProviderParameters)}`); + const getTokenOptions = Object.assign({}, appTokenProviderParameters); + logger$c.info(`authenticateManagedIdentity invoked with scopes- ${JSON.stringify(appTokenProviderParameters.scopes)} and getTokenOptions - ${JSON.stringify(getTokenOptions)}`); + const resultToken = await this.authenticateManagedIdentity(appTokenProviderParameters.scopes, getTokenOptions); + if (resultToken) { + logger$c.info(`SetAppTokenProvider will save the token in cache`); + const expiresInSeconds = (resultToken === null || resultToken === void 0 ? void 0 : resultToken.expiresOnTimestamp) + ? Math.floor((resultToken.expiresOnTimestamp - Date.now()) / 1000) + : 0; + return { + accessToken: resultToken === null || resultToken === void 0 ? void 0 : resultToken.token, + expiresInSeconds, + }; + } + else { + logger$c.info(`SetAppTokenProvider token has "no_access_token_returned" as the saved token`); + return { + accessToken: "no_access_token_returned", + expiresInSeconds: 0, + }; + } + }); + this.isAppTokenProviderInitialized = true; + } + } +} + +// Copyright (c) Microsoft Corporation. +/** + * Ensures the scopes value is an array. + * @internal + */ +function ensureScopes(scopes) { + return Array.isArray(scopes) ? scopes : [scopes]; +} +/** + * Throws if the received scope is not valid. + * @internal + */ +function ensureValidScopeForDevTimeCreds(scope, logger) { + if (!scope.match(/^[0-9a-zA-Z-.:/]+$/)) { + const error = new Error("Invalid scope was specified by the user or calling client"); + logger.getToken.info(formatError(scope, error)); + throw error; + } +} +/** + * Returns the resource out of a scope. + * @internal + */ +function getScopeResource(scope) { + return scope.replace(/\/.default$/, ""); +} + +// Copyright (c) Microsoft Corporation. +/** + * Mockable reference to the CLI credential cliCredentialFunctions + * @internal + */ +const cliCredentialInternals = { + /** + * @internal + */ + getSafeWorkingDir() { + if (process.platform === "win32") { + if (!process.env.SystemRoot) { + throw new Error("Azure CLI credential expects a 'SystemRoot' environment variable"); + } + return process.env.SystemRoot; + } + else { + return "/bin"; + } + }, + /** + * Gets the access token from Azure CLI + * @param resource - The resource to use when getting the token + * @internal + */ + async getAzureCliAccessToken(resource, tenantId, timeout) { + let tenantSection = []; + if (tenantId) { + tenantSection = ["--tenant", tenantId]; + } + return new Promise((resolve, reject) => { + try { + child_process__default["default"].execFile("az", [ + "account", + "get-access-token", + "--output", + "json", + "--resource", + resource, + ...tenantSection, + ], { cwd: cliCredentialInternals.getSafeWorkingDir(), shell: true, timeout }, (error, stdout, stderr) => { + resolve({ stdout: stdout, stderr: stderr, error }); + }); + } + catch (err) { + reject(err); + } + }); + }, +}; +const logger$b = credentialLogger("AzureCliCredential"); +/** + * This credential will use the currently logged-in user login information + * via the Azure CLI ('az') commandline tool. + * To do so, it will read the user access token and expire time + * with Azure CLI command "az account get-access-token". + */ +class AzureCliCredential { + /** + * Creates an instance of the {@link AzureCliCredential}. + * + * To use this credential, ensure that you have already logged + * in via the 'az' tool using the command "az login" from the commandline. + * + * @param options - Options, to optionally allow multi-tenant requests. + */ + constructor(options) { + this.tenantId = options === null || options === void 0 ? void 0 : options.tenantId; + this.additionallyAllowedTenantIds = resolveAddionallyAllowedTenantIds(options === null || options === void 0 ? void 0 : options.additionallyAllowedTenants); + this.timeout = options === null || options === void 0 ? void 0 : options.processTimeoutInMs; + } + /** + * Authenticates with Azure Active Directory and returns an access token if successful. + * If authentication fails, a {@link CredentialUnavailableError} will be thrown with the details of the failure. + * + * @param scopes - The list of scopes for which the token will have access. + * @param options - The options used to configure any requests this + * TokenCredential implementation might make. + */ + async getToken(scopes, options = {}) { + const tenantId = processMultiTenantRequest(this.tenantId, options, this.additionallyAllowedTenantIds); + const scope = typeof scopes === "string" ? scopes : scopes[0]; + logger$b.getToken.info(`Using the scope ${scope}`); + return tracingClient.withSpan(`${this.constructor.name}.getToken`, options, async () => { + var _a, _b, _c, _d; + try { + ensureValidScopeForDevTimeCreds(scope, logger$b); + const resource = getScopeResource(scope); + const obj = await cliCredentialInternals.getAzureCliAccessToken(resource, tenantId, this.timeout); + const specificScope = (_a = obj.stderr) === null || _a === void 0 ? void 0 : _a.match("(.*)az login --scope(.*)"); + const isLoginError = ((_b = obj.stderr) === null || _b === void 0 ? void 0 : _b.match("(.*)az login(.*)")) && !specificScope; + const isNotInstallError = ((_c = obj.stderr) === null || _c === void 0 ? void 0 : _c.match("az:(.*)not found")) || ((_d = obj.stderr) === null || _d === void 0 ? void 0 : _d.startsWith("'az' is not recognized")); + if (isNotInstallError) { + const error = new CredentialUnavailableError("Azure CLI could not be found. Please visit https://aka.ms/azure-cli for installation instructions and then, once installed, authenticate to your Azure account using 'az login'."); + logger$b.getToken.info(formatError(scopes, error)); + throw error; + } + if (isLoginError) { + const error = new CredentialUnavailableError("Please run 'az login' from a command prompt to authenticate before using this credential."); + logger$b.getToken.info(formatError(scopes, error)); + throw error; + } + try { + const responseData = obj.stdout; + const response = JSON.parse(responseData); + logger$b.getToken.info(formatSuccess(scopes)); + const returnValue = { + token: response.accessToken, + expiresOnTimestamp: new Date(response.expiresOn).getTime(), + }; + return returnValue; + } + catch (e) { + if (obj.stderr) { + throw new CredentialUnavailableError(obj.stderr); + } + throw e; + } + } + catch (err) { + const error = err.name === "CredentialUnavailableError" + ? err + : new CredentialUnavailableError(err.message || "Unknown error while trying to retrieve the access token"); + logger$b.getToken.info(formatError(scopes, error)); + throw error; + } + }); + } +} + +// Copyright (c) Microsoft Corporation. +/** + * Easy to mock childProcess utils. + * @internal + */ +const processUtils = { + /** + * Promisifying childProcess.execFile + * @internal + */ + execFile(file, params, options) { + return new Promise((resolve, reject) => { + child_process__namespace.execFile(file, params, options, (error, stdout, stderr) => { + if (Buffer.isBuffer(stdout)) { + stdout = stdout.toString("utf8"); + } + if (Buffer.isBuffer(stderr)) { + stderr = stderr.toString("utf8"); + } + if (stderr || error) { + reject(stderr ? new Error(stderr) : error); + } + else { + resolve(stdout); + } + }); + }); + }, +}; + +// Copyright (c) Microsoft Corporation. +const logger$a = credentialLogger("AzurePowerShellCredential"); +const isWindows = process.platform === "win32"; +/** + * Returns a platform-appropriate command name by appending ".exe" on Windows. + * + * @internal + */ +function formatCommand(commandName) { + if (isWindows) { + return `${commandName}.exe`; + } + else { + return commandName; + } +} +/** + * Receives a list of commands to run, executes them, then returns the outputs. + * If anything fails, an error is thrown. + * @internal + */ +async function runCommands(commands, timeout) { + const results = []; + for (const command of commands) { + const [file, ...parameters] = command; + const result = (await processUtils.execFile(file, parameters, { + encoding: "utf8", + timeout, + })); + results.push(result); + } + return results; +} +/** + * Known PowerShell errors + * @internal + */ +const powerShellErrors = { + login: "Run Connect-AzAccount to login", + installed: "The specified module 'Az.Accounts' with version '2.2.0' was not loaded because no valid module file was found in any module directory", +}; +/** + * Messages to use when throwing in this credential. + * @internal + */ +const powerShellPublicErrorMessages = { + login: "Please run 'Connect-AzAccount' from PowerShell to authenticate before using this credential.", + installed: `The 'Az.Account' module >= 2.2.0 is not installed. Install the Azure Az PowerShell module with: "Install-Module -Name Az -Scope CurrentUser -Repository PSGallery -Force".`, + troubleshoot: `To troubleshoot, visit https://aka.ms/azsdk/js/identity/powershellcredential/troubleshoot.`, +}; +// PowerShell Azure User not logged in error check. +const isLoginError = (err) => err.message.match(`(.*)${powerShellErrors.login}(.*)`); +// Az Module not Installed in Azure PowerShell check. +const isNotInstalledError = (err) => err.message.match(powerShellErrors.installed); +/** + * The PowerShell commands to be tried, in order. + * + * @internal + */ +const commandStack = [formatCommand("pwsh")]; +if (isWindows) { + commandStack.push(formatCommand("powershell")); +} +/** + * This credential will use the currently logged-in user information from the + * Azure PowerShell module. To do so, it will read the user access token and + * expire time with Azure PowerShell command `Get-AzAccessToken -ResourceUrl {ResourceScope}` + */ +class AzurePowerShellCredential { + /** + * Creates an instance of the {@link AzurePowerShellCredential}. + * + * To use this credential: + * - Install the Azure Az PowerShell module with: + * `Install-Module -Name Az -Scope CurrentUser -Repository PSGallery -Force`. + * - You have already logged in to Azure PowerShell using the command + * `Connect-AzAccount` from the command line. + * + * @param options - Options, to optionally allow multi-tenant requests. + */ + constructor(options) { + this.tenantId = options === null || options === void 0 ? void 0 : options.tenantId; + this.additionallyAllowedTenantIds = resolveAddionallyAllowedTenantIds(options === null || options === void 0 ? void 0 : options.additionallyAllowedTenants); + this.timeout = options === null || options === void 0 ? void 0 : options.processTimeoutInMs; + } + /** + * Gets the access token from Azure PowerShell + * @param resource - The resource to use when getting the token + */ + async getAzurePowerShellAccessToken(resource, tenantId, timeout) { + // Clone the stack to avoid mutating it while iterating + for (const powerShellCommand of [...commandStack]) { + try { + await runCommands([[powerShellCommand, "/?"]], timeout); + } + catch (e) { + // Remove this credential from the original stack so that we don't try it again. + commandStack.shift(); + continue; + } + let tenantSection = ""; + if (tenantId) { + tenantSection = `-TenantId "${tenantId}"`; + } + const results = await runCommands([ + [ + powerShellCommand, + "-Command", + "Import-Module Az.Accounts -MinimumVersion 2.2.0 -PassThru", + ], + [ + powerShellCommand, + "-Command", + `Get-AzAccessToken ${tenantSection} -ResourceUrl "${resource}" | ConvertTo-Json`, + ], + ]); + const result = results[1]; + try { + return JSON.parse(result); + } + catch (e) { + throw new Error(`Unable to parse the output of PowerShell. Received output: ${result}`); + } + } + throw new Error(`Unable to execute PowerShell. Ensure that it is installed in your system`); + } + /** + * Authenticates with Azure Active Directory and returns an access token if successful. + * If the authentication cannot be performed through PowerShell, a {@link CredentialUnavailableError} will be thrown. + * + * @param scopes - The list of scopes for which the token will have access. + * @param options - The options used to configure any requests this TokenCredential implementation might make. + */ + async getToken(scopes, options = {}) { + return tracingClient.withSpan(`${this.constructor.name}.getToken`, options, async () => { + const tenantId = processMultiTenantRequest(this.tenantId, options, this.additionallyAllowedTenantIds); + const scope = typeof scopes === "string" ? scopes : scopes[0]; + try { + ensureValidScopeForDevTimeCreds(scope, logger$a); + logger$a.getToken.info(`Using the scope ${scope}`); + const resource = getScopeResource(scope); + const response = await this.getAzurePowerShellAccessToken(resource, tenantId, this.timeout); + logger$a.getToken.info(formatSuccess(scopes)); + return { + token: response.Token, + expiresOnTimestamp: new Date(response.ExpiresOn).getTime(), + }; + } + catch (err) { + if (isNotInstalledError(err)) { + const error = new CredentialUnavailableError(powerShellPublicErrorMessages.installed); + logger$a.getToken.info(formatError(scope, error)); + throw error; + } + else if (isLoginError(err)) { + const error = new CredentialUnavailableError(powerShellPublicErrorMessages.login); + logger$a.getToken.info(formatError(scope, error)); + throw error; + } + const error = new CredentialUnavailableError(`${err}. ${powerShellPublicErrorMessages.troubleshoot}`); + logger$a.getToken.info(formatError(scope, error)); + throw error; + } + }); + } +} + +// Copyright (c) Microsoft Corporation. +/** + * @internal + */ +const logger$9 = credentialLogger("ChainedTokenCredential"); +/** + * Enables multiple `TokenCredential` implementations to be tried in order + * until one of the getToken methods returns an access token. + */ +class ChainedTokenCredential { + /** + * Creates an instance of ChainedTokenCredential using the given credentials. + * + * @param sources - `TokenCredential` implementations to be tried in order. + * + * Example usage: + * ```javascript + * const firstCredential = new ClientSecretCredential(tenantId, clientId, clientSecret); + * const secondCredential = new ClientSecretCredential(tenantId, anotherClientId, anotherSecret); + * const credentialChain = new ChainedTokenCredential(firstCredential, secondCredential); + * ``` + */ + constructor(...sources) { + this._sources = []; + this._sources = sources; + } + /** + * Returns the first access token returned by one of the chained + * `TokenCredential` implementations. Throws an {@link AggregateAuthenticationError} + * when one or more credentials throws an {@link AuthenticationError} and + * no credentials have returned an access token. + * + * This method is called automatically by Azure SDK client libraries. You may call this method + * directly, but you must also handle token caching and token refreshing. + * + * @param scopes - The list of scopes for which the token will have access. + * @param options - The options used to configure any requests this + * `TokenCredential` implementation might make. + */ + async getToken(scopes, options = {}) { + const { token } = await this.getTokenInternal(scopes, options); + return token; + } + async getTokenInternal(scopes, options = {}) { + let token = null; + let successfulCredential; + const errors = []; + return tracingClient.withSpan("ChainedTokenCredential.getToken", options, async (updatedOptions) => { + for (let i = 0; i < this._sources.length && token === null; i++) { + try { + token = await this._sources[i].getToken(scopes, updatedOptions); + successfulCredential = this._sources[i]; + } + catch (err) { + if (err.name === "CredentialUnavailableError" || + err.name === "AuthenticationRequiredError") { + errors.push(err); + } + else { + logger$9.getToken.info(formatError(scopes, err)); + throw err; + } + } + } + if (!token && errors.length > 0) { + const err = new AggregateAuthenticationError(errors, "ChainedTokenCredential authentication failed."); + logger$9.getToken.info(formatError(scopes, err)); + throw err; + } + logger$9.getToken.info(`Result for ${successfulCredential.constructor.name}: ${formatSuccess(scopes)}`); + if (token === null) { + throw new CredentialUnavailableError("Failed to retrieve a valid token"); + } + return { token, successfulCredential }; + }); + } +} + +// Copyright (c) Microsoft Corporation. +const readFileAsync = util.promisify(fs.readFile); +/** + * Tries to asynchronously load a certificate from the given path. + * + * @param configuration - Either the PEM value or the path to the certificate. + * @param sendCertificateChain - Option to include x5c header for SubjectName and Issuer name authorization. + * @returns - The certificate parts, or `undefined` if the certificate could not be loaded. + * @internal + */ +async function parseCertificate(configuration, sendCertificateChain) { + const certificateParts = {}; + const certificate = configuration + .certificate; + const certificatePath = configuration + .certificatePath; + certificateParts.certificateContents = + certificate || (await readFileAsync(certificatePath, "utf8")); + if (sendCertificateChain) { + certificateParts.x5c = certificateParts.certificateContents; + } + const certificatePattern = /(-+BEGIN CERTIFICATE-+)(\n\r?|\r\n?)([A-Za-z0-9+/\n\r]+=*)(\n\r?|\r\n?)(-+END CERTIFICATE-+)/g; + const publicKeys = []; + // Match all possible certificates, in the order they are in the file. These will form the chain that is used for x5c + let match; + do { + match = certificatePattern.exec(certificateParts.certificateContents); + if (match) { + publicKeys.push(match[3]); + } + } while (match); + if (publicKeys.length === 0) { + throw new Error("The file at the specified path does not contain a PEM-encoded certificate."); + } + certificateParts.thumbprint = crypto.createHash("sha1") + .update(Buffer.from(publicKeys[0], "base64")) + .digest("hex") + .toUpperCase(); + return certificateParts; +} +/** + * MSAL client certificate client. Calls to MSAL's confidential application's `acquireTokenByClientCredential` during `doGetToken`. + * @internal + */ +class MsalClientCertificate extends MsalNode { + constructor(options) { + super(options); + this.requiresConfidential = true; + this.configuration = options.configuration; + this.sendCertificateChain = options.sendCertificateChain; + } + // Changing the MSAL configuration asynchronously + async init(options) { + try { + const parts = await parseCertificate(this.configuration, this.sendCertificateChain); + let privateKey; + if (this.configuration.certificatePassword !== undefined) { + const privateKeyObject = crypto.createPrivateKey({ + key: parts.certificateContents, + passphrase: this.configuration.certificatePassword, + format: "pem", + }); + privateKey = privateKeyObject + .export({ + format: "pem", + type: "pkcs8", + }) + .toString(); + } + else { + privateKey = parts.certificateContents; + } + this.msalConfig.auth.clientCertificate = { + thumbprint: parts.thumbprint, + privateKey: privateKey, + x5c: parts.x5c, + }; + } + catch (error) { + this.logger.info(formatError("", error)); + throw error; + } + return super.init(options); + } + async doGetToken(scopes, options = {}) { + try { + const clientCredReq = { + scopes, + correlationId: options.correlationId, + azureRegion: this.azureRegion, + authority: options.authority, + claims: options.claims, + }; + const result = await this.getApp("confidential", options.enableCae).acquireTokenByClientCredential(clientCredReq); + // Even though we're providing the same default in memory persistence cache that we use for DeviceCodeCredential, + // The Client Credential flow does not return the account information from the authentication service, + // so each time getToken gets called, we will have to acquire a new token through the service. + return this.handleResult(scopes, this.clientId, result || undefined); + } + catch (err) { + throw this.handleError(scopes, err, options); + } + } +} + +// Copyright (c) Microsoft Corporation. +const credentialName$2 = "ClientCertificateCredential"; +const logger$8 = credentialLogger(credentialName$2); +/** + * Enables authentication to Azure Active Directory using a PEM-encoded + * certificate that is assigned to an App Registration. More information + * on how to configure certificate authentication can be found here: + * + * https://docs.microsoft.com/en-us/azure/active-directory/develop/active-directory-certificate-credentials#register-your-certificate-with-azure-ad + * + */ +class ClientCertificateCredential { + constructor(tenantId, clientId, certificatePathOrConfiguration, options = {}) { + if (!tenantId || !clientId) { + throw new Error(`${credentialName$2}: tenantId and clientId are required parameters.`); + } + this.tenantId = tenantId; + this.additionallyAllowedTenantIds = resolveAddionallyAllowedTenantIds(options === null || options === void 0 ? void 0 : options.additionallyAllowedTenants); + const configuration = Object.assign({}, (typeof certificatePathOrConfiguration === "string" + ? { + certificatePath: certificatePathOrConfiguration, + } + : certificatePathOrConfiguration)); + const certificate = configuration + .certificate; + const certificatePath = configuration.certificatePath; + if (!configuration || !(certificate || certificatePath)) { + throw new Error(`${credentialName$2}: Provide either a PEM certificate in string form, or the path to that certificate in the filesystem. To troubleshoot, visit https://aka.ms/azsdk/js/identity/serviceprincipalauthentication/troubleshoot.`); + } + if (certificate && certificatePath) { + throw new Error(`${credentialName$2}: To avoid unexpected behaviors, providing both the contents of a PEM certificate and the path to a PEM certificate is forbidden. To troubleshoot, visit https://aka.ms/azsdk/js/identity/serviceprincipalauthentication/troubleshoot.`); + } + this.msalFlow = new MsalClientCertificate(Object.assign(Object.assign({}, options), { configuration, + logger: logger$8, + clientId, + tenantId, sendCertificateChain: options.sendCertificateChain, tokenCredentialOptions: options })); + } + /** + * Authenticates with Azure Active Directory and returns an access token if successful. + * If authentication fails, a {@link CredentialUnavailableError} will be thrown with the details of the failure. + * + * @param scopes - The list of scopes for which the token will have access. + * @param options - The options used to configure any requests this + * TokenCredential implementation might make. + */ + async getToken(scopes, options = {}) { + return tracingClient.withSpan(`${credentialName$2}.getToken`, options, async (newOptions) => { + newOptions.tenantId = processMultiTenantRequest(this.tenantId, newOptions, this.additionallyAllowedTenantIds, logger$8); + const arrayScopes = Array.isArray(scopes) ? scopes : [scopes]; + return this.msalFlow.getToken(arrayScopes, newOptions); + }); + } +} + +// Copyright (c) Microsoft Corporation. +/** + * MSAL client secret client. Calls to MSAL's confidential application's `acquireTokenByClientCredential` during `doGetToken`. + * @internal + */ +class MsalClientSecret extends MsalNode { + constructor(options) { + super(options); + this.requiresConfidential = true; + this.msalConfig.auth.clientSecret = options.clientSecret; + } + async doGetToken(scopes, options = {}) { + try { + const result = await this.getApp("confidential", options.enableCae).acquireTokenByClientCredential({ + scopes, + correlationId: options.correlationId, + azureRegion: this.azureRegion, + authority: options.authority, + claims: options.claims, + }); + // The Client Credential flow does not return an account, + // so each time getToken gets called, we will have to acquire a new token through the service. + return this.handleResult(scopes, this.clientId, result || undefined); + } + catch (err) { + throw this.handleError(scopes, err, options); + } + } +} + +// Copyright (c) Microsoft Corporation. +const logger$7 = credentialLogger("ClientSecretCredential"); +/** + * Enables authentication to Azure Active Directory using a client secret + * that was generated for an App Registration. More information on how + * to configure a client secret can be found here: + * + * https://docs.microsoft.com/en-us/azure/active-directory/develop/quickstart-configure-app-access-web-apis#add-credentials-to-your-web-application + * + */ +class ClientSecretCredential { + /** + * Creates an instance of the ClientSecretCredential with the details + * needed to authenticate against Azure Active Directory with a client + * secret. + * + * @param tenantId - The Azure Active Directory tenant (directory) ID. + * @param clientId - The client (application) ID of an App Registration in the tenant. + * @param clientSecret - A client secret that was generated for the App Registration. + * @param options - Options for configuring the client which makes the authentication request. + */ + constructor(tenantId, clientId, clientSecret, options = {}) { + if (!tenantId || !clientId || !clientSecret) { + throw new Error("ClientSecretCredential: tenantId, clientId, and clientSecret are required parameters. To troubleshoot, visit https://aka.ms/azsdk/js/identity/serviceprincipalauthentication/troubleshoot."); + } + this.tenantId = tenantId; + this.additionallyAllowedTenantIds = resolveAddionallyAllowedTenantIds(options === null || options === void 0 ? void 0 : options.additionallyAllowedTenants); + this.msalFlow = new MsalClientSecret(Object.assign(Object.assign({}, options), { logger: logger$7, + clientId, + tenantId, + clientSecret, tokenCredentialOptions: options })); + } + /** + * Authenticates with Azure Active Directory and returns an access token if successful. + * If authentication fails, a {@link CredentialUnavailableError} will be thrown with the details of the failure. + * + * @param scopes - The list of scopes for which the token will have access. + * @param options - The options used to configure any requests this + * TokenCredential implementation might make. + */ + async getToken(scopes, options = {}) { + return tracingClient.withSpan(`${this.constructor.name}.getToken`, options, async (newOptions) => { + newOptions.tenantId = processMultiTenantRequest(this.tenantId, newOptions, this.additionallyAllowedTenantIds, logger$7); + const arrayScopes = ensureScopes(scopes); + return this.msalFlow.getToken(arrayScopes, newOptions); + }); + } +} + +// Copyright (c) Microsoft Corporation. +/** + * MSAL username and password client. Calls to the MSAL's public application's `acquireTokenByUsernamePassword` during `doGetToken`. + * @internal + */ +class MsalUsernamePassword extends MsalNode { + constructor(options) { + super(options); + this.username = options.username; + this.password = options.password; + } + async doGetToken(scopes, options) { + try { + const requestOptions = { + scopes, + username: this.username, + password: this.password, + correlationId: options === null || options === void 0 ? void 0 : options.correlationId, + authority: options === null || options === void 0 ? void 0 : options.authority, + claims: options === null || options === void 0 ? void 0 : options.claims, + }; + const result = await this.getApp("public", options === null || options === void 0 ? void 0 : options.enableCae).acquireTokenByUsernamePassword(requestOptions); + return this.handleResult(scopes, this.clientId, result || undefined); + } + catch (error) { + throw this.handleError(scopes, error, options); + } + } +} + +// Copyright (c) Microsoft Corporation. +const logger$6 = credentialLogger("UsernamePasswordCredential"); +/** + * Enables authentication to Azure Active Directory with a user's + * username and password. This credential requires a high degree of + * trust so you should only use it when other, more secure credential + * types can't be used. + */ +class UsernamePasswordCredential { + /** + * Creates an instance of the UsernamePasswordCredential with the details + * needed to authenticate against Azure Active Directory with a username + * and password. + * + * @param tenantId - The Azure Active Directory tenant (directory). + * @param clientId - The client (application) ID of an App Registration in the tenant. + * @param username - The user account's e-mail address (user name). + * @param password - The user account's account password + * @param options - Options for configuring the client which makes the authentication request. + */ + constructor(tenantId, clientId, username, password, options = {}) { + if (!tenantId || !clientId || !username || !password) { + throw new Error("UsernamePasswordCredential: tenantId, clientId, username and password are required parameters. To troubleshoot, visit https://aka.ms/azsdk/js/identity/usernamepasswordcredential/troubleshoot."); + } + this.tenantId = tenantId; + this.additionallyAllowedTenantIds = resolveAddionallyAllowedTenantIds(options === null || options === void 0 ? void 0 : options.additionallyAllowedTenants); + this.msalFlow = new MsalUsernamePassword(Object.assign(Object.assign({}, options), { logger: logger$6, + clientId, + tenantId, + username, + password, tokenCredentialOptions: options || {} })); + } + /** + * Authenticates with Azure Active Directory and returns an access token if successful. + * If authentication fails, a {@link CredentialUnavailableError} will be thrown with the details of the failure. + * + * If the user provided the option `disableAutomaticAuthentication`, + * once the token can't be retrieved silently, + * this method won't attempt to request user interaction to retrieve the token. + * + * @param scopes - The list of scopes for which the token will have access. + * @param options - The options used to configure any requests this + * TokenCredential implementation might make. + */ + async getToken(scopes, options = {}) { + return tracingClient.withSpan(`${this.constructor.name}.getToken`, options, async (newOptions) => { + newOptions.tenantId = processMultiTenantRequest(this.tenantId, newOptions, this.additionallyAllowedTenantIds, logger$6); + const arrayScopes = ensureScopes(scopes); + return this.msalFlow.getToken(arrayScopes, newOptions); + }); + } +} + +// Copyright (c) Microsoft Corporation. +/** + * Contains the list of all supported environment variable names so that an + * appropriate error message can be generated when no credentials can be + * configured. + * + * @internal + */ +const AllSupportedEnvironmentVariables = [ + "AZURE_TENANT_ID", + "AZURE_CLIENT_ID", + "AZURE_CLIENT_SECRET", + "AZURE_CLIENT_CERTIFICATE_PATH", + "AZURE_CLIENT_CERTIFICATE_PASSWORD", + "AZURE_USERNAME", + "AZURE_PASSWORD", + "AZURE_ADDITIONALLY_ALLOWED_TENANTS", +]; +function getAdditionallyAllowedTenants() { + var _a; + const additionallyAllowedValues = (_a = process.env.AZURE_ADDITIONALLY_ALLOWED_TENANTS) !== null && _a !== void 0 ? _a : ""; + return additionallyAllowedValues.split(";"); +} +const credentialName$1 = "EnvironmentCredential"; +const logger$5 = credentialLogger(credentialName$1); +/** + * Enables authentication to Azure Active Directory using a client secret or certificate, or as a user + * with a username and password. + */ +class EnvironmentCredential { + /** + * Creates an instance of the EnvironmentCredential class and decides what credential to use depending on the available environment variables. + * + * Required environment variables: + * - `AZURE_TENANT_ID`: The Azure Active Directory tenant (directory) ID. + * - `AZURE_CLIENT_ID`: The client (application) ID of an App Registration in the tenant. + * + * If setting the AZURE_TENANT_ID, then you can also set the additionally allowed tenants + * - `AZURE_ADDITIONALLY_ALLOWED_TENANTS`: For multi-tenant applications, specifies additional tenants for which the credential may acquire tokens with a single semicolon delimited string. Use * to allow all tenants. + * + * Environment variables used for client credential authentication: + * - `AZURE_CLIENT_SECRET`: A client secret that was generated for the App Registration. + * - `AZURE_CLIENT_CERTIFICATE_PATH`: The path to a PEM certificate to use during the authentication, instead of the client secret. + * - `AZURE_CLIENT_CERTIFICATE_PASSWORD`: (optional) password for the certificate file. + * + * Alternatively, users can provide environment variables for username and password authentication: + * - `AZURE_USERNAME`: Username to authenticate with. + * - `AZURE_PASSWORD`: Password to authenticate with. + * + * If the environment variables required to perform the authentication are missing, a {@link CredentialUnavailableError} will be thrown. + * If the authentication fails, or if there's an unknown error, an {@link AuthenticationError} will be thrown. + * + * @param options - Options for configuring the client which makes the authentication request. + */ + constructor(options) { + // Keep track of any missing environment variables for error details + this._credential = undefined; + const assigned = processEnvVars(AllSupportedEnvironmentVariables).assigned.join(", "); + logger$5.info(`Found the following environment variables: ${assigned}`); + const tenantId = process.env.AZURE_TENANT_ID, clientId = process.env.AZURE_CLIENT_ID, clientSecret = process.env.AZURE_CLIENT_SECRET; + const additionallyAllowedTenantIds = getAdditionallyAllowedTenants(); + const newOptions = Object.assign(Object.assign({}, options), { additionallyAllowedTenantIds }); + if (tenantId) { + checkTenantId(logger$5, tenantId); + } + if (tenantId && clientId && clientSecret) { + logger$5.info(`Invoking ClientSecretCredential with tenant ID: ${tenantId}, clientId: ${clientId} and clientSecret: [REDACTED]`); + this._credential = new ClientSecretCredential(tenantId, clientId, clientSecret, newOptions); + return; + } + const certificatePath = process.env.AZURE_CLIENT_CERTIFICATE_PATH; + const certificatePassword = process.env.AZURE_CLIENT_CERTIFICATE_PASSWORD; + if (tenantId && clientId && certificatePath) { + logger$5.info(`Invoking ClientCertificateCredential with tenant ID: ${tenantId}, clientId: ${clientId} and certificatePath: ${certificatePath}`); + this._credential = new ClientCertificateCredential(tenantId, clientId, { certificatePath, certificatePassword }, newOptions); + return; + } + const username = process.env.AZURE_USERNAME; + const password = process.env.AZURE_PASSWORD; + if (tenantId && clientId && username && password) { + logger$5.info(`Invoking UsernamePasswordCredential with tenant ID: ${tenantId}, clientId: ${clientId} and username: ${username}`); + this._credential = new UsernamePasswordCredential(tenantId, clientId, username, password, newOptions); + } + } + /** + * Authenticates with Azure Active Directory and returns an access token if successful. + * + * @param scopes - The list of scopes for which the token will have access. + * @param options - Optional parameters. See {@link GetTokenOptions}. + */ + async getToken(scopes, options = {}) { + return tracingClient.withSpan(`${credentialName$1}.getToken`, options, async (newOptions) => { + if (this._credential) { + try { + const result = await this._credential.getToken(scopes, newOptions); + logger$5.getToken.info(formatSuccess(scopes)); + return result; + } + catch (err) { + const authenticationError = new AuthenticationError(400, { + error: `${credentialName$1} authentication failed. To troubleshoot, visit https://aka.ms/azsdk/js/identity/environmentcredential/troubleshoot.`, + error_description: err.message.toString().split("More details:").join(""), + }); + logger$5.getToken.info(formatError(scopes, authenticationError)); + throw authenticationError; + } + } + throw new CredentialUnavailableError(`${credentialName$1} is unavailable. No underlying credential could be used. To troubleshoot, visit https://aka.ms/azsdk/js/identity/environmentcredential/troubleshoot.`); + }); + } +} + +// Copyright (c) Microsoft Corporation. +/** + * Mockable reference to the Developer CLI credential cliCredentialFunctions + * @internal + */ +const developerCliCredentialInternals = { + /** + * @internal + */ + getSafeWorkingDir() { + if (process.platform === "win32") { + if (!process.env.SystemRoot) { + throw new Error("Azure Developer CLI credential expects a 'SystemRoot' environment variable"); + } + return process.env.SystemRoot; + } + else { + return "/bin"; + } + }, + /** + * Gets the access token from Azure Developer CLI + * @param scopes - The scopes to use when getting the token + * @internal + */ + async getAzdAccessToken(scopes, tenantId, timeout) { + let tenantSection = []; + if (tenantId) { + tenantSection = ["--tenant-id", tenantId]; + } + return new Promise((resolve, reject) => { + try { + child_process__default["default"].execFile("azd", [ + "auth", + "token", + "--output", + "json", + ...scopes.reduce((previous, current) => previous.concat("--scope", current), []), + ...tenantSection, + ], { + cwd: developerCliCredentialInternals.getSafeWorkingDir(), + shell: true, + timeout, + }, (error, stdout, stderr) => { + resolve({ stdout, stderr, error }); + }); + } + catch (err) { + reject(err); + } + }); + }, +}; +const logger$4 = credentialLogger("AzureDeveloperCliCredential"); +/** + * Azure Developer CLI is a command-line interface tool that allows developers to create, manage, and deploy + * resources in Azure. It's built on top of the Azure CLI and provides additional functionality specific + * to Azure developers. It allows users to authenticate as a user and/or a service principal against + * Azure Active Directory (Azure AD) + * . The AzureDeveloperCliCredential authenticates in a development environment and acquires a token on behalf of + * the logged-in user or service principal in the Azure Developer CLI. It acts as the Azure Developer CLI logged in user or + * service principal and executes an Azure CLI command underneath to authenticate the application against + * Azure Active Directory. + * + *

Configure AzureDeveloperCliCredential

+ * + * To use this credential, the developer needs to authenticate locally in Azure Developer CLI using one of the + * commands below: + * + *
    + *
  1. Run "azd auth login" in Azure Developer CLI to authenticate interactively as a user.
  2. + *
  3. Run "azd auth login --client-id clientID --client-secret clientSecret + * --tenant-id tenantID" to authenticate as a service principal.
  4. + *
+ * + * You may need to repeat this process after a certain time period, depending on the refresh token validity in your + * organization. Generally, the refresh token validity period is a few weeks to a few months. + * AzureDeveloperCliCredential will prompt you to sign in again. + */ +class AzureDeveloperCliCredential { + /** + * Creates an instance of the {@link AzureDeveloperCliCredential}. + * + * To use this credential, ensure that you have already logged + * in via the 'azd' tool using the command "azd auth login" from the commandline. + * + * @param options - Options, to optionally allow multi-tenant requests. + */ + constructor(options) { + this.tenantId = options === null || options === void 0 ? void 0 : options.tenantId; + this.additionallyAllowedTenantIds = resolveAddionallyAllowedTenantIds(options === null || options === void 0 ? void 0 : options.additionallyAllowedTenants); + this.timeout = options === null || options === void 0 ? void 0 : options.processTimeoutInMs; + } + /** + * Authenticates with Azure Active Directory and returns an access token if successful. + * If authentication fails, a {@link CredentialUnavailableError} will be thrown with the details of the failure. + * + * @param scopes - The list of scopes for which the token will have access. + * @param options - The options used to configure any requests this + * TokenCredential implementation might make. + */ + async getToken(scopes, options = {}) { + const tenantId = processMultiTenantRequest(this.tenantId, options, this.additionallyAllowedTenantIds); + let scopeList; + if (typeof scopes === "string") { + scopeList = [scopes]; + } + else { + scopeList = scopes; + } + logger$4.getToken.info(`Using the scopes ${scopes}`); + return tracingClient.withSpan(`${this.constructor.name}.getToken`, options, async () => { + var _a, _b, _c, _d; + try { + const obj = await developerCliCredentialInternals.getAzdAccessToken(scopeList, tenantId, this.timeout); + const isNotLoggedInError = ((_a = obj.stderr) === null || _a === void 0 ? void 0 : _a.match("not logged in, run `azd login` to login")) || + ((_b = obj.stderr) === null || _b === void 0 ? void 0 : _b.match("not logged in, run `azd auth login` to login")); + const isNotInstallError = ((_c = obj.stderr) === null || _c === void 0 ? void 0 : _c.match("azd:(.*)not found")) || + ((_d = obj.stderr) === null || _d === void 0 ? void 0 : _d.startsWith("'azd' is not recognized")); + if (isNotInstallError || (obj.error && obj.error.code === "ENOENT")) { + const error = new CredentialUnavailableError("Azure Developer CLI couldn't be found. To mitigate this issue, see the troubleshooting guidelines at https://aka.ms/azsdk/js/identity/azdevclicredential/troubleshoot."); + logger$4.getToken.info(formatError(scopes, error)); + throw error; + } + if (isNotLoggedInError) { + const error = new CredentialUnavailableError("Please run 'azd auth login' from a command prompt to authenticate before using this credential. For more information, see the troubleshooting guidelines at https://aka.ms/azsdk/js/identity/azdevclicredential/troubleshoot."); + logger$4.getToken.info(formatError(scopes, error)); + throw error; + } + try { + const resp = JSON.parse(obj.stdout); + logger$4.getToken.info(formatSuccess(scopes)); + return { + token: resp.token, + expiresOnTimestamp: new Date(resp.expiresOn).getTime(), + }; + } + catch (e) { + if (obj.stderr) { + throw new CredentialUnavailableError(obj.stderr); + } + throw e; + } + } + catch (err) { + const error = err.name === "CredentialUnavailableError" + ? err + : new CredentialUnavailableError(err.message || "Unknown error while trying to retrieve the access token"); + logger$4.getToken.info(formatError(scopes, error)); + throw error; + } + }); + } +} + +// Copyright (c) Microsoft Corporation. +/** + * A shim around ManagedIdentityCredential that adapts it to accept + * `DefaultAzureCredentialOptions`. + * + * @internal + */ +class DefaultManagedIdentityCredential extends ManagedIdentityCredential { + // Constructor overload with just the other default options + // Last constructor overload with Union of all options not required since the above two constructor overloads have optional properties + constructor(options) { + var _a, _b, _c; + const managedIdentityClientId = (_a = options === null || options === void 0 ? void 0 : options.managedIdentityClientId) !== null && _a !== void 0 ? _a : process.env.AZURE_CLIENT_ID; + const workloadIdentityClientId = (_b = options === null || options === void 0 ? void 0 : options.workloadIdentityClientId) !== null && _b !== void 0 ? _b : managedIdentityClientId; + const managedResourceId = options === null || options === void 0 ? void 0 : options.managedIdentityResourceId; + const workloadFile = process.env.AZURE_FEDERATED_TOKEN_FILE; + const tenantId = (_c = options === null || options === void 0 ? void 0 : options.tenantId) !== null && _c !== void 0 ? _c : process.env.AZURE_TENANT_ID; + // ManagedIdentityCredential throws if both the resourceId and the clientId are provided. + if (managedResourceId) { + const managedIdentityResourceIdOptions = Object.assign(Object.assign({}, options), { resourceId: managedResourceId }); + super(managedIdentityResourceIdOptions); + } + else if (workloadFile && workloadIdentityClientId) { + const workloadIdentityCredentialOptions = Object.assign(Object.assign({}, options), { tenantId: tenantId }); + super(workloadIdentityClientId, workloadIdentityCredentialOptions); + } + else if (managedIdentityClientId) { + const managedIdentityClientOptions = Object.assign(Object.assign({}, options), { clientId: managedIdentityClientId }); + super(managedIdentityClientOptions); + } + else { + super(options); + } + } +} +/** + * A shim around WorkloadIdentityCredential that adapts it to accept + * `DefaultAzureCredentialOptions`. + * + * @internal + */ +class DefaultWorkloadIdentityCredential extends WorkloadIdentityCredential { + // Constructor overload with just the other default options + // Last constructor overload with Union of all options not required since the above two constructor overloads have optional properties + constructor(options) { + var _a, _b, _c; + const managedIdentityClientId = (_a = options === null || options === void 0 ? void 0 : options.managedIdentityClientId) !== null && _a !== void 0 ? _a : process.env.AZURE_CLIENT_ID; + const workloadIdentityClientId = (_b = options === null || options === void 0 ? void 0 : options.workloadIdentityClientId) !== null && _b !== void 0 ? _b : managedIdentityClientId; + const workloadFile = process.env.AZURE_FEDERATED_TOKEN_FILE; + const tenantId = (_c = options === null || options === void 0 ? void 0 : options.tenantId) !== null && _c !== void 0 ? _c : process.env.AZURE_TENANT_ID; + if (workloadFile && workloadIdentityClientId) { + const workloadIdentityCredentialOptions = Object.assign(Object.assign({}, options), { tenantId, clientId: workloadIdentityClientId, tokenFilePath: workloadFile }); + super(workloadIdentityCredentialOptions); + } + else if (tenantId) { + const workloadIdentityClientTenantOptions = Object.assign(Object.assign({}, options), { tenantId }); + super(workloadIdentityClientTenantOptions); + } + else { + super(options); + } + } +} +class DefaultAzureDeveloperCliCredential extends AzureDeveloperCliCredential { + constructor(options) { + super(Object.assign({ processTimeoutInMs: options === null || options === void 0 ? void 0 : options.processTimeoutInMs }, options)); + } +} +class DefaultAzureCliCredential extends AzureCliCredential { + constructor(options) { + super(Object.assign({ processTimeoutInMs: options === null || options === void 0 ? void 0 : options.processTimeoutInMs }, options)); + } +} +class DefaultAzurePowershellCredential extends AzurePowerShellCredential { + constructor(options) { + super(Object.assign({ processTimeoutInMs: options === null || options === void 0 ? void 0 : options.processTimeoutInMs }, options)); + } +} +const defaultCredentials = [ + EnvironmentCredential, + DefaultWorkloadIdentityCredential, + DefaultManagedIdentityCredential, + DefaultAzureCliCredential, + DefaultAzurePowershellCredential, + DefaultAzureDeveloperCliCredential, +]; +/** + * Provides a default {@link ChainedTokenCredential} configuration that should + * work for most applications that use the Azure SDK. + */ +class DefaultAzureCredential extends ChainedTokenCredential { + constructor(options) { + super(...defaultCredentials.map((ctor) => new ctor(options))); + } +} + +// Copyright (c) Microsoft Corporation. +/** + * A call to open(), but mockable + * @internal + */ +const interactiveBrowserMockable = { + open: open__default["default"], +}; +/** + * This MSAL client sets up a web server to listen for redirect callbacks, then calls to the MSAL's public application's `acquireTokenByDeviceCode` during `doGetToken` + * to trigger the authentication flow, and then respond based on the values obtained from the redirect callback + * @internal + */ +class MsalOpenBrowser extends MsalNode { + constructor(options) { + super(options); + this.logger = credentialLogger("Node.js MSAL Open Browser"); + this.redirectUri = options.redirectUri; + this.loginHint = options.loginHint; + const url = new URL(this.redirectUri); + this.port = parseInt(url.port); + if (isNaN(this.port)) { + this.port = 80; + } + this.hostname = url.hostname; + } + async acquireTokenByCode(request, enableCae) { + return this.getApp("public", enableCae).acquireTokenByCode(request); + } + doGetToken(scopes, options) { + return new Promise((resolve, reject) => { + const socketToDestroy = []; + const requestListener = (req, res) => { + var _a; + if (!req.url) { + reject(new Error(`Interactive Browser Authentication Error "Did not receive token with a valid expiration"`)); + return; + } + let url; + try { + url = new URL(req.url, this.redirectUri); + } + catch (e) { + reject(new Error(`Interactive Browser Authentication Error "Did not receive token with a valid expiration"`)); + return; + } + const tokenRequest = { + code: url.searchParams.get("code"), + redirectUri: this.redirectUri, + scopes: scopes, + authority: options === null || options === void 0 ? void 0 : options.authority, + codeVerifier: (_a = this.pkceCodes) === null || _a === void 0 ? void 0 : _a.verifier, + }; + this.acquireTokenByCode(tokenRequest, options === null || options === void 0 ? void 0 : options.enableCae) + .then((authResponse) => { + if (authResponse === null || authResponse === void 0 ? void 0 : authResponse.account) { + this.account = msalToPublic(this.clientId, authResponse.account); + } + const successMessage = `Authentication Complete. You can close the browser and return to the application.`; + if (authResponse && authResponse.expiresOn) { + const expiresOnTimestamp = authResponse === null || authResponse === void 0 ? void 0 : authResponse.expiresOn.valueOf(); + res.writeHead(200); + res.end(successMessage); + this.logger.getToken.info(formatSuccess(scopes)); + resolve({ + expiresOnTimestamp, + token: authResponse.accessToken, + }); + } + else { + const errorMessage = formatError(scopes, `${url.searchParams.get("error")}. ${url.searchParams.get("error_description")}`); + res.writeHead(500); + res.end(errorMessage); + this.logger.getToken.info(errorMessage); + reject(new Error(`Interactive Browser Authentication Error "Did not receive token with a valid expiration"`)); + } + cleanup(); + return; + }) + .catch(() => { + const errorMessage = formatError(scopes, `${url.searchParams.get("error")}. ${url.searchParams.get("error_description")}`); + res.writeHead(500); + res.end(errorMessage); + this.logger.getToken.info(errorMessage); + reject(new Error(`Interactive Browser Authentication Error "Did not receive token with a valid expiration"`)); + cleanup(); + }); + }; + const app = http__default["default"].createServer(requestListener); + const server = stoppable__default["default"](app); + const listen = app.listen(this.port, this.hostname, () => this.logger.info(`InteractiveBrowserCredential listening on port ${this.port}!`)); + function cleanup() { + if (listen) { + listen.close(); + } + for (const socket of socketToDestroy) { + socket.destroy(); + } + if (server) { + server.close(); + server.stop(); + } + } + app.on("connection", (socket) => socketToDestroy.push(socket)); + app.on("error", (err) => { + cleanup(); + const code = err.code; + if (code === "EACCES" || code === "EADDRINUSE") { + reject(new CredentialUnavailableError([ + `InteractiveBrowserCredential: Access denied to port ${this.port}.`, + `Try sending a redirect URI with a different port, as follows:`, + '`new InteractiveBrowserCredential({ redirectUri: "http://localhost:1337" })`', + ].join(" "))); + } + else { + reject(new CredentialUnavailableError(`InteractiveBrowserCredential: Failed to start the necessary web server. Error: ${err.message}`)); + } + }); + app.on("listening", () => { + const openPromise = this.openAuthCodeUrl(scopes, options); + const abortSignal = options === null || options === void 0 ? void 0 : options.abortSignal; + if (abortSignal) { + abortSignal.addEventListener("abort", () => { + cleanup(); + reject(new Error("Aborted")); + }); + } + openPromise.catch((e) => { + cleanup(); + reject(e); + }); + }); + }); + } + async openAuthCodeUrl(scopeArray, options) { + // Initialize CryptoProvider instance + const cryptoProvider = new msalNode__namespace.CryptoProvider(); + // Generate PKCE Codes before starting the authorization flow + this.pkceCodes = await cryptoProvider.generatePkceCodes(); + const authCodeUrlParameters = { + scopes: scopeArray, + correlationId: options === null || options === void 0 ? void 0 : options.correlationId, + redirectUri: this.redirectUri, + authority: options === null || options === void 0 ? void 0 : options.authority, + claims: options === null || options === void 0 ? void 0 : options.claims, + loginHint: this.loginHint, + codeChallenge: this.pkceCodes.challenge, + codeChallengeMethod: "S256", // Use SHA256 Algorithm + }; + const response = await this.getApp("public", options === null || options === void 0 ? void 0 : options.enableCae).getAuthCodeUrl(authCodeUrlParameters); + try { + // A new instance on macOS only which allows it to not hang, does not fix the issue on linux + await interactiveBrowserMockable.open(response, { wait: true, newInstance: true }); + } + catch (e) { + throw new CredentialUnavailableError(`InteractiveBrowserCredential: Could not open a browser window. Error: ${e.message}`); + } + } +} + +// Copyright (c) Microsoft Corporation. +const logger$3 = credentialLogger("InteractiveBrowserCredential"); +/** + * Enables authentication to Azure Active Directory inside of the web browser + * using the interactive login flow. + */ +class InteractiveBrowserCredential { + /** + * Creates an instance of InteractiveBrowserCredential with the details needed. + * + * This credential uses the [Authorization Code Flow](https://docs.microsoft.com/azure/active-directory/develop/v2-oauth2-auth-code-flow). + * On Node.js, it will open a browser window while it listens for a redirect response from the authentication service. + * On browsers, it authenticates via popups. The `loginStyle` optional parameter can be set to `redirect` to authenticate by redirecting the user to an Azure secure login page, which then will redirect the user back to the web application where the authentication started. + * + * For Node.js, if a `clientId` is provided, the Azure Active Directory application will need to be configured to have a "Mobile and desktop applications" redirect endpoint. + * Follow our guide on [setting up Redirect URIs for Desktop apps that calls to web APIs](https://docs.microsoft.com/azure/active-directory/develop/scenario-desktop-app-registration#redirect-uris). + * + * @param options - Options for configuring the client which makes the authentication requests. + */ + constructor(options = {}) { + const redirectUri = typeof options.redirectUri === "function" + ? options.redirectUri() + : options.redirectUri || "http://localhost"; + this.tenantId = options === null || options === void 0 ? void 0 : options.tenantId; + this.additionallyAllowedTenantIds = resolveAddionallyAllowedTenantIds(options === null || options === void 0 ? void 0 : options.additionallyAllowedTenants); + this.msalFlow = new MsalOpenBrowser(Object.assign(Object.assign({}, options), { tokenCredentialOptions: options, logger: logger$3, + redirectUri })); + this.disableAutomaticAuthentication = options === null || options === void 0 ? void 0 : options.disableAutomaticAuthentication; + } + /** + * Authenticates with Azure Active Directory and returns an access token if successful. + * If authentication fails, a {@link CredentialUnavailableError} will be thrown with the details of the failure. + * + * If the user provided the option `disableAutomaticAuthentication`, + * once the token can't be retrieved silently, + * this method won't attempt to request user interaction to retrieve the token. + * + * @param scopes - The list of scopes for which the token will have access. + * @param options - The options used to configure any requests this + * TokenCredential implementation might make. + */ + async getToken(scopes, options = {}) { + return tracingClient.withSpan(`${this.constructor.name}.getToken`, options, async (newOptions) => { + newOptions.tenantId = processMultiTenantRequest(this.tenantId, newOptions, this.additionallyAllowedTenantIds, logger$3); + const arrayScopes = ensureScopes(scopes); + return this.msalFlow.getToken(arrayScopes, Object.assign(Object.assign({}, newOptions), { disableAutomaticAuthentication: this.disableAutomaticAuthentication })); + }); + } + /** + * Authenticates with Azure Active Directory and returns an access token if successful. + * If authentication fails, a {@link CredentialUnavailableError} will be thrown with the details of the failure. + * + * If the token can't be retrieved silently, this method will require user interaction to retrieve the token. + * + * On Node.js, this credential has [Proof Key for Code Exchange (PKCE)](https://datatracker.ietf.org/doc/html/rfc7636) enabled by default. + * PKCE is a security feature that mitigates authentication code interception attacks. + * + * @param scopes - The list of scopes for which the token will have access. + * @param options - The options used to configure any requests this + * TokenCredential implementation might make. + */ + async authenticate(scopes, options = {}) { + return tracingClient.withSpan(`${this.constructor.name}.authenticate`, options, async (newOptions) => { + const arrayScopes = ensureScopes(scopes); + await this.msalFlow.getToken(arrayScopes, newOptions); + return this.msalFlow.getActiveAccount(); + }); + } +} + +// Copyright (c) Microsoft Corporation. +/** + * MSAL device code client. Calls to the MSAL's public application's `acquireTokenByDeviceCode` during `doGetToken`. + * @internal + */ +class MsalDeviceCode extends MsalNode { + constructor(options) { + super(options); + this.userPromptCallback = options.userPromptCallback; + } + async doGetToken(scopes, options) { + try { + const requestOptions = { + deviceCodeCallback: this.userPromptCallback, + scopes, + cancel: false, + correlationId: options === null || options === void 0 ? void 0 : options.correlationId, + authority: options === null || options === void 0 ? void 0 : options.authority, + claims: options === null || options === void 0 ? void 0 : options.claims, + }; + const promise = this.getApp("public", options === null || options === void 0 ? void 0 : options.enableCae).acquireTokenByDeviceCode(requestOptions); + const deviceResponse = await this.withCancellation(promise, options === null || options === void 0 ? void 0 : options.abortSignal, () => { + requestOptions.cancel = true; + }); + return this.handleResult(scopes, this.clientId, deviceResponse || undefined); + } + catch (error) { + throw this.handleError(scopes, error, options); + } + } +} + +// Copyright (c) Microsoft Corporation. +const logger$2 = credentialLogger("DeviceCodeCredential"); +/** + * Method that logs the user code from the DeviceCodeCredential. + * @param deviceCodeInfo - The device code. + */ +function defaultDeviceCodePromptCallback(deviceCodeInfo) { + console.log(deviceCodeInfo.message); +} +/** + * Enables authentication to Azure Active Directory using a device code + * that the user can enter into https://microsoft.com/devicelogin. + */ +class DeviceCodeCredential { + /** + * Creates an instance of DeviceCodeCredential with the details needed + * to initiate the device code authorization flow with Azure Active Directory. + * + * A message will be logged, giving users a code that they can use to authenticate once they go to https://microsoft.com/devicelogin + * + * Developers can configure how this message is shown by passing a custom `userPromptCallback`: + * + * ```js + * const credential = new DeviceCodeCredential({ + * tenantId: env.AZURE_TENANT_ID, + * clientId: env.AZURE_CLIENT_ID, + * userPromptCallback: (info) => { + * console.log("CUSTOMIZED PROMPT CALLBACK", info.message); + * } + * }); + * ``` + * + * @param options - Options for configuring the client which makes the authentication requests. + */ + constructor(options) { + this.tenantId = options === null || options === void 0 ? void 0 : options.tenantId; + this.additionallyAllowedTenantIds = resolveAddionallyAllowedTenantIds(options === null || options === void 0 ? void 0 : options.additionallyAllowedTenants); + this.msalFlow = new MsalDeviceCode(Object.assign(Object.assign({}, options), { logger: logger$2, userPromptCallback: (options === null || options === void 0 ? void 0 : options.userPromptCallback) || defaultDeviceCodePromptCallback, tokenCredentialOptions: options || {} })); + this.disableAutomaticAuthentication = options === null || options === void 0 ? void 0 : options.disableAutomaticAuthentication; + } + /** + * Authenticates with Azure Active Directory and returns an access token if successful. + * If authentication fails, a {@link CredentialUnavailableError} will be thrown with the details of the failure. + * + * If the user provided the option `disableAutomaticAuthentication`, + * once the token can't be retrieved silently, + * this method won't attempt to request user interaction to retrieve the token. + * + * @param scopes - The list of scopes for which the token will have access. + * @param options - The options used to configure any requests this + * TokenCredential implementation might make. + */ + async getToken(scopes, options = {}) { + return tracingClient.withSpan(`${this.constructor.name}.getToken`, options, async (newOptions) => { + newOptions.tenantId = processMultiTenantRequest(this.tenantId, newOptions, this.additionallyAllowedTenantIds, logger$2); + const arrayScopes = ensureScopes(scopes); + return this.msalFlow.getToken(arrayScopes, Object.assign(Object.assign({}, newOptions), { disableAutomaticAuthentication: this.disableAutomaticAuthentication })); + }); + } + /** + * Authenticates with Azure Active Directory and returns an access token if successful. + * If authentication fails, a {@link CredentialUnavailableError} will be thrown with the details of the failure. + * + * If the token can't be retrieved silently, this method will require user interaction to retrieve the token. + * + * @param scopes - The list of scopes for which the token will have access. + * @param options - The options used to configure any requests this + * TokenCredential implementation might make. + */ + async authenticate(scopes, options = {}) { + return tracingClient.withSpan(`${this.constructor.name}.authenticate`, options, async (newOptions) => { + const arrayScopes = Array.isArray(scopes) ? scopes : [scopes]; + await this.msalFlow.getToken(arrayScopes, newOptions); + return this.msalFlow.getActiveAccount(); + }); + } +} + +// Copyright (c) Microsoft Corporation. +/** + * This MSAL client sets up a web server to listen for redirect callbacks, then calls to the MSAL's public application's `acquireTokenByDeviceCode` during `doGetToken` + * to trigger the authentication flow, and then respond based on the values obtained from the redirect callback + * @internal + */ +class MsalAuthorizationCode extends MsalNode { + constructor(options) { + super(options); + this.logger = credentialLogger("Node.js MSAL Authorization Code"); + this.redirectUri = options.redirectUri; + this.authorizationCode = options.authorizationCode; + if (options.clientSecret) { + this.msalConfig.auth.clientSecret = options.clientSecret; + } + } + async getAuthCodeUrl(options) { + await this.init(); + return this.getApp("confidentialFirst", options.enableCae).getAuthCodeUrl({ + scopes: options.scopes, + redirectUri: options.redirectUri, + }); + } + async doGetToken(scopes, options) { + try { + const result = await this.getApp("confidentialFirst", options === null || options === void 0 ? void 0 : options.enableCae).acquireTokenByCode({ + scopes, + redirectUri: this.redirectUri, + code: this.authorizationCode, + correlationId: options === null || options === void 0 ? void 0 : options.correlationId, + authority: options === null || options === void 0 ? void 0 : options.authority, + claims: options === null || options === void 0 ? void 0 : options.claims, + }); + // The Client Credential flow does not return an account, + // so each time getToken gets called, we will have to acquire a new token through the service. + return this.handleResult(scopes, this.clientId, result || undefined); + } + catch (err) { + throw this.handleError(scopes, err, options); + } + } +} + +// Copyright (c) Microsoft Corporation. +const logger$1 = credentialLogger("AuthorizationCodeCredential"); +/** + * Enables authentication to Azure Active Directory using an authorization code + * that was obtained through the authorization code flow, described in more detail + * in the Azure Active Directory documentation: + * + * https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-auth-code-flow + */ +class AuthorizationCodeCredential { + /** + * @hidden + * @internal + */ + constructor(tenantId, clientId, clientSecretOrAuthorizationCode, authorizationCodeOrRedirectUri, redirectUriOrOptions, options) { + checkTenantId(logger$1, tenantId); + let clientSecret = clientSecretOrAuthorizationCode; + if (typeof redirectUriOrOptions === "string") { + // the clientId+clientSecret constructor + this.authorizationCode = authorizationCodeOrRedirectUri; + this.redirectUri = redirectUriOrOptions; + // in this case, options are good as they come + } + else { + // clientId only + this.authorizationCode = clientSecretOrAuthorizationCode; + this.redirectUri = authorizationCodeOrRedirectUri; + clientSecret = undefined; + options = redirectUriOrOptions; + } + // TODO: Validate tenant if provided + this.tenantId = tenantId; + this.additionallyAllowedTenantIds = resolveAddionallyAllowedTenantIds(options === null || options === void 0 ? void 0 : options.additionallyAllowedTenants); + this.msalFlow = new MsalAuthorizationCode(Object.assign(Object.assign({}, options), { clientSecret, + clientId, + tenantId, tokenCredentialOptions: options || {}, logger: logger$1, redirectUri: this.redirectUri, authorizationCode: this.authorizationCode })); + } + /** + * Authenticates with Azure Active Directory and returns an access token if successful. + * If authentication fails, a {@link CredentialUnavailableError} will be thrown with the details of the failure. + * + * @param scopes - The list of scopes for which the token will have access. + * @param options - The options used to configure any requests this + * TokenCredential implementation might make. + */ + async getToken(scopes, options = {}) { + return tracingClient.withSpan(`${this.constructor.name}.getToken`, options, async (newOptions) => { + const tenantId = processMultiTenantRequest(this.tenantId, newOptions, this.additionallyAllowedTenantIds); + newOptions.tenantId = tenantId; + const arrayScopes = ensureScopes(scopes); + return this.msalFlow.getToken(arrayScopes, Object.assign(Object.assign({}, newOptions), { disableAutomaticAuthentication: this.disableAutomaticAuthentication })); + }); + } +} + +// Copyright (c) Microsoft Corporation. +/** + * MSAL on behalf of flow. Calls to MSAL's confidential application's `acquireTokenOnBehalfOf` during `doGetToken`. + * @internal + */ +class MsalOnBehalfOf extends MsalNode { + constructor(options) { + super(options); + this.logger.info("Initialized MSAL's On-Behalf-Of flow"); + this.requiresConfidential = true; + this.userAssertionToken = options.userAssertionToken; + this.certificatePath = options.certificatePath; + this.sendCertificateChain = options.sendCertificateChain; + this.clientSecret = options.clientSecret; + } + // Changing the MSAL configuration asynchronously + async init(options) { + if (this.certificatePath) { + try { + const parts = await parseCertificate({ certificatePath: this.certificatePath }, this.sendCertificateChain); + this.msalConfig.auth.clientCertificate = { + thumbprint: parts.thumbprint, + privateKey: parts.certificateContents, + x5c: parts.x5c, + }; + } + catch (error) { + this.logger.info(formatError("", error)); + throw error; + } + } + else { + this.msalConfig.auth.clientSecret = this.clientSecret; + } + return super.init(options); + } + async doGetToken(scopes, options = {}) { + try { + const result = await this.getApp("confidential", options.enableCae).acquireTokenOnBehalfOf({ + scopes, + correlationId: options.correlationId, + authority: options.authority, + claims: options.claims, + oboAssertion: this.userAssertionToken, + }); + return this.handleResult(scopes, this.clientId, result || undefined); + } + catch (err) { + throw this.handleError(scopes, err, options); + } + } +} + +// Copyright (c) Microsoft Corporation. +const credentialName = "OnBehalfOfCredential"; +const logger = credentialLogger(credentialName); +/** + * Enables authentication to Azure Active Directory using the [On Behalf Of flow](https://docs.microsoft.com/azure/active-directory/develop/v2-oauth2-on-behalf-of-flow). + */ +class OnBehalfOfCredential { + constructor(options) { + this.options = options; + const { clientSecret } = options; + const { certificatePath } = options; + const { tenantId, clientId, userAssertionToken, additionallyAllowedTenants: additionallyAllowedTenantIds, } = options; + if (!tenantId || !clientId || !(clientSecret || certificatePath) || !userAssertionToken) { + throw new Error(`${credentialName}: tenantId, clientId, clientSecret (or certificatePath) and userAssertionToken are required parameters.`); + } + this.tenantId = tenantId; + this.additionallyAllowedTenantIds = resolveAddionallyAllowedTenantIds(additionallyAllowedTenantIds); + this.msalFlow = new MsalOnBehalfOf(Object.assign(Object.assign({}, this.options), { logger, tokenCredentialOptions: this.options })); + } + /** + * Authenticates with Azure Active Directory and returns an access token if successful. + * If authentication fails, a {@link CredentialUnavailableError} will be thrown with the details of the failure. + * + * @param scopes - The list of scopes for which the token will have access. + * @param options - The options used to configure the underlying network requests. + */ + async getToken(scopes, options = {}) { + return tracingClient.withSpan(`${credentialName}.getToken`, options, async (newOptions) => { + newOptions.tenantId = processMultiTenantRequest(this.tenantId, newOptions, this.additionallyAllowedTenantIds, logger); + const arrayScopes = ensureScopes(scopes); + return this.msalFlow.getToken(arrayScopes, newOptions); + }); + } +} + +// Copyright (c) Microsoft Corporation. +/** + * Returns a new instance of the {@link DefaultAzureCredential}. + */ +function getDefaultAzureCredential() { + return new DefaultAzureCredential(); +} + +exports.AggregateAuthenticationError = AggregateAuthenticationError; +exports.AggregateAuthenticationErrorName = AggregateAuthenticationErrorName; +exports.AuthenticationError = AuthenticationError; +exports.AuthenticationErrorName = AuthenticationErrorName; +exports.AuthenticationRequiredError = AuthenticationRequiredError; +exports.AuthorizationCodeCredential = AuthorizationCodeCredential; +exports.AzureCliCredential = AzureCliCredential; +exports.AzureDeveloperCliCredential = AzureDeveloperCliCredential; +exports.AzurePowerShellCredential = AzurePowerShellCredential; +exports.ChainedTokenCredential = ChainedTokenCredential; +exports.ClientAssertionCredential = ClientAssertionCredential; +exports.ClientCertificateCredential = ClientCertificateCredential; +exports.ClientSecretCredential = ClientSecretCredential; +exports.CredentialUnavailableError = CredentialUnavailableError; +exports.CredentialUnavailableErrorName = CredentialUnavailableErrorName; +exports.DefaultAzureCredential = DefaultAzureCredential; +exports.DeviceCodeCredential = DeviceCodeCredential; +exports.EnvironmentCredential = EnvironmentCredential; +exports.InteractiveBrowserCredential = InteractiveBrowserCredential; +exports.ManagedIdentityCredential = ManagedIdentityCredential; +exports.OnBehalfOfCredential = OnBehalfOfCredential; +exports.UsernamePasswordCredential = UsernamePasswordCredential; +exports.VisualStudioCodeCredential = VisualStudioCodeCredential; +exports.WorkloadIdentityCredential = WorkloadIdentityCredential; +exports.deserializeAuthenticationRecord = deserializeAuthenticationRecord; +exports.getDefaultAzureCredential = getDefaultAzureCredential; +exports.logger = logger$n; +exports.serializeAuthenticationRecord = serializeAuthenticationRecord; +exports.useIdentityPlugin = useIdentityPlugin; +//# sourceMappingURL=index.js.map + + +/***/ }), + +/***/ 3233: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ value: true })); + +var os = __nccwpck_require__(2037); +var util = __nccwpck_require__(3837); + +function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; } + +var util__default = /*#__PURE__*/_interopDefaultLegacy(util); + +// Copyright (c) Microsoft Corporation. +function log(message, ...args) { + process.stderr.write(`${util__default["default"].format(message, ...args)}${os.EOL}`); +} + +// Copyright (c) Microsoft Corporation. +const debugEnvVariable = (typeof process !== "undefined" && process.env && process.env.DEBUG) || undefined; +let enabledString; +let enabledNamespaces = []; +let skippedNamespaces = []; +const debuggers = []; +if (debugEnvVariable) { + enable(debugEnvVariable); +} +const debugObj = Object.assign((namespace) => { + return createDebugger(namespace); +}, { + enable, + enabled, + disable, + log, +}); +function enable(namespaces) { + enabledString = namespaces; + enabledNamespaces = []; + skippedNamespaces = []; + const wildcard = /\*/g; + const namespaceList = namespaces.split(",").map((ns) => ns.trim().replace(wildcard, ".*?")); + for (const ns of namespaceList) { + if (ns.startsWith("-")) { + skippedNamespaces.push(new RegExp(`^${ns.substr(1)}$`)); + } + else { + enabledNamespaces.push(new RegExp(`^${ns}$`)); + } + } + for (const instance of debuggers) { + instance.enabled = enabled(instance.namespace); + } +} +function enabled(namespace) { + if (namespace.endsWith("*")) { + return true; + } + for (const skipped of skippedNamespaces) { + if (skipped.test(namespace)) { + return false; + } + } + for (const enabledNamespace of enabledNamespaces) { + if (enabledNamespace.test(namespace)) { + return true; + } + } + return false; +} +function disable() { + const result = enabledString || ""; + enable(""); + return result; +} +function createDebugger(namespace) { + const newDebugger = Object.assign(debug, { + enabled: enabled(namespace), + destroy, + log: debugObj.log, + namespace, + extend, + }); + function debug(...args) { + if (!newDebugger.enabled) { + return; + } + if (args.length > 0) { + args[0] = `${namespace} ${args[0]}`; + } + newDebugger.log(...args); + } + debuggers.push(newDebugger); + return newDebugger; +} +function destroy() { + const index = debuggers.indexOf(this); + if (index >= 0) { + debuggers.splice(index, 1); + return true; + } + return false; +} +function extend(namespace) { + const newDebugger = createDebugger(`${this.namespace}:${namespace}`); + newDebugger.log = this.log; + return newDebugger; +} +var debug = debugObj; + +// Copyright (c) Microsoft Corporation. +const registeredLoggers = new Set(); +const logLevelFromEnv = (typeof process !== "undefined" && process.env && process.env.AZURE_LOG_LEVEL) || undefined; +let azureLogLevel; +/** + * The AzureLogger provides a mechanism for overriding where logs are output to. + * By default, logs are sent to stderr. + * Override the `log` method to redirect logs to another location. + */ +const AzureLogger = debug("azure"); +AzureLogger.log = (...args) => { + debug.log(...args); +}; +const AZURE_LOG_LEVELS = ["verbose", "info", "warning", "error"]; +if (logLevelFromEnv) { + // avoid calling setLogLevel because we don't want a mis-set environment variable to crash + if (isAzureLogLevel(logLevelFromEnv)) { + setLogLevel(logLevelFromEnv); + } + else { + console.error(`AZURE_LOG_LEVEL set to unknown log level '${logLevelFromEnv}'; logging is not enabled. Acceptable values: ${AZURE_LOG_LEVELS.join(", ")}.`); + } +} +/** + * Immediately enables logging at the specified log level. If no level is specified, logging is disabled. + * @param level - The log level to enable for logging. + * Options from most verbose to least verbose are: + * - verbose + * - info + * - warning + * - error + */ +function setLogLevel(level) { + if (level && !isAzureLogLevel(level)) { + throw new Error(`Unknown log level '${level}'. Acceptable values: ${AZURE_LOG_LEVELS.join(",")}`); + } + azureLogLevel = level; + const enabledNamespaces = []; + for (const logger of registeredLoggers) { + if (shouldEnable(logger)) { + enabledNamespaces.push(logger.namespace); + } + } + debug.enable(enabledNamespaces.join(",")); +} +/** + * Retrieves the currently specified log level. + */ +function getLogLevel() { + return azureLogLevel; +} +const levelMap = { + verbose: 400, + info: 300, + warning: 200, + error: 100, +}; +/** + * Creates a logger for use by the Azure SDKs that inherits from `AzureLogger`. + * @param namespace - The name of the SDK package. + * @hidden + */ +function createClientLogger(namespace) { + const clientRootLogger = AzureLogger.extend(namespace); + patchLogMethod(AzureLogger, clientRootLogger); + return { + error: createLogger(clientRootLogger, "error"), + warning: createLogger(clientRootLogger, "warning"), + info: createLogger(clientRootLogger, "info"), + verbose: createLogger(clientRootLogger, "verbose"), + }; +} +function patchLogMethod(parent, child) { + child.log = (...args) => { + parent.log(...args); + }; +} +function createLogger(parent, level) { + const logger = Object.assign(parent.extend(level), { + level, + }); + patchLogMethod(parent, logger); + if (shouldEnable(logger)) { + const enabledNamespaces = debug.disable(); + debug.enable(enabledNamespaces + "," + logger.namespace); + } + registeredLoggers.add(logger); + return logger; +} +function shouldEnable(logger) { + return Boolean(azureLogLevel && levelMap[logger.level] <= levelMap[azureLogLevel]); +} +function isAzureLogLevel(logLevel) { + return AZURE_LOG_LEVELS.includes(logLevel); +} + +exports.AzureLogger = AzureLogger; +exports.createClientLogger = createClientLogger; +exports.getLogLevel = getLogLevel; +exports.setLogLevel = setLogLevel; +//# sourceMappingURL=index.js.map + + +/***/ }), + +/***/ 5728: +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; +/*! @azure/msal-common v13.2.1 2023-08-07 */ + +'use strict'; + +Object.defineProperty(exports, "__esModule", ({ value: true })); + +/*! ***************************************************************************** +Copyright (c) Microsoft Corporation. + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +PERFORMANCE OF THIS SOFTWARE. +***************************************************************************** */ +/* global Reflect, Promise */ + +var extendStatics = function(d, b) { + extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; + return extendStatics(d, b); +}; + +function __extends(d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); +} + +var __assign = function() { + __assign = Object.assign || function __assign(t) { + for (var s, i = 1, n = arguments.length; i < n; i++) { + s = arguments[i]; + for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; + } + return t; + }; + return __assign.apply(this, arguments); +}; + +function __awaiter(thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +} + +function __generator(thisArg, body) { + var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; + return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; + function verb(n) { return function (v) { return step([n, v]); }; } + function step(op) { + if (f) throw new TypeError("Generator is already executing."); + while (_) try { + if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; + if (y = 0, t) op = [op[0] & 2, t.value]; + switch (op[0]) { + case 0: case 1: t = op; break; + case 4: _.label++; return { value: op[1], done: false }; + case 5: _.label++; y = op[1]; op = [0]; continue; + case 7: op = _.ops.pop(); _.trys.pop(); continue; + default: + if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } + if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } + if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } + if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } + if (t[2]) _.ops.pop(); + _.trys.pop(); continue; + } + op = body.call(thisArg, _); + } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } + if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; + } +} + +function __spreadArrays() { + for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length; + for (var r = Array(s), k = 0, i = 0; i < il; i++) + for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++) + r[k] = a[j]; + return r; +} + +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. + */ +var Constants = { + LIBRARY_NAME: "MSAL.JS", + SKU: "msal.js.common", + // Prefix for all library cache entries + CACHE_PREFIX: "msal", + // default authority + DEFAULT_AUTHORITY: "https://login.microsoftonline.com/common/", + DEFAULT_AUTHORITY_HOST: "login.microsoftonline.com", + DEFAULT_COMMON_TENANT: "common", + // ADFS String + ADFS: "adfs", + DSTS: "dstsv2", + // Default AAD Instance Discovery Endpoint + AAD_INSTANCE_DISCOVERY_ENDPT: "https://login.microsoftonline.com/common/discovery/instance?api-version=1.1&authorization_endpoint=", + // CIAM URL + CIAM_AUTH_URL: ".ciamlogin.com", + AAD_TENANT_DOMAIN_SUFFIX: ".onmicrosoft.com", + // Resource delimiter - used for certain cache entries + RESOURCE_DELIM: "|", + // Placeholder for non-existent account ids/objects + NO_ACCOUNT: "NO_ACCOUNT", + // Claims + CLAIMS: "claims", + // Consumer UTID + CONSUMER_UTID: "9188040d-6c67-4c5b-b112-36a304b66dad", + // Default scopes + OPENID_SCOPE: "openid", + PROFILE_SCOPE: "profile", + OFFLINE_ACCESS_SCOPE: "offline_access", + EMAIL_SCOPE: "email", + // Default response type for authorization code flow + CODE_RESPONSE_TYPE: "code", + CODE_GRANT_TYPE: "authorization_code", + RT_GRANT_TYPE: "refresh_token", + FRAGMENT_RESPONSE_MODE: "fragment", + S256_CODE_CHALLENGE_METHOD: "S256", + URL_FORM_CONTENT_TYPE: "application/x-www-form-urlencoded;charset=utf-8", + AUTHORIZATION_PENDING: "authorization_pending", + NOT_DEFINED: "not_defined", + EMPTY_STRING: "", + NOT_APPLICABLE: "N/A", + FORWARD_SLASH: "/", + IMDS_ENDPOINT: "http://169.254.169.254/metadata/instance/compute/location", + IMDS_VERSION: "2020-06-01", + IMDS_TIMEOUT: 2000, + AZURE_REGION_AUTO_DISCOVER_FLAG: "TryAutoDetect", + REGIONAL_AUTH_PUBLIC_CLOUD_SUFFIX: "login.microsoft.com", + REGIONAL_AUTH_NON_MSI_QUERY_STRING: "allowestsrnonmsi=true", + KNOWN_PUBLIC_CLOUDS: ["login.microsoftonline.com", "login.windows.net", "login.microsoft.com", "sts.windows.net"], + TOKEN_RESPONSE_TYPE: "token", + ID_TOKEN_RESPONSE_TYPE: "id_token", + SHR_NONCE_VALIDITY: 240, + INVALID_INSTANCE: "invalid_instance", +}; +var OIDC_DEFAULT_SCOPES = [ + Constants.OPENID_SCOPE, + Constants.PROFILE_SCOPE, + Constants.OFFLINE_ACCESS_SCOPE +]; +var OIDC_SCOPES = __spreadArrays(OIDC_DEFAULT_SCOPES, [ + Constants.EMAIL_SCOPE +]); +/** + * Request header names + */ +exports.HeaderNames = void 0; +(function (HeaderNames) { + HeaderNames["CONTENT_TYPE"] = "Content-Type"; + HeaderNames["RETRY_AFTER"] = "Retry-After"; + HeaderNames["CCS_HEADER"] = "X-AnchorMailbox"; + HeaderNames["WWWAuthenticate"] = "WWW-Authenticate"; + HeaderNames["AuthenticationInfo"] = "Authentication-Info"; + HeaderNames["X_MS_REQUEST_ID"] = "x-ms-request-id"; + HeaderNames["X_MS_HTTP_VERSION"] = "x-ms-httpver"; +})(exports.HeaderNames || (exports.HeaderNames = {})); +/** + * Persistent cache keys MSAL which stay while user is logged in. + */ +exports.PersistentCacheKeys = void 0; +(function (PersistentCacheKeys) { + PersistentCacheKeys["ID_TOKEN"] = "idtoken"; + PersistentCacheKeys["CLIENT_INFO"] = "client.info"; + PersistentCacheKeys["ADAL_ID_TOKEN"] = "adal.idtoken"; + PersistentCacheKeys["ERROR"] = "error"; + PersistentCacheKeys["ERROR_DESC"] = "error.description"; + PersistentCacheKeys["ACTIVE_ACCOUNT"] = "active-account"; + PersistentCacheKeys["ACTIVE_ACCOUNT_FILTERS"] = "active-account-filters"; // new cache entry for active_account for a more robust version for browser +})(exports.PersistentCacheKeys || (exports.PersistentCacheKeys = {})); +/** + * String constants related to AAD Authority + */ +var AADAuthorityConstants; +(function (AADAuthorityConstants) { + AADAuthorityConstants["COMMON"] = "common"; + AADAuthorityConstants["ORGANIZATIONS"] = "organizations"; + AADAuthorityConstants["CONSUMERS"] = "consumers"; +})(AADAuthorityConstants || (AADAuthorityConstants = {})); +/** + * Keys in the hashParams sent by AAD Server + */ +exports.AADServerParamKeys = void 0; +(function (AADServerParamKeys) { + AADServerParamKeys["CLIENT_ID"] = "client_id"; + AADServerParamKeys["REDIRECT_URI"] = "redirect_uri"; + AADServerParamKeys["RESPONSE_TYPE"] = "response_type"; + AADServerParamKeys["RESPONSE_MODE"] = "response_mode"; + AADServerParamKeys["GRANT_TYPE"] = "grant_type"; + AADServerParamKeys["CLAIMS"] = "claims"; + AADServerParamKeys["SCOPE"] = "scope"; + AADServerParamKeys["ERROR"] = "error"; + AADServerParamKeys["ERROR_DESCRIPTION"] = "error_description"; + AADServerParamKeys["ACCESS_TOKEN"] = "access_token"; + AADServerParamKeys["ID_TOKEN"] = "id_token"; + AADServerParamKeys["REFRESH_TOKEN"] = "refresh_token"; + AADServerParamKeys["EXPIRES_IN"] = "expires_in"; + AADServerParamKeys["STATE"] = "state"; + AADServerParamKeys["NONCE"] = "nonce"; + AADServerParamKeys["PROMPT"] = "prompt"; + AADServerParamKeys["SESSION_STATE"] = "session_state"; + AADServerParamKeys["CLIENT_INFO"] = "client_info"; + AADServerParamKeys["CODE"] = "code"; + AADServerParamKeys["CODE_CHALLENGE"] = "code_challenge"; + AADServerParamKeys["CODE_CHALLENGE_METHOD"] = "code_challenge_method"; + AADServerParamKeys["CODE_VERIFIER"] = "code_verifier"; + AADServerParamKeys["CLIENT_REQUEST_ID"] = "client-request-id"; + AADServerParamKeys["X_CLIENT_SKU"] = "x-client-SKU"; + AADServerParamKeys["X_CLIENT_VER"] = "x-client-VER"; + AADServerParamKeys["X_CLIENT_OS"] = "x-client-OS"; + AADServerParamKeys["X_CLIENT_CPU"] = "x-client-CPU"; + AADServerParamKeys["X_CLIENT_CURR_TELEM"] = "x-client-current-telemetry"; + AADServerParamKeys["X_CLIENT_LAST_TELEM"] = "x-client-last-telemetry"; + AADServerParamKeys["X_MS_LIB_CAPABILITY"] = "x-ms-lib-capability"; + AADServerParamKeys["X_APP_NAME"] = "x-app-name"; + AADServerParamKeys["X_APP_VER"] = "x-app-ver"; + AADServerParamKeys["POST_LOGOUT_URI"] = "post_logout_redirect_uri"; + AADServerParamKeys["ID_TOKEN_HINT"] = "id_token_hint"; + AADServerParamKeys["DEVICE_CODE"] = "device_code"; + AADServerParamKeys["CLIENT_SECRET"] = "client_secret"; + AADServerParamKeys["CLIENT_ASSERTION"] = "client_assertion"; + AADServerParamKeys["CLIENT_ASSERTION_TYPE"] = "client_assertion_type"; + AADServerParamKeys["TOKEN_TYPE"] = "token_type"; + AADServerParamKeys["REQ_CNF"] = "req_cnf"; + AADServerParamKeys["OBO_ASSERTION"] = "assertion"; + AADServerParamKeys["REQUESTED_TOKEN_USE"] = "requested_token_use"; + AADServerParamKeys["ON_BEHALF_OF"] = "on_behalf_of"; + AADServerParamKeys["FOCI"] = "foci"; + AADServerParamKeys["CCS_HEADER"] = "X-AnchorMailbox"; + AADServerParamKeys["RETURN_SPA_CODE"] = "return_spa_code"; + AADServerParamKeys["NATIVE_BROKER"] = "nativebroker"; + AADServerParamKeys["LOGOUT_HINT"] = "logout_hint"; +})(exports.AADServerParamKeys || (exports.AADServerParamKeys = {})); +/** + * Claims request keys + */ +exports.ClaimsRequestKeys = void 0; +(function (ClaimsRequestKeys) { + ClaimsRequestKeys["ACCESS_TOKEN"] = "access_token"; + ClaimsRequestKeys["XMS_CC"] = "xms_cc"; +})(exports.ClaimsRequestKeys || (exports.ClaimsRequestKeys = {})); +/** + * we considered making this "enum" in the request instead of string, however it looks like the allowed list of + * prompt values kept changing over past couple of years. There are some undocumented prompt values for some + * internal partners too, hence the choice of generic "string" type instead of the "enum" + */ +var PromptValue = { + LOGIN: "login", + SELECT_ACCOUNT: "select_account", + CONSENT: "consent", + NONE: "none", + CREATE: "create", + NO_SESSION: "no_session" +}; +/** + * SSO Types - generated to populate hints + */ +exports.SSOTypes = void 0; +(function (SSOTypes) { + SSOTypes["ACCOUNT"] = "account"; + SSOTypes["SID"] = "sid"; + SSOTypes["LOGIN_HINT"] = "login_hint"; + SSOTypes["ID_TOKEN"] = "id_token"; + SSOTypes["DOMAIN_HINT"] = "domain_hint"; + SSOTypes["ORGANIZATIONS"] = "organizations"; + SSOTypes["CONSUMERS"] = "consumers"; + SSOTypes["ACCOUNT_ID"] = "accountIdentifier"; + SSOTypes["HOMEACCOUNT_ID"] = "homeAccountIdentifier"; +})(exports.SSOTypes || (exports.SSOTypes = {})); +/** + * allowed values for codeVerifier + */ +var CodeChallengeMethodValues = { + PLAIN: "plain", + S256: "S256" +}; +/** + * The method used to encode the code verifier for the code challenge parameter. can be one + * of plain or s256. if excluded, code challenge is assumed to be plaintext. for more + * information, see the pkce rcf: https://tools.ietf.org/html/rfc7636 + */ +[ + CodeChallengeMethodValues.PLAIN, + CodeChallengeMethodValues.S256 +]; +/** + * allowed values for response_mode + */ +exports.ResponseMode = void 0; +(function (ResponseMode) { + ResponseMode["QUERY"] = "query"; + ResponseMode["FRAGMENT"] = "fragment"; + ResponseMode["FORM_POST"] = "form_post"; +})(exports.ResponseMode || (exports.ResponseMode = {})); +/** + * allowed grant_type + */ +var GrantType; +(function (GrantType) { + GrantType["IMPLICIT_GRANT"] = "implicit"; + GrantType["AUTHORIZATION_CODE_GRANT"] = "authorization_code"; + GrantType["CLIENT_CREDENTIALS_GRANT"] = "client_credentials"; + GrantType["RESOURCE_OWNER_PASSWORD_GRANT"] = "password"; + GrantType["REFRESH_TOKEN_GRANT"] = "refresh_token"; + GrantType["DEVICE_CODE_GRANT"] = "device_code"; + GrantType["JWT_BEARER"] = "urn:ietf:params:oauth:grant-type:jwt-bearer"; +})(GrantType || (GrantType = {})); +/** + * Account types in Cache + */ +exports.CacheAccountType = void 0; +(function (CacheAccountType) { + CacheAccountType["MSSTS_ACCOUNT_TYPE"] = "MSSTS"; + CacheAccountType["ADFS_ACCOUNT_TYPE"] = "ADFS"; + CacheAccountType["MSAV1_ACCOUNT_TYPE"] = "MSA"; + CacheAccountType["GENERIC_ACCOUNT_TYPE"] = "Generic"; // NTLM, Kerberos, FBA, Basic etc +})(exports.CacheAccountType || (exports.CacheAccountType = {})); +/** + * Separators used in cache + */ +var Separators; +(function (Separators) { + Separators["CACHE_KEY_SEPARATOR"] = "-"; + Separators["CLIENT_INFO_SEPARATOR"] = "."; +})(Separators || (Separators = {})); +/** + * Credential Type stored in the cache + */ +exports.CredentialType = void 0; +(function (CredentialType) { + CredentialType["ID_TOKEN"] = "IdToken"; + CredentialType["ACCESS_TOKEN"] = "AccessToken"; + CredentialType["ACCESS_TOKEN_WITH_AUTH_SCHEME"] = "AccessToken_With_AuthScheme"; + CredentialType["REFRESH_TOKEN"] = "RefreshToken"; +})(exports.CredentialType || (exports.CredentialType = {})); +/** + * Combine all cache types + */ +exports.CacheType = void 0; +(function (CacheType) { + CacheType[CacheType["ADFS"] = 1001] = "ADFS"; + CacheType[CacheType["MSA"] = 1002] = "MSA"; + CacheType[CacheType["MSSTS"] = 1003] = "MSSTS"; + CacheType[CacheType["GENERIC"] = 1004] = "GENERIC"; + CacheType[CacheType["ACCESS_TOKEN"] = 2001] = "ACCESS_TOKEN"; + CacheType[CacheType["REFRESH_TOKEN"] = 2002] = "REFRESH_TOKEN"; + CacheType[CacheType["ID_TOKEN"] = 2003] = "ID_TOKEN"; + CacheType[CacheType["APP_METADATA"] = 3001] = "APP_METADATA"; + CacheType[CacheType["UNDEFINED"] = 9999] = "UNDEFINED"; +})(exports.CacheType || (exports.CacheType = {})); +/** + * More Cache related constants + */ +var APP_METADATA = "appmetadata"; +var CLIENT_INFO = "client_info"; +var THE_FAMILY_ID = "1"; +var AUTHORITY_METADATA_CONSTANTS = { + CACHE_KEY: "authority-metadata", + REFRESH_TIME_SECONDS: 3600 * 24 // 24 Hours +}; +var AuthorityMetadataSource; +(function (AuthorityMetadataSource) { + AuthorityMetadataSource["CONFIG"] = "config"; + AuthorityMetadataSource["CACHE"] = "cache"; + AuthorityMetadataSource["NETWORK"] = "network"; + AuthorityMetadataSource["HARDCODED_VALUES"] = "hardcoded_values"; +})(AuthorityMetadataSource || (AuthorityMetadataSource = {})); +var SERVER_TELEM_CONSTANTS = { + SCHEMA_VERSION: 5, + MAX_CUR_HEADER_BYTES: 80, + MAX_LAST_HEADER_BYTES: 330, + MAX_CACHED_ERRORS: 50, + CACHE_KEY: "server-telemetry", + CATEGORY_SEPARATOR: "|", + VALUE_SEPARATOR: ",", + OVERFLOW_TRUE: "1", + OVERFLOW_FALSE: "0", + UNKNOWN_ERROR: "unknown_error" +}; +/** + * Type of the authentication request + */ +exports.AuthenticationScheme = void 0; +(function (AuthenticationScheme) { + AuthenticationScheme["BEARER"] = "Bearer"; + AuthenticationScheme["POP"] = "pop"; + AuthenticationScheme["SSH"] = "ssh-cert"; +})(exports.AuthenticationScheme || (exports.AuthenticationScheme = {})); +/** + * Constants related to throttling + */ +var ThrottlingConstants = { + // Default time to throttle RequestThumbprint in seconds + DEFAULT_THROTTLE_TIME_SECONDS: 60, + // Default maximum time to throttle in seconds, overrides what the server sends back + DEFAULT_MAX_THROTTLE_TIME_SECONDS: 3600, + // Prefix for storing throttling entries + THROTTLING_PREFIX: "throttling", + // Value assigned to the x-ms-lib-capability header to indicate to the server the library supports throttling + X_MS_LIB_CAPABILITY_VALUE: "retry-after, h429" +}; +var Errors = { + INVALID_GRANT_ERROR: "invalid_grant", + CLIENT_MISMATCH_ERROR: "client_mismatch", +}; +/** + * Password grant parameters + */ +exports.PasswordGrantConstants = void 0; +(function (PasswordGrantConstants) { + PasswordGrantConstants["username"] = "username"; + PasswordGrantConstants["password"] = "password"; +})(exports.PasswordGrantConstants || (exports.PasswordGrantConstants = {})); +/** + * Response codes + */ +var ResponseCodes; +(function (ResponseCodes) { + ResponseCodes[ResponseCodes["httpSuccess"] = 200] = "httpSuccess"; + ResponseCodes[ResponseCodes["httpBadRequest"] = 400] = "httpBadRequest"; +})(ResponseCodes || (ResponseCodes = {})); +/** + * Region Discovery Sources + */ +var RegionDiscoverySources; +(function (RegionDiscoverySources) { + RegionDiscoverySources["FAILED_AUTO_DETECTION"] = "1"; + RegionDiscoverySources["INTERNAL_CACHE"] = "2"; + RegionDiscoverySources["ENVIRONMENT_VARIABLE"] = "3"; + RegionDiscoverySources["IMDS"] = "4"; +})(RegionDiscoverySources || (RegionDiscoverySources = {})); +/** + * Region Discovery Outcomes + */ +var RegionDiscoveryOutcomes; +(function (RegionDiscoveryOutcomes) { + RegionDiscoveryOutcomes["CONFIGURED_MATCHES_DETECTED"] = "1"; + RegionDiscoveryOutcomes["CONFIGURED_NO_AUTO_DETECTION"] = "2"; + RegionDiscoveryOutcomes["CONFIGURED_NOT_DETECTED"] = "3"; + RegionDiscoveryOutcomes["AUTO_DETECTION_REQUESTED_SUCCESSFUL"] = "4"; + RegionDiscoveryOutcomes["AUTO_DETECTION_REQUESTED_FAILED"] = "5"; +})(RegionDiscoveryOutcomes || (RegionDiscoveryOutcomes = {})); +var CacheOutcome; +(function (CacheOutcome) { + CacheOutcome["NO_CACHE_HIT"] = "0"; + CacheOutcome["FORCE_REFRESH"] = "1"; + CacheOutcome["NO_CACHED_ACCESS_TOKEN"] = "2"; + CacheOutcome["CACHED_ACCESS_TOKEN_EXPIRED"] = "3"; + CacheOutcome["REFRESH_CACHED_ACCESS_TOKEN"] = "4"; + CacheOutcome["CLAIMS_REQUESTED_CACHE_SKIPPED"] = "5"; +})(CacheOutcome || (CacheOutcome = {})); +var JsonTypes; +(function (JsonTypes) { + JsonTypes["Jwt"] = "JWT"; + JsonTypes["Jwk"] = "JWK"; + JsonTypes["Pop"] = "pop"; +})(JsonTypes || (JsonTypes = {})); +var ONE_DAY_IN_MS = 86400000; + +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. + */ +/** + * AuthErrorMessage class containing string constants used by error codes and messages. + */ +var AuthErrorMessage = { + unexpectedError: { + code: "unexpected_error", + desc: "Unexpected error in authentication." + }, + postRequestFailed: { + code: "post_request_failed", + desc: "Post request failed from the network, could be a 4xx/5xx or a network unavailability. Please check the exact error code for details." + } +}; +/** + * General error class thrown by the MSAL.js library. + */ +var AuthError = /** @class */ (function (_super) { + __extends(AuthError, _super); + function AuthError(errorCode, errorMessage, suberror) { + var _this = this; + var errorString = errorMessage ? errorCode + ": " + errorMessage : errorCode; + _this = _super.call(this, errorString) || this; + Object.setPrototypeOf(_this, AuthError.prototype); + _this.errorCode = errorCode || Constants.EMPTY_STRING; + _this.errorMessage = errorMessage || Constants.EMPTY_STRING; + _this.subError = suberror || Constants.EMPTY_STRING; + _this.name = "AuthError"; + return _this; + } + AuthError.prototype.setCorrelationId = function (correlationId) { + this.correlationId = correlationId; + }; + /** + * Creates an error that is thrown when something unexpected happens in the library. + * @param errDesc + */ + AuthError.createUnexpectedError = function (errDesc) { + return new AuthError(AuthErrorMessage.unexpectedError.code, AuthErrorMessage.unexpectedError.desc + ": " + errDesc); + }; + /** + * Creates an error for post request failures. + * @param errDesc + * @returns + */ + AuthError.createPostRequestFailed = function (errDesc) { + return new AuthError(AuthErrorMessage.postRequestFailed.code, AuthErrorMessage.postRequestFailed.desc + ": " + errDesc); + }; + return AuthError; +}(Error)); + +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. + */ +var DEFAULT_CRYPTO_IMPLEMENTATION = { + createNewGuid: function () { + var notImplErr = "Crypto interface - createNewGuid() has not been implemented"; + throw AuthError.createUnexpectedError(notImplErr); + }, + base64Decode: function () { + var notImplErr = "Crypto interface - base64Decode() has not been implemented"; + throw AuthError.createUnexpectedError(notImplErr); + }, + base64Encode: function () { + var notImplErr = "Crypto interface - base64Encode() has not been implemented"; + throw AuthError.createUnexpectedError(notImplErr); + }, + generatePkceCodes: function () { + return __awaiter(this, void 0, void 0, function () { + var notImplErr; + return __generator(this, function (_a) { + notImplErr = "Crypto interface - generatePkceCodes() has not been implemented"; + throw AuthError.createUnexpectedError(notImplErr); + }); + }); + }, + getPublicKeyThumbprint: function () { + return __awaiter(this, void 0, void 0, function () { + var notImplErr; + return __generator(this, function (_a) { + notImplErr = "Crypto interface - getPublicKeyThumbprint() has not been implemented"; + throw AuthError.createUnexpectedError(notImplErr); + }); + }); + }, + removeTokenBindingKey: function () { + return __awaiter(this, void 0, void 0, function () { + var notImplErr; + return __generator(this, function (_a) { + notImplErr = "Crypto interface - removeTokenBindingKey() has not been implemented"; + throw AuthError.createUnexpectedError(notImplErr); + }); + }); + }, + clearKeystore: function () { + return __awaiter(this, void 0, void 0, function () { + var notImplErr; + return __generator(this, function (_a) { + notImplErr = "Crypto interface - clearKeystore() has not been implemented"; + throw AuthError.createUnexpectedError(notImplErr); + }); + }); + }, + signJwt: function () { + return __awaiter(this, void 0, void 0, function () { + var notImplErr; + return __generator(this, function (_a) { + notImplErr = "Crypto interface - signJwt() has not been implemented"; + throw AuthError.createUnexpectedError(notImplErr); + }); + }); + }, + hashString: function () { + return __awaiter(this, void 0, void 0, function () { + var notImplErr; + return __generator(this, function (_a) { + notImplErr = "Crypto interface - hashString() has not been implemented"; + throw AuthError.createUnexpectedError(notImplErr); + }); + }); + } +}; + +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. + */ +/** + * ClientAuthErrorMessage class containing string constants used by error codes and messages. + */ +var ClientAuthErrorMessage = { + clientInfoDecodingError: { + code: "client_info_decoding_error", + desc: "The client info could not be parsed/decoded correctly. Please review the trace to determine the root cause." + }, + clientInfoEmptyError: { + code: "client_info_empty_error", + desc: "The client info was empty. Please review the trace to determine the root cause." + }, + tokenParsingError: { + code: "token_parsing_error", + desc: "Token cannot be parsed. Please review stack trace to determine root cause." + }, + nullOrEmptyToken: { + code: "null_or_empty_token", + desc: "The token is null or empty. Please review the trace to determine the root cause." + }, + endpointResolutionError: { + code: "endpoints_resolution_error", + desc: "Error: could not resolve endpoints. Please check network and try again." + }, + networkError: { + code: "network_error", + desc: "Network request failed. Please check network trace to determine root cause." + }, + unableToGetOpenidConfigError: { + code: "openid_config_error", + desc: "Could not retrieve endpoints. Check your authority and verify the .well-known/openid-configuration endpoint returns the required endpoints." + }, + hashNotDeserialized: { + code: "hash_not_deserialized", + desc: "The hash parameters could not be deserialized. Please review the trace to determine the root cause." + }, + blankGuidGenerated: { + code: "blank_guid_generated", + desc: "The guid generated was blank. Please review the trace to determine the root cause." + }, + invalidStateError: { + code: "invalid_state", + desc: "State was not the expected format. Please check the logs to determine whether the request was sent using ProtocolUtils.setRequestState()." + }, + stateMismatchError: { + code: "state_mismatch", + desc: "State mismatch error. Please check your network. Continued requests may cause cache overflow." + }, + stateNotFoundError: { + code: "state_not_found", + desc: "State not found" + }, + nonceMismatchError: { + code: "nonce_mismatch", + desc: "Nonce mismatch error. This may be caused by a race condition in concurrent requests." + }, + nonceNotFoundError: { + code: "nonce_not_found", + desc: "nonce not found" + }, + authTimeNotFoundError: { + code: "auth_time_not_found", + desc: "Max Age was requested and the ID token is missing the auth_time variable." + + " auth_time is an optional claim and is not enabled by default - it must be enabled." + + " See https://aka.ms/msaljs/optional-claims for more information." + }, + maxAgeTranspiredError: { + code: "max_age_transpired", + desc: "Max Age is set to 0, or too much time has elapsed since the last end-user authentication." + }, + noTokensFoundError: { + code: "no_tokens_found", + desc: "No tokens were found for the given scopes, and no authorization code was passed to acquireToken. You must retrieve an authorization code before making a call to acquireToken()." + }, + multipleMatchingTokens: { + code: "multiple_matching_tokens", + desc: "The cache contains multiple tokens satisfying the requirements. " + + "Call AcquireToken again providing more requirements such as authority or account." + }, + multipleMatchingAccounts: { + code: "multiple_matching_accounts", + desc: "The cache contains multiple accounts satisfying the given parameters. Please pass more info to obtain the correct account" + }, + multipleMatchingAppMetadata: { + code: "multiple_matching_appMetadata", + desc: "The cache contains multiple appMetadata satisfying the given parameters. Please pass more info to obtain the correct appMetadata" + }, + tokenRequestCannotBeMade: { + code: "request_cannot_be_made", + desc: "Token request cannot be made without authorization code or refresh token." + }, + appendEmptyScopeError: { + code: "cannot_append_empty_scope", + desc: "Cannot append null or empty scope to ScopeSet. Please check the stack trace for more info." + }, + removeEmptyScopeError: { + code: "cannot_remove_empty_scope", + desc: "Cannot remove null or empty scope from ScopeSet. Please check the stack trace for more info." + }, + appendScopeSetError: { + code: "cannot_append_scopeset", + desc: "Cannot append ScopeSet due to error." + }, + emptyInputScopeSetError: { + code: "empty_input_scopeset", + desc: "Empty input ScopeSet cannot be processed." + }, + DeviceCodePollingCancelled: { + code: "device_code_polling_cancelled", + desc: "Caller has cancelled token endpoint polling during device code flow by setting DeviceCodeRequest.cancel = true." + }, + DeviceCodeExpired: { + code: "device_code_expired", + desc: "Device code is expired." + }, + DeviceCodeUnknownError: { + code: "device_code_unknown_error", + desc: "Device code stopped polling for unknown reasons." + }, + NoAccountInSilentRequest: { + code: "no_account_in_silent_request", + desc: "Please pass an account object, silent flow is not supported without account information" + }, + invalidCacheRecord: { + code: "invalid_cache_record", + desc: "Cache record object was null or undefined." + }, + invalidCacheEnvironment: { + code: "invalid_cache_environment", + desc: "Invalid environment when attempting to create cache entry" + }, + noAccountFound: { + code: "no_account_found", + desc: "No account found in cache for given key." + }, + CachePluginError: { + code: "no cache plugin set on CacheManager", + desc: "ICachePlugin needs to be set before using readFromStorage or writeFromStorage" + }, + noCryptoObj: { + code: "no_crypto_object", + desc: "No crypto object detected. This is required for the following operation: " + }, + invalidCacheType: { + code: "invalid_cache_type", + desc: "Invalid cache type" + }, + unexpectedAccountType: { + code: "unexpected_account_type", + desc: "Unexpected account type." + }, + unexpectedCredentialType: { + code: "unexpected_credential_type", + desc: "Unexpected credential type." + }, + invalidAssertion: { + code: "invalid_assertion", + desc: "Client assertion must meet requirements described in https://tools.ietf.org/html/rfc7515" + }, + invalidClientCredential: { + code: "invalid_client_credential", + desc: "Client credential (secret, certificate, or assertion) must not be empty when creating a confidential client. An application should at most have one credential" + }, + tokenRefreshRequired: { + code: "token_refresh_required", + desc: "Cannot return token from cache because it must be refreshed. This may be due to one of the following reasons: forceRefresh parameter is set to true, claims have been requested, there is no cached access token or it is expired." + }, + userTimeoutReached: { + code: "user_timeout_reached", + desc: "User defined timeout for device code polling reached", + }, + tokenClaimsRequired: { + code: "token_claims_cnf_required_for_signedjwt", + desc: "Cannot generate a POP jwt if the token_claims are not populated" + }, + noAuthorizationCodeFromServer: { + code: "authorization_code_missing_from_server_response", + desc: "Server response does not contain an authorization code to proceed" + }, + noAzureRegionDetected: { + code: "no_azure_region_detected", + desc: "No azure region was detected and no fallback was made available" + }, + accessTokenEntityNullError: { + code: "access_token_entity_null", + desc: "Access token entity is null, please check logs and cache to ensure a valid access token is present." + }, + bindingKeyNotRemovedError: { + code: "binding_key_not_removed", + desc: "Could not remove the credential's binding key from storage." + }, + logoutNotSupported: { + code: "end_session_endpoint_not_supported", + desc: "Provided authority does not support logout." + }, + keyIdMissing: { + code: "key_id_missing", + desc: "A keyId value is missing from the requested bound token's cache record and is required to match the token to it's stored binding key." + }, + noNetworkConnectivity: { + code: "no_network_connectivity", + desc: "No network connectivity. Check your internet connection." + }, + userCanceledError: { + code: "user_canceled", + desc: "User canceled the flow." + } +}; +/** + * Error thrown when there is an error in the client code running on the browser. + */ +var ClientAuthError = /** @class */ (function (_super) { + __extends(ClientAuthError, _super); + function ClientAuthError(errorCode, errorMessage) { + var _this = _super.call(this, errorCode, errorMessage) || this; + _this.name = "ClientAuthError"; + Object.setPrototypeOf(_this, ClientAuthError.prototype); + return _this; + } + /** + * Creates an error thrown when client info object doesn't decode correctly. + * @param caughtError + */ + ClientAuthError.createClientInfoDecodingError = function (caughtError) { + return new ClientAuthError(ClientAuthErrorMessage.clientInfoDecodingError.code, ClientAuthErrorMessage.clientInfoDecodingError.desc + " Failed with error: " + caughtError); + }; + /** + * Creates an error thrown if the client info is empty. + * @param rawClientInfo + */ + ClientAuthError.createClientInfoEmptyError = function () { + return new ClientAuthError(ClientAuthErrorMessage.clientInfoEmptyError.code, "" + ClientAuthErrorMessage.clientInfoEmptyError.desc); + }; + /** + * Creates an error thrown when the id token extraction errors out. + * @param err + */ + ClientAuthError.createTokenParsingError = function (caughtExtractionError) { + return new ClientAuthError(ClientAuthErrorMessage.tokenParsingError.code, ClientAuthErrorMessage.tokenParsingError.desc + " Failed with error: " + caughtExtractionError); + }; + /** + * Creates an error thrown when the id token string is null or empty. + * @param invalidRawTokenString + */ + ClientAuthError.createTokenNullOrEmptyError = function (invalidRawTokenString) { + return new ClientAuthError(ClientAuthErrorMessage.nullOrEmptyToken.code, ClientAuthErrorMessage.nullOrEmptyToken.desc + " Raw Token Value: " + invalidRawTokenString); + }; + /** + * Creates an error thrown when the endpoint discovery doesn't complete correctly. + */ + ClientAuthError.createEndpointDiscoveryIncompleteError = function (errDetail) { + return new ClientAuthError(ClientAuthErrorMessage.endpointResolutionError.code, ClientAuthErrorMessage.endpointResolutionError.desc + " Detail: " + errDetail); + }; + /** + * Creates an error thrown when the fetch client throws + */ + ClientAuthError.createNetworkError = function (endpoint, errDetail) { + return new ClientAuthError(ClientAuthErrorMessage.networkError.code, ClientAuthErrorMessage.networkError.desc + " | Fetch client threw: " + errDetail + " | Attempted to reach: " + endpoint.split("?")[0]); + }; + /** + * Creates an error thrown when the openid-configuration endpoint cannot be reached or does not contain the required data + */ + ClientAuthError.createUnableToGetOpenidConfigError = function (errDetail) { + return new ClientAuthError(ClientAuthErrorMessage.unableToGetOpenidConfigError.code, ClientAuthErrorMessage.unableToGetOpenidConfigError.desc + " Attempted to retrieve endpoints from: " + errDetail); + }; + /** + * Creates an error thrown when the hash cannot be deserialized. + * @param hashParamObj + */ + ClientAuthError.createHashNotDeserializedError = function (hashParamObj) { + return new ClientAuthError(ClientAuthErrorMessage.hashNotDeserialized.code, ClientAuthErrorMessage.hashNotDeserialized.desc + " Given Object: " + hashParamObj); + }; + /** + * Creates an error thrown when the state cannot be parsed. + * @param invalidState + */ + ClientAuthError.createInvalidStateError = function (invalidState, errorString) { + return new ClientAuthError(ClientAuthErrorMessage.invalidStateError.code, ClientAuthErrorMessage.invalidStateError.desc + " Invalid State: " + invalidState + ", Root Err: " + errorString); + }; + /** + * Creates an error thrown when two states do not match. + */ + ClientAuthError.createStateMismatchError = function () { + return new ClientAuthError(ClientAuthErrorMessage.stateMismatchError.code, ClientAuthErrorMessage.stateMismatchError.desc); + }; + /** + * Creates an error thrown when the state is not present + * @param missingState + */ + ClientAuthError.createStateNotFoundError = function (missingState) { + return new ClientAuthError(ClientAuthErrorMessage.stateNotFoundError.code, ClientAuthErrorMessage.stateNotFoundError.desc + ": " + missingState); + }; + /** + * Creates an error thrown when the nonce does not match. + */ + ClientAuthError.createNonceMismatchError = function () { + return new ClientAuthError(ClientAuthErrorMessage.nonceMismatchError.code, ClientAuthErrorMessage.nonceMismatchError.desc); + }; + /** + * Creates an error thrown when max_age was provided in the request, but auth_time is not in the token claims + * @param missingNonce + */ + ClientAuthError.createAuthTimeNotFoundError = function () { + return new ClientAuthError(ClientAuthErrorMessage.authTimeNotFoundError.code, ClientAuthErrorMessage.authTimeNotFoundError.desc); + }; + /** + * Creates an error thrown when too much time has elapsed since the last end-user authentication + */ + ClientAuthError.createMaxAgeTranspiredError = function () { + return new ClientAuthError(ClientAuthErrorMessage.maxAgeTranspiredError.code, ClientAuthErrorMessage.maxAgeTranspiredError.desc); + }; + /** + * Creates an error thrown when the mnonce is not present + * @param missingNonce + */ + ClientAuthError.createNonceNotFoundError = function (missingNonce) { + return new ClientAuthError(ClientAuthErrorMessage.nonceNotFoundError.code, ClientAuthErrorMessage.nonceNotFoundError.desc + ": " + missingNonce); + }; + /** + * Throws error when multiple tokens are in cache. + */ + ClientAuthError.createMultipleMatchingTokensInCacheError = function () { + return new ClientAuthError(ClientAuthErrorMessage.multipleMatchingTokens.code, ClientAuthErrorMessage.multipleMatchingTokens.desc + "."); + }; + /** + * Throws error when multiple accounts are in cache for the given params + */ + ClientAuthError.createMultipleMatchingAccountsInCacheError = function () { + return new ClientAuthError(ClientAuthErrorMessage.multipleMatchingAccounts.code, ClientAuthErrorMessage.multipleMatchingAccounts.desc); + }; + /** + * Throws error when multiple appMetada are in cache for the given clientId. + */ + ClientAuthError.createMultipleMatchingAppMetadataInCacheError = function () { + return new ClientAuthError(ClientAuthErrorMessage.multipleMatchingAppMetadata.code, ClientAuthErrorMessage.multipleMatchingAppMetadata.desc); + }; + /** + * Throws error when no auth code or refresh token is given to ServerTokenRequestParameters. + */ + ClientAuthError.createTokenRequestCannotBeMadeError = function () { + return new ClientAuthError(ClientAuthErrorMessage.tokenRequestCannotBeMade.code, ClientAuthErrorMessage.tokenRequestCannotBeMade.desc); + }; + /** + * Throws error when attempting to append a null, undefined or empty scope to a set + * @param givenScope + */ + ClientAuthError.createAppendEmptyScopeToSetError = function (givenScope) { + return new ClientAuthError(ClientAuthErrorMessage.appendEmptyScopeError.code, ClientAuthErrorMessage.appendEmptyScopeError.desc + " Given Scope: " + givenScope); + }; + /** + * Throws error when attempting to append a null, undefined or empty scope to a set + * @param givenScope + */ + ClientAuthError.createRemoveEmptyScopeFromSetError = function (givenScope) { + return new ClientAuthError(ClientAuthErrorMessage.removeEmptyScopeError.code, ClientAuthErrorMessage.removeEmptyScopeError.desc + " Given Scope: " + givenScope); + }; + /** + * Throws error when attempting to append null or empty ScopeSet. + * @param appendError + */ + ClientAuthError.createAppendScopeSetError = function (appendError) { + return new ClientAuthError(ClientAuthErrorMessage.appendScopeSetError.code, ClientAuthErrorMessage.appendScopeSetError.desc + " Detail Error: " + appendError); + }; + /** + * Throws error if ScopeSet is null or undefined. + * @param givenScopeSet + */ + ClientAuthError.createEmptyInputScopeSetError = function () { + return new ClientAuthError(ClientAuthErrorMessage.emptyInputScopeSetError.code, "" + ClientAuthErrorMessage.emptyInputScopeSetError.desc); + }; + /** + * Throws error if user sets CancellationToken.cancel = true during polling of token endpoint during device code flow + */ + ClientAuthError.createDeviceCodeCancelledError = function () { + return new ClientAuthError(ClientAuthErrorMessage.DeviceCodePollingCancelled.code, "" + ClientAuthErrorMessage.DeviceCodePollingCancelled.desc); + }; + /** + * Throws error if device code is expired + */ + ClientAuthError.createDeviceCodeExpiredError = function () { + return new ClientAuthError(ClientAuthErrorMessage.DeviceCodeExpired.code, "" + ClientAuthErrorMessage.DeviceCodeExpired.desc); + }; + /** + * Throws error if device code is expired + */ + ClientAuthError.createDeviceCodeUnknownError = function () { + return new ClientAuthError(ClientAuthErrorMessage.DeviceCodeUnknownError.code, "" + ClientAuthErrorMessage.DeviceCodeUnknownError.desc); + }; + /** + * Throws error when silent requests are made without an account object + */ + ClientAuthError.createNoAccountInSilentRequestError = function () { + return new ClientAuthError(ClientAuthErrorMessage.NoAccountInSilentRequest.code, "" + ClientAuthErrorMessage.NoAccountInSilentRequest.desc); + }; + /** + * Throws error when cache record is null or undefined. + */ + ClientAuthError.createNullOrUndefinedCacheRecord = function () { + return new ClientAuthError(ClientAuthErrorMessage.invalidCacheRecord.code, ClientAuthErrorMessage.invalidCacheRecord.desc); + }; + /** + * Throws error when provided environment is not part of the CloudDiscoveryMetadata object + */ + ClientAuthError.createInvalidCacheEnvironmentError = function () { + return new ClientAuthError(ClientAuthErrorMessage.invalidCacheEnvironment.code, ClientAuthErrorMessage.invalidCacheEnvironment.desc); + }; + /** + * Throws error when account is not found in cache. + */ + ClientAuthError.createNoAccountFoundError = function () { + return new ClientAuthError(ClientAuthErrorMessage.noAccountFound.code, ClientAuthErrorMessage.noAccountFound.desc); + }; + /** + * Throws error if ICachePlugin not set on CacheManager. + */ + ClientAuthError.createCachePluginError = function () { + return new ClientAuthError(ClientAuthErrorMessage.CachePluginError.code, "" + ClientAuthErrorMessage.CachePluginError.desc); + }; + /** + * Throws error if crypto object not found. + * @param operationName + */ + ClientAuthError.createNoCryptoObjectError = function (operationName) { + return new ClientAuthError(ClientAuthErrorMessage.noCryptoObj.code, "" + ClientAuthErrorMessage.noCryptoObj.desc + operationName); + }; + /** + * Throws error if cache type is invalid. + */ + ClientAuthError.createInvalidCacheTypeError = function () { + return new ClientAuthError(ClientAuthErrorMessage.invalidCacheType.code, "" + ClientAuthErrorMessage.invalidCacheType.desc); + }; + /** + * Throws error if unexpected account type. + */ + ClientAuthError.createUnexpectedAccountTypeError = function () { + return new ClientAuthError(ClientAuthErrorMessage.unexpectedAccountType.code, "" + ClientAuthErrorMessage.unexpectedAccountType.desc); + }; + /** + * Throws error if unexpected credential type. + */ + ClientAuthError.createUnexpectedCredentialTypeError = function () { + return new ClientAuthError(ClientAuthErrorMessage.unexpectedCredentialType.code, "" + ClientAuthErrorMessage.unexpectedCredentialType.desc); + }; + /** + * Throws error if client assertion is not valid. + */ + ClientAuthError.createInvalidAssertionError = function () { + return new ClientAuthError(ClientAuthErrorMessage.invalidAssertion.code, "" + ClientAuthErrorMessage.invalidAssertion.desc); + }; + /** + * Throws error if client assertion is not valid. + */ + ClientAuthError.createInvalidCredentialError = function () { + return new ClientAuthError(ClientAuthErrorMessage.invalidClientCredential.code, "" + ClientAuthErrorMessage.invalidClientCredential.desc); + }; + /** + * Throws error if token cannot be retrieved from cache due to refresh being required. + */ + ClientAuthError.createRefreshRequiredError = function () { + return new ClientAuthError(ClientAuthErrorMessage.tokenRefreshRequired.code, ClientAuthErrorMessage.tokenRefreshRequired.desc); + }; + /** + * Throws error if the user defined timeout is reached. + */ + ClientAuthError.createUserTimeoutReachedError = function () { + return new ClientAuthError(ClientAuthErrorMessage.userTimeoutReached.code, ClientAuthErrorMessage.userTimeoutReached.desc); + }; + /* + * Throws error if token claims are not populated for a signed jwt generation + */ + ClientAuthError.createTokenClaimsRequiredError = function () { + return new ClientAuthError(ClientAuthErrorMessage.tokenClaimsRequired.code, ClientAuthErrorMessage.tokenClaimsRequired.desc); + }; + /** + * Throws error when the authorization code is missing from the server response + */ + ClientAuthError.createNoAuthCodeInServerResponseError = function () { + return new ClientAuthError(ClientAuthErrorMessage.noAuthorizationCodeFromServer.code, ClientAuthErrorMessage.noAuthorizationCodeFromServer.desc); + }; + ClientAuthError.createBindingKeyNotRemovedError = function () { + return new ClientAuthError(ClientAuthErrorMessage.bindingKeyNotRemovedError.code, ClientAuthErrorMessage.bindingKeyNotRemovedError.desc); + }; + /** + * Thrown when logout is attempted for an authority that doesnt have an end_session_endpoint + */ + ClientAuthError.createLogoutNotSupportedError = function () { + return new ClientAuthError(ClientAuthErrorMessage.logoutNotSupported.code, ClientAuthErrorMessage.logoutNotSupported.desc); + }; + /** + * Create an error when kid attribute is missing from a PoP token's cache record + */ + ClientAuthError.createKeyIdMissingError = function () { + return new ClientAuthError(ClientAuthErrorMessage.keyIdMissing.code, ClientAuthErrorMessage.keyIdMissing.desc); + }; + /** + * Create an error when the client does not have network connectivity + */ + ClientAuthError.createNoNetworkConnectivityError = function () { + return new ClientAuthError(ClientAuthErrorMessage.noNetworkConnectivity.code, ClientAuthErrorMessage.noNetworkConnectivity.desc); + }; + /** + * Create an error when the user cancels the flow + */ + ClientAuthError.createUserCanceledError = function () { + return new ClientAuthError(ClientAuthErrorMessage.userCanceledError.code, ClientAuthErrorMessage.userCanceledError.desc); + }; + return ClientAuthError; +}(AuthError)); + +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. + */ +/** + * @hidden + */ +var StringUtils = /** @class */ (function () { + function StringUtils() { + } + /** + * decode a JWT + * + * @param authToken + */ + StringUtils.decodeAuthToken = function (authToken) { + if (StringUtils.isEmpty(authToken)) { + throw ClientAuthError.createTokenNullOrEmptyError(authToken); + } + var tokenPartsRegex = /^([^\.\s]*)\.([^\.\s]+)\.([^\.\s]*)$/; + var matches = tokenPartsRegex.exec(authToken); + if (!matches || matches.length < 4) { + throw ClientAuthError.createTokenParsingError("Given token is malformed: " + JSON.stringify(authToken)); + } + var crackedToken = { + header: matches[1], + JWSPayload: matches[2], + JWSSig: matches[3] + }; + return crackedToken; + }; + /** + * Check if a string is empty. + * + * @param str + */ + StringUtils.isEmpty = function (str) { + return (typeof str === "undefined" || !str || 0 === str.length); + }; + /** + * Check if stringified object is empty + * @param strObj + */ + StringUtils.isEmptyObj = function (strObj) { + if (strObj && !StringUtils.isEmpty(strObj)) { + try { + var obj = JSON.parse(strObj); + return Object.keys(obj).length === 0; + } + catch (e) { } + } + return true; + }; + StringUtils.startsWith = function (str, search) { + return str.indexOf(search) === 0; + }; + StringUtils.endsWith = function (str, search) { + return (str.length >= search.length) && (str.lastIndexOf(search) === (str.length - search.length)); + }; + /** + * Parses string into an object. + * + * @param query + */ + StringUtils.queryStringToObject = function (query) { + var obj = {}; + var params = query.split("&"); + var decode = function (s) { return decodeURIComponent(s.replace(/\+/g, " ")); }; + params.forEach(function (pair) { + if (pair.trim()) { + var _a = pair.split(/=(.+)/g, 2), key = _a[0], value = _a[1]; // Split on the first occurence of the '=' character + if (key && value) { + obj[decode(key)] = decode(value); + } + } + }); + return obj; + }; + /** + * Trims entries in an array. + * + * @param arr + */ + StringUtils.trimArrayEntries = function (arr) { + return arr.map(function (entry) { return entry.trim(); }); + }; + /** + * Removes empty strings from array + * @param arr + */ + StringUtils.removeEmptyStringsFromArray = function (arr) { + return arr.filter(function (entry) { + return !StringUtils.isEmpty(entry); + }); + }; + /** + * Attempts to parse a string into JSON + * @param str + */ + StringUtils.jsonParseHelper = function (str) { + try { + return JSON.parse(str); + } + catch (e) { + return null; + } + }; + /** + * Tests if a given string matches a given pattern, with support for wildcards and queries. + * @param pattern Wildcard pattern to string match. Supports "*" for wildcards and "?" for queries + * @param input String to match against + */ + StringUtils.matchPattern = function (pattern, input) { + /** + * Wildcard support: https://stackoverflow.com/a/3117248/4888559 + * Queries: replaces "?" in string with escaped "\?" for regex test + */ + var regex = new RegExp(pattern.replace(/\\/g, "\\\\").replace(/\*/g, "[^ ]*").replace(/\?/g, "\\\?")); // eslint-disable-line security/detect-non-literal-regexp + return regex.test(input); + }; + return StringUtils; +}()); + +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. + */ +/** + * Log message level. + */ +exports.LogLevel = void 0; +(function (LogLevel) { + LogLevel[LogLevel["Error"] = 0] = "Error"; + LogLevel[LogLevel["Warning"] = 1] = "Warning"; + LogLevel[LogLevel["Info"] = 2] = "Info"; + LogLevel[LogLevel["Verbose"] = 3] = "Verbose"; + LogLevel[LogLevel["Trace"] = 4] = "Trace"; +})(exports.LogLevel || (exports.LogLevel = {})); +/** + * Class which facilitates logging of messages to a specific place. + */ +var Logger = /** @class */ (function () { + function Logger(loggerOptions, packageName, packageVersion) { + // Current log level, defaults to info. + this.level = exports.LogLevel.Info; + var defaultLoggerCallback = function () { + return; + }; + var setLoggerOptions = loggerOptions || Logger.createDefaultLoggerOptions(); + this.localCallback = setLoggerOptions.loggerCallback || defaultLoggerCallback; + this.piiLoggingEnabled = setLoggerOptions.piiLoggingEnabled || false; + this.level = typeof (setLoggerOptions.logLevel) === "number" ? setLoggerOptions.logLevel : exports.LogLevel.Info; + this.correlationId = setLoggerOptions.correlationId || Constants.EMPTY_STRING; + this.packageName = packageName || Constants.EMPTY_STRING; + this.packageVersion = packageVersion || Constants.EMPTY_STRING; + } + Logger.createDefaultLoggerOptions = function () { + return { + loggerCallback: function () { + // allow users to not set loggerCallback + }, + piiLoggingEnabled: false, + logLevel: exports.LogLevel.Info + }; + }; + /** + * Create new Logger with existing configurations. + */ + Logger.prototype.clone = function (packageName, packageVersion, correlationId) { + return new Logger({ loggerCallback: this.localCallback, piiLoggingEnabled: this.piiLoggingEnabled, logLevel: this.level, correlationId: correlationId || this.correlationId }, packageName, packageVersion); + }; + /** + * Log message with required options. + */ + Logger.prototype.logMessage = function (logMessage, options) { + if ((options.logLevel > this.level) || (!this.piiLoggingEnabled && options.containsPii)) { + return; + } + var timestamp = new Date().toUTCString(); + // Add correlationId to logs if set, correlationId provided on log messages take precedence + var logHeader; + if (!StringUtils.isEmpty(options.correlationId)) { + logHeader = "[" + timestamp + "] : [" + options.correlationId + "]"; + } + else if (!StringUtils.isEmpty(this.correlationId)) { + logHeader = "[" + timestamp + "] : [" + this.correlationId + "]"; + } + else { + logHeader = "[" + timestamp + "]"; + } + var log = logHeader + " : " + this.packageName + "@" + this.packageVersion + " : " + exports.LogLevel[options.logLevel] + " - " + logMessage; + // debug(`msal:${LogLevel[options.logLevel]}${options.containsPii ? "-Pii": Constants.EMPTY_STRING}${options.context ? `:${options.context}` : Constants.EMPTY_STRING}`)(logMessage); + this.executeCallback(options.logLevel, log, options.containsPii || false); + }; + /** + * Execute callback with message. + */ + Logger.prototype.executeCallback = function (level, message, containsPii) { + if (this.localCallback) { + this.localCallback(level, message, containsPii); + } + }; + /** + * Logs error messages. + */ + Logger.prototype.error = function (message, correlationId) { + this.logMessage(message, { + logLevel: exports.LogLevel.Error, + containsPii: false, + correlationId: correlationId || Constants.EMPTY_STRING + }); + }; + /** + * Logs error messages with PII. + */ + Logger.prototype.errorPii = function (message, correlationId) { + this.logMessage(message, { + logLevel: exports.LogLevel.Error, + containsPii: true, + correlationId: correlationId || Constants.EMPTY_STRING + }); + }; + /** + * Logs warning messages. + */ + Logger.prototype.warning = function (message, correlationId) { + this.logMessage(message, { + logLevel: exports.LogLevel.Warning, + containsPii: false, + correlationId: correlationId || Constants.EMPTY_STRING + }); + }; + /** + * Logs warning messages with PII. + */ + Logger.prototype.warningPii = function (message, correlationId) { + this.logMessage(message, { + logLevel: exports.LogLevel.Warning, + containsPii: true, + correlationId: correlationId || Constants.EMPTY_STRING + }); + }; + /** + * Logs info messages. + */ + Logger.prototype.info = function (message, correlationId) { + this.logMessage(message, { + logLevel: exports.LogLevel.Info, + containsPii: false, + correlationId: correlationId || Constants.EMPTY_STRING + }); + }; + /** + * Logs info messages with PII. + */ + Logger.prototype.infoPii = function (message, correlationId) { + this.logMessage(message, { + logLevel: exports.LogLevel.Info, + containsPii: true, + correlationId: correlationId || Constants.EMPTY_STRING + }); + }; + /** + * Logs verbose messages. + */ + Logger.prototype.verbose = function (message, correlationId) { + this.logMessage(message, { + logLevel: exports.LogLevel.Verbose, + containsPii: false, + correlationId: correlationId || Constants.EMPTY_STRING + }); + }; + /** + * Logs verbose messages with PII. + */ + Logger.prototype.verbosePii = function (message, correlationId) { + this.logMessage(message, { + logLevel: exports.LogLevel.Verbose, + containsPii: true, + correlationId: correlationId || Constants.EMPTY_STRING + }); + }; + /** + * Logs trace messages. + */ + Logger.prototype.trace = function (message, correlationId) { + this.logMessage(message, { + logLevel: exports.LogLevel.Trace, + containsPii: false, + correlationId: correlationId || Constants.EMPTY_STRING + }); + }; + /** + * Logs trace messages with PII. + */ + Logger.prototype.tracePii = function (message, correlationId) { + this.logMessage(message, { + logLevel: exports.LogLevel.Trace, + containsPii: true, + correlationId: correlationId || Constants.EMPTY_STRING + }); + }; + /** + * Returns whether PII Logging is enabled or not. + */ + Logger.prototype.isPiiLoggingEnabled = function () { + return this.piiLoggingEnabled || false; + }; + return Logger; +}()); + +/* eslint-disable header/header */ +var name = "@azure/msal-common"; +var version = "13.2.1"; + +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. + */ +exports.AzureCloudInstance = void 0; +(function (AzureCloudInstance) { + // AzureCloudInstance is not specified. + AzureCloudInstance[AzureCloudInstance["None"] = 0] = "None"; + // Microsoft Azure public cloud + AzureCloudInstance["AzurePublic"] = "https://login.microsoftonline.com"; + // Microsoft PPE + AzureCloudInstance["AzurePpe"] = "https://login.windows-ppe.net"; + // Microsoft Chinese national cloud + AzureCloudInstance["AzureChina"] = "https://login.chinacloudapi.cn"; + // Microsoft German national cloud ("Black Forest") + AzureCloudInstance["AzureGermany"] = "https://login.microsoftonline.de"; + // US Government cloud + AzureCloudInstance["AzureUsGovernment"] = "https://login.microsoftonline.us"; +})(exports.AzureCloudInstance || (exports.AzureCloudInstance = {})); + +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. + */ +/** + * ClientConfigurationErrorMessage class containing string constants used by error codes and messages. + */ +var ClientConfigurationErrorMessage = { + redirectUriNotSet: { + code: "redirect_uri_empty", + desc: "A redirect URI is required for all calls, and none has been set." + }, + postLogoutUriNotSet: { + code: "post_logout_uri_empty", + desc: "A post logout redirect has not been set." + }, + claimsRequestParsingError: { + code: "claims_request_parsing_error", + desc: "Could not parse the given claims request object." + }, + authorityUriInsecure: { + code: "authority_uri_insecure", + desc: "Authority URIs must use https. Please see here for valid authority configuration options: https://docs.microsoft.com/en-us/azure/active-directory/develop/msal-js-initializing-client-applications#configuration-options" + }, + urlParseError: { + code: "url_parse_error", + desc: "URL could not be parsed into appropriate segments." + }, + urlEmptyError: { + code: "empty_url_error", + desc: "URL was empty or null." + }, + emptyScopesError: { + code: "empty_input_scopes_error", + desc: "Scopes cannot be passed as null, undefined or empty array because they are required to obtain an access token." + }, + nonArrayScopesError: { + code: "nonarray_input_scopes_error", + desc: "Scopes cannot be passed as non-array." + }, + clientIdSingleScopeError: { + code: "clientid_input_scopes_error", + desc: "Client ID can only be provided as a single scope." + }, + invalidPrompt: { + code: "invalid_prompt_value", + desc: "Supported prompt values are 'login', 'select_account', 'consent', 'create', 'none' and 'no_session'. Please see here for valid configuration options: https://azuread.github.io/microsoft-authentication-library-for-js/ref/modules/_azure_msal_common.html#commonauthorizationurlrequest", + }, + invalidClaimsRequest: { + code: "invalid_claims", + desc: "Given claims parameter must be a stringified JSON object." + }, + tokenRequestEmptyError: { + code: "token_request_empty", + desc: "Token request was empty and not found in cache." + }, + logoutRequestEmptyError: { + code: "logout_request_empty", + desc: "The logout request was null or undefined." + }, + invalidCodeChallengeMethod: { + code: "invalid_code_challenge_method", + desc: "code_challenge_method passed is invalid. Valid values are \"plain\" and \"S256\"." + }, + invalidCodeChallengeParams: { + code: "pkce_params_missing", + desc: "Both params: code_challenge and code_challenge_method are to be passed if to be sent in the request" + }, + invalidCloudDiscoveryMetadata: { + code: "invalid_cloud_discovery_metadata", + desc: "Invalid cloudDiscoveryMetadata provided. Must be a stringified JSON object containing tenant_discovery_endpoint and metadata fields" + }, + invalidAuthorityMetadata: { + code: "invalid_authority_metadata", + desc: "Invalid authorityMetadata provided. Must by a stringified JSON object containing authorization_endpoint, token_endpoint, issuer fields." + }, + untrustedAuthority: { + code: "untrusted_authority", + desc: "The provided authority is not a trusted authority. Please include this authority in the knownAuthorities config parameter." + }, + invalidAzureCloudInstance: { + code: "invalid_azure_cloud_instance", + desc: "Invalid AzureCloudInstance provided. Please refer MSAL JS docs: aks.ms/msaljs/azure_cloud_instance for valid values" + }, + missingSshJwk: { + code: "missing_ssh_jwk", + desc: "Missing sshJwk in SSH certificate request. A stringified JSON Web Key is required when using the SSH authentication scheme." + }, + missingSshKid: { + code: "missing_ssh_kid", + desc: "Missing sshKid in SSH certificate request. A string that uniquely identifies the public SSH key is required when using the SSH authentication scheme." + }, + missingNonceAuthenticationHeader: { + code: "missing_nonce_authentication_header", + desc: "Unable to find an authentication header containing server nonce. Either the Authentication-Info or WWW-Authenticate headers must be present in order to obtain a server nonce." + }, + invalidAuthenticationHeader: { + code: "invalid_authentication_header", + desc: "Invalid authentication header provided" + }, + authorityMismatch: { + code: "authority_mismatch", + desc: "Authority mismatch error. Authority provided in login request or PublicClientApplication config does not match the environment of the provided account. Please use a matching account or make an interactive request to login to this authority." + } +}; +/** + * Error thrown when there is an error in configuration of the MSAL.js library. + */ +var ClientConfigurationError = /** @class */ (function (_super) { + __extends(ClientConfigurationError, _super); + function ClientConfigurationError(errorCode, errorMessage) { + var _this = _super.call(this, errorCode, errorMessage) || this; + _this.name = "ClientConfigurationError"; + Object.setPrototypeOf(_this, ClientConfigurationError.prototype); + return _this; + } + /** + * Creates an error thrown when the redirect uri is empty (not set by caller) + */ + ClientConfigurationError.createRedirectUriEmptyError = function () { + return new ClientConfigurationError(ClientConfigurationErrorMessage.redirectUriNotSet.code, ClientConfigurationErrorMessage.redirectUriNotSet.desc); + }; + /** + * Creates an error thrown when the post-logout redirect uri is empty (not set by caller) + */ + ClientConfigurationError.createPostLogoutRedirectUriEmptyError = function () { + return new ClientConfigurationError(ClientConfigurationErrorMessage.postLogoutUriNotSet.code, ClientConfigurationErrorMessage.postLogoutUriNotSet.desc); + }; + /** + * Creates an error thrown when the claims request could not be successfully parsed + */ + ClientConfigurationError.createClaimsRequestParsingError = function (claimsRequestParseError) { + return new ClientConfigurationError(ClientConfigurationErrorMessage.claimsRequestParsingError.code, ClientConfigurationErrorMessage.claimsRequestParsingError.desc + " Given value: " + claimsRequestParseError); + }; + /** + * Creates an error thrown if authority uri is given an insecure protocol. + * @param urlString + */ + ClientConfigurationError.createInsecureAuthorityUriError = function (urlString) { + return new ClientConfigurationError(ClientConfigurationErrorMessage.authorityUriInsecure.code, ClientConfigurationErrorMessage.authorityUriInsecure.desc + " Given URI: " + urlString); + }; + /** + * Creates an error thrown if URL string does not parse into separate segments. + * @param urlString + */ + ClientConfigurationError.createUrlParseError = function (urlParseError) { + return new ClientConfigurationError(ClientConfigurationErrorMessage.urlParseError.code, ClientConfigurationErrorMessage.urlParseError.desc + " Given Error: " + urlParseError); + }; + /** + * Creates an error thrown if URL string is empty or null. + * @param urlString + */ + ClientConfigurationError.createUrlEmptyError = function () { + return new ClientConfigurationError(ClientConfigurationErrorMessage.urlEmptyError.code, ClientConfigurationErrorMessage.urlEmptyError.desc); + }; + /** + * Error thrown when scopes are empty. + * @param scopesValue + */ + ClientConfigurationError.createEmptyScopesArrayError = function () { + return new ClientConfigurationError(ClientConfigurationErrorMessage.emptyScopesError.code, "" + ClientConfigurationErrorMessage.emptyScopesError.desc); + }; + /** + * Error thrown when client id scope is not provided as single scope. + * @param inputScopes + */ + ClientConfigurationError.createClientIdSingleScopeError = function (inputScopes) { + return new ClientConfigurationError(ClientConfigurationErrorMessage.clientIdSingleScopeError.code, ClientConfigurationErrorMessage.clientIdSingleScopeError.desc + " Given Scopes: " + inputScopes); + }; + /** + * Error thrown when prompt is not an allowed type. + * @param promptValue + */ + ClientConfigurationError.createInvalidPromptError = function (promptValue) { + return new ClientConfigurationError(ClientConfigurationErrorMessage.invalidPrompt.code, ClientConfigurationErrorMessage.invalidPrompt.desc + " Given value: " + promptValue); + }; + /** + * Creates error thrown when claims parameter is not a stringified JSON object + */ + ClientConfigurationError.createInvalidClaimsRequestError = function () { + return new ClientConfigurationError(ClientConfigurationErrorMessage.invalidClaimsRequest.code, ClientConfigurationErrorMessage.invalidClaimsRequest.desc); + }; + /** + * Throws error when token request is empty and nothing cached in storage. + */ + ClientConfigurationError.createEmptyLogoutRequestError = function () { + return new ClientConfigurationError(ClientConfigurationErrorMessage.logoutRequestEmptyError.code, ClientConfigurationErrorMessage.logoutRequestEmptyError.desc); + }; + /** + * Throws error when token request is empty and nothing cached in storage. + */ + ClientConfigurationError.createEmptyTokenRequestError = function () { + return new ClientConfigurationError(ClientConfigurationErrorMessage.tokenRequestEmptyError.code, ClientConfigurationErrorMessage.tokenRequestEmptyError.desc); + }; + /** + * Throws error when an invalid code_challenge_method is passed by the user + */ + ClientConfigurationError.createInvalidCodeChallengeMethodError = function () { + return new ClientConfigurationError(ClientConfigurationErrorMessage.invalidCodeChallengeMethod.code, ClientConfigurationErrorMessage.invalidCodeChallengeMethod.desc); + }; + /** + * Throws error when both params: code_challenge and code_challenge_method are not passed together + */ + ClientConfigurationError.createInvalidCodeChallengeParamsError = function () { + return new ClientConfigurationError(ClientConfigurationErrorMessage.invalidCodeChallengeParams.code, ClientConfigurationErrorMessage.invalidCodeChallengeParams.desc); + }; + /** + * Throws an error when the user passes invalid cloudDiscoveryMetadata + */ + ClientConfigurationError.createInvalidCloudDiscoveryMetadataError = function () { + return new ClientConfigurationError(ClientConfigurationErrorMessage.invalidCloudDiscoveryMetadata.code, ClientConfigurationErrorMessage.invalidCloudDiscoveryMetadata.desc); + }; + /** + * Throws an error when the user passes invalid cloudDiscoveryMetadata + */ + ClientConfigurationError.createInvalidAuthorityMetadataError = function () { + return new ClientConfigurationError(ClientConfigurationErrorMessage.invalidAuthorityMetadata.code, ClientConfigurationErrorMessage.invalidAuthorityMetadata.desc); + }; + /** + * Throws error when provided authority is not a member of the trusted host list + */ + ClientConfigurationError.createUntrustedAuthorityError = function () { + return new ClientConfigurationError(ClientConfigurationErrorMessage.untrustedAuthority.code, ClientConfigurationErrorMessage.untrustedAuthority.desc); + }; + /** + * Throws error when the AzureCloudInstance is set to an invalid value + */ + ClientConfigurationError.createInvalidAzureCloudInstanceError = function () { + return new ClientConfigurationError(ClientConfigurationErrorMessage.invalidAzureCloudInstance.code, ClientConfigurationErrorMessage.invalidAzureCloudInstance.desc); + }; + /** + * Throws an error when the authentication scheme is set to SSH but the SSH public key is omitted from the request + */ + ClientConfigurationError.createMissingSshJwkError = function () { + return new ClientConfigurationError(ClientConfigurationErrorMessage.missingSshJwk.code, ClientConfigurationErrorMessage.missingSshJwk.desc); + }; + /** + * Throws an error when the authentication scheme is set to SSH but the SSH public key ID is omitted from the request + */ + ClientConfigurationError.createMissingSshKidError = function () { + return new ClientConfigurationError(ClientConfigurationErrorMessage.missingSshKid.code, ClientConfigurationErrorMessage.missingSshKid.desc); + }; + /** + * Throws error when provided headers don't contain a header that a server nonce can be extracted from + */ + ClientConfigurationError.createMissingNonceAuthenticationHeadersError = function () { + return new ClientConfigurationError(ClientConfigurationErrorMessage.missingNonceAuthenticationHeader.code, ClientConfigurationErrorMessage.missingNonceAuthenticationHeader.desc); + }; + /** + * Throws error when a provided header is invalid in any way + */ + ClientConfigurationError.createInvalidAuthenticationHeaderError = function (invalidHeaderName, details) { + return new ClientConfigurationError(ClientConfigurationErrorMessage.invalidAuthenticationHeader.code, ClientConfigurationErrorMessage.invalidAuthenticationHeader.desc + ". Invalid header: " + invalidHeaderName + ". Details: " + details); + }; + /** + * Create an error when the authority provided in request does not match authority provided in account or MSAL.js configuration. + */ + ClientConfigurationError.createAuthorityMismatchError = function () { + return new ClientConfigurationError(ClientConfigurationErrorMessage.authorityMismatch.code, ClientConfigurationErrorMessage.authorityMismatch.desc); + }; + return ClientConfigurationError; +}(ClientAuthError)); + +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. + */ +/** + * The ScopeSet class creates a set of scopes. Scopes are case-insensitive, unique values, so the Set object in JS makes + * the most sense to implement for this class. All scopes are trimmed and converted to lower case strings in intersection and union functions + * to ensure uniqueness of strings. + */ +var ScopeSet = /** @class */ (function () { + function ScopeSet(inputScopes) { + var _this = this; + // Filter empty string and null/undefined array items + var scopeArr = inputScopes ? StringUtils.trimArrayEntries(__spreadArrays(inputScopes)) : []; + var filteredInput = scopeArr ? StringUtils.removeEmptyStringsFromArray(scopeArr) : []; + // Validate and filter scopes (validate function throws if validation fails) + this.validateInputScopes(filteredInput); + this.scopes = new Set(); // Iterator in constructor not supported by IE11 + filteredInput.forEach(function (scope) { return _this.scopes.add(scope); }); + } + /** + * Factory method to create ScopeSet from space-delimited string + * @param inputScopeString + * @param appClientId + * @param scopesRequired + */ + ScopeSet.fromString = function (inputScopeString) { + var scopeString = inputScopeString || Constants.EMPTY_STRING; + var inputScopes = scopeString.split(" "); + return new ScopeSet(inputScopes); + }; + /** + * Creates the set of scopes to search for in cache lookups + * @param inputScopeString + * @returns + */ + ScopeSet.createSearchScopes = function (inputScopeString) { + var scopeSet = new ScopeSet(inputScopeString); + if (!scopeSet.containsOnlyOIDCScopes()) { + scopeSet.removeOIDCScopes(); + } + else { + scopeSet.removeScope(Constants.OFFLINE_ACCESS_SCOPE); + } + return scopeSet; + }; + /** + * Used to validate the scopes input parameter requested by the developer. + * @param {Array} inputScopes - Developer requested permissions. Not all scopes are guaranteed to be included in the access token returned. + * @param {boolean} scopesRequired - Boolean indicating whether the scopes array is required or not + */ + ScopeSet.prototype.validateInputScopes = function (inputScopes) { + // Check if scopes are required but not given or is an empty array + if (!inputScopes || inputScopes.length < 1) { + throw ClientConfigurationError.createEmptyScopesArrayError(); + } + }; + /** + * Check if a given scope is present in this set of scopes. + * @param scope + */ + ScopeSet.prototype.containsScope = function (scope) { + var lowerCaseScopes = this.printScopesLowerCase().split(" "); + var lowerCaseScopesSet = new ScopeSet(lowerCaseScopes); + // compare lowercase scopes + return !StringUtils.isEmpty(scope) ? lowerCaseScopesSet.scopes.has(scope.toLowerCase()) : false; + }; + /** + * Check if a set of scopes is present in this set of scopes. + * @param scopeSet + */ + ScopeSet.prototype.containsScopeSet = function (scopeSet) { + var _this = this; + if (!scopeSet || scopeSet.scopes.size <= 0) { + return false; + } + return (this.scopes.size >= scopeSet.scopes.size && scopeSet.asArray().every(function (scope) { return _this.containsScope(scope); })); + }; + /** + * Check if set of scopes contains only the defaults + */ + ScopeSet.prototype.containsOnlyOIDCScopes = function () { + var _this = this; + var defaultScopeCount = 0; + OIDC_SCOPES.forEach(function (defaultScope) { + if (_this.containsScope(defaultScope)) { + defaultScopeCount += 1; + } + }); + return this.scopes.size === defaultScopeCount; + }; + /** + * Appends single scope if passed + * @param newScope + */ + ScopeSet.prototype.appendScope = function (newScope) { + if (!StringUtils.isEmpty(newScope)) { + this.scopes.add(newScope.trim()); + } + }; + /** + * Appends multiple scopes if passed + * @param newScopes + */ + ScopeSet.prototype.appendScopes = function (newScopes) { + var _this = this; + try { + newScopes.forEach(function (newScope) { return _this.appendScope(newScope); }); + } + catch (e) { + throw ClientAuthError.createAppendScopeSetError(e); + } + }; + /** + * Removes element from set of scopes. + * @param scope + */ + ScopeSet.prototype.removeScope = function (scope) { + if (StringUtils.isEmpty(scope)) { + throw ClientAuthError.createRemoveEmptyScopeFromSetError(scope); + } + this.scopes.delete(scope.trim()); + }; + /** + * Removes default scopes from set of scopes + * Primarily used to prevent cache misses if the default scopes are not returned from the server + */ + ScopeSet.prototype.removeOIDCScopes = function () { + var _this = this; + OIDC_SCOPES.forEach(function (defaultScope) { + _this.scopes.delete(defaultScope); + }); + }; + /** + * Combines an array of scopes with the current set of scopes. + * @param otherScopes + */ + ScopeSet.prototype.unionScopeSets = function (otherScopes) { + if (!otherScopes) { + throw ClientAuthError.createEmptyInputScopeSetError(); + } + var unionScopes = new Set(); // Iterator in constructor not supported in IE11 + otherScopes.scopes.forEach(function (scope) { return unionScopes.add(scope.toLowerCase()); }); + this.scopes.forEach(function (scope) { return unionScopes.add(scope.toLowerCase()); }); + return unionScopes; + }; + /** + * Check if scopes intersect between this set and another. + * @param otherScopes + */ + ScopeSet.prototype.intersectingScopeSets = function (otherScopes) { + if (!otherScopes) { + throw ClientAuthError.createEmptyInputScopeSetError(); + } + // Do not allow OIDC scopes to be the only intersecting scopes + if (!otherScopes.containsOnlyOIDCScopes()) { + otherScopes.removeOIDCScopes(); + } + var unionScopes = this.unionScopeSets(otherScopes); + var sizeOtherScopes = otherScopes.getScopeCount(); + var sizeThisScopes = this.getScopeCount(); + var sizeUnionScopes = unionScopes.size; + return sizeUnionScopes < (sizeThisScopes + sizeOtherScopes); + }; + /** + * Returns size of set of scopes. + */ + ScopeSet.prototype.getScopeCount = function () { + return this.scopes.size; + }; + /** + * Returns the scopes as an array of string values + */ + ScopeSet.prototype.asArray = function () { + var array = []; + this.scopes.forEach(function (val) { return array.push(val); }); + return array; + }; + /** + * Prints scopes into a space-delimited string + */ + ScopeSet.prototype.printScopes = function () { + if (this.scopes) { + var scopeArr = this.asArray(); + return scopeArr.join(" "); + } + return Constants.EMPTY_STRING; + }; + /** + * Prints scopes into a space-delimited lower-case string (used for caching) + */ + ScopeSet.prototype.printScopesLowerCase = function () { + return this.printScopes().toLowerCase(); + }; + return ScopeSet; +}()); + +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. + */ +/** + * Function to build a client info object from server clientInfo string + * @param rawClientInfo + * @param crypto + */ +function buildClientInfo(rawClientInfo, crypto) { + if (StringUtils.isEmpty(rawClientInfo)) { + throw ClientAuthError.createClientInfoEmptyError(); + } + try { + var decodedClientInfo = crypto.base64Decode(rawClientInfo); + return JSON.parse(decodedClientInfo); + } + catch (e) { + throw ClientAuthError.createClientInfoDecodingError(e.message); + } +} +/** + * Function to build a client info object from cached homeAccountId string + * @param homeAccountId + */ +function buildClientInfoFromHomeAccountId(homeAccountId) { + if (StringUtils.isEmpty(homeAccountId)) { + throw ClientAuthError.createClientInfoDecodingError("Home account ID was empty."); + } + var clientInfoParts = homeAccountId.split(Separators.CLIENT_INFO_SEPARATOR, 2); + return { + uid: clientInfoParts[0], + utid: clientInfoParts.length < 2 ? Constants.EMPTY_STRING : clientInfoParts[1] + }; +} + +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. + */ +/** + * Authority types supported by MSAL. + */ +exports.AuthorityType = void 0; +(function (AuthorityType) { + AuthorityType[AuthorityType["Default"] = 0] = "Default"; + AuthorityType[AuthorityType["Adfs"] = 1] = "Adfs"; + AuthorityType[AuthorityType["Dsts"] = 2] = "Dsts"; + AuthorityType[AuthorityType["Ciam"] = 3] = "Ciam"; +})(exports.AuthorityType || (exports.AuthorityType = {})); + +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. + */ +/** + * Type that defines required and optional parameters for an Account field (based on universal cache schema implemented by all MSALs). + * + * Key : Value Schema + * + * Key: -- + * + * Value Schema: + * { + * homeAccountId: home account identifier for the auth scheme, + * environment: entity that issued the token, represented as a full host + * realm: Full tenant or organizational identifier that the account belongs to + * localAccountId: Original tenant-specific accountID, usually used for legacy cases + * username: primary username that represents the user, usually corresponds to preferred_username in the v2 endpt + * authorityType: Accounts authority type as a string + * name: Full name for the account, including given name and family name, + * clientInfo: Full base64 encoded client info received from ESTS + * lastModificationTime: last time this entity was modified in the cache + * lastModificationApp: + * idTokenClaims: Object containing claims parsed from ID token + * nativeAccountId: Account identifier on the native device + * } + */ +var AccountEntity = /** @class */ (function () { + function AccountEntity() { + } + /** + * Generate Account Id key component as per the schema: - + */ + AccountEntity.prototype.generateAccountId = function () { + var accountId = [this.homeAccountId, this.environment]; + return accountId.join(Separators.CACHE_KEY_SEPARATOR).toLowerCase(); + }; + /** + * Generate Account Cache Key as per the schema: -- + */ + AccountEntity.prototype.generateAccountKey = function () { + return AccountEntity.generateAccountCacheKey({ + homeAccountId: this.homeAccountId, + environment: this.environment, + tenantId: this.realm, + username: this.username, + localAccountId: this.localAccountId + }); + }; + /** + * returns the type of the cache (in this case account) + */ + AccountEntity.prototype.generateType = function () { + switch (this.authorityType) { + case exports.CacheAccountType.ADFS_ACCOUNT_TYPE: + return exports.CacheType.ADFS; + case exports.CacheAccountType.MSAV1_ACCOUNT_TYPE: + return exports.CacheType.MSA; + case exports.CacheAccountType.MSSTS_ACCOUNT_TYPE: + return exports.CacheType.MSSTS; + case exports.CacheAccountType.GENERIC_ACCOUNT_TYPE: + return exports.CacheType.GENERIC; + default: { + throw ClientAuthError.createUnexpectedAccountTypeError(); + } + } + }; + /** + * Returns the AccountInfo interface for this account. + */ + AccountEntity.prototype.getAccountInfo = function () { + return { + homeAccountId: this.homeAccountId, + environment: this.environment, + tenantId: this.realm, + username: this.username, + localAccountId: this.localAccountId, + name: this.name, + idTokenClaims: this.idTokenClaims, + nativeAccountId: this.nativeAccountId + }; + }; + /** + * Generates account key from interface + * @param accountInterface + */ + AccountEntity.generateAccountCacheKey = function (accountInterface) { + var accountKey = [ + accountInterface.homeAccountId, + accountInterface.environment || Constants.EMPTY_STRING, + accountInterface.tenantId || Constants.EMPTY_STRING, + ]; + return accountKey.join(Separators.CACHE_KEY_SEPARATOR).toLowerCase(); + }; + /** + * Build Account cache from IdToken, clientInfo and authority/policy. Associated with AAD. + * @param clientInfo + * @param authority + * @param idToken + * @param policy + */ + AccountEntity.createAccount = function (clientInfo, homeAccountId, idToken, authority, cloudGraphHostName, msGraphHost, environment, nativeAccountId) { + var _a, _b, _c, _d, _e, _f; + var account = new AccountEntity(); + account.authorityType = exports.CacheAccountType.MSSTS_ACCOUNT_TYPE; + account.clientInfo = clientInfo; + account.homeAccountId = homeAccountId; + account.nativeAccountId = nativeAccountId; + var env = environment || (authority && authority.getPreferredCache()); + if (!env) { + throw ClientAuthError.createInvalidCacheEnvironmentError(); + } + account.environment = env; + // non AAD scenarios can have empty realm + account.realm = ((_a = idToken === null || idToken === void 0 ? void 0 : idToken.claims) === null || _a === void 0 ? void 0 : _a.tid) || Constants.EMPTY_STRING; + if (idToken) { + account.idTokenClaims = idToken.claims; + // How do you account for MSA CID here? + account.localAccountId = ((_b = idToken === null || idToken === void 0 ? void 0 : idToken.claims) === null || _b === void 0 ? void 0 : _b.oid) || ((_c = idToken === null || idToken === void 0 ? void 0 : idToken.claims) === null || _c === void 0 ? void 0 : _c.sub) || Constants.EMPTY_STRING; + /* + * In B2C scenarios the emails claim is used instead of preferred_username and it is an array. + * In most cases it will contain a single email. This field should not be relied upon if a custom + * policy is configured to return more than 1 email. + */ + var preferredUsername = (_d = idToken === null || idToken === void 0 ? void 0 : idToken.claims) === null || _d === void 0 ? void 0 : _d.preferred_username; + var email = ((_e = idToken === null || idToken === void 0 ? void 0 : idToken.claims) === null || _e === void 0 ? void 0 : _e.emails) ? idToken.claims.emails[0] : null; + account.username = preferredUsername || email || Constants.EMPTY_STRING; + account.name = (_f = idToken === null || idToken === void 0 ? void 0 : idToken.claims) === null || _f === void 0 ? void 0 : _f.name; + } + account.cloudGraphHostName = cloudGraphHostName; + account.msGraphHost = msGraphHost; + return account; + }; + /** + * Builds non-AAD/ADFS account. + * @param authority + * @param idToken + */ + AccountEntity.createGenericAccount = function (homeAccountId, idToken, authority, cloudGraphHostName, msGraphHost, environment) { + var _a, _b, _c, _d; + var account = new AccountEntity(); + account.authorityType = (authority && + authority.authorityType === exports.AuthorityType.Adfs) ? exports.CacheAccountType.ADFS_ACCOUNT_TYPE : exports.CacheAccountType.GENERIC_ACCOUNT_TYPE; + account.homeAccountId = homeAccountId; + // non AAD scenarios can have empty realm + account.realm = Constants.EMPTY_STRING; + var env = environment || authority && authority.getPreferredCache(); + if (!env) { + throw ClientAuthError.createInvalidCacheEnvironmentError(); + } + if (idToken) { + // How do you account for MSA CID here? + account.localAccountId = ((_a = idToken === null || idToken === void 0 ? void 0 : idToken.claims) === null || _a === void 0 ? void 0 : _a.oid) || ((_b = idToken === null || idToken === void 0 ? void 0 : idToken.claims) === null || _b === void 0 ? void 0 : _b.sub) || Constants.EMPTY_STRING; + // upn claim for most ADFS scenarios + account.username = ((_c = idToken === null || idToken === void 0 ? void 0 : idToken.claims) === null || _c === void 0 ? void 0 : _c.upn) || Constants.EMPTY_STRING; + account.name = ((_d = idToken === null || idToken === void 0 ? void 0 : idToken.claims) === null || _d === void 0 ? void 0 : _d.name) || Constants.EMPTY_STRING; + account.idTokenClaims = idToken === null || idToken === void 0 ? void 0 : idToken.claims; + } + account.environment = env; + account.cloudGraphHostName = cloudGraphHostName; + account.msGraphHost = msGraphHost; + /* + * add uniqueName to claims + * account.name = idToken.claims.uniqueName; + */ + return account; + }; + /** + * Generate HomeAccountId from server response + * @param serverClientInfo + * @param authType + */ + AccountEntity.generateHomeAccountId = function (serverClientInfo, authType, logger, cryptoObj, idToken) { + var _a; + var accountId = ((_a = idToken === null || idToken === void 0 ? void 0 : idToken.claims) === null || _a === void 0 ? void 0 : _a.sub) ? idToken.claims.sub : Constants.EMPTY_STRING; + // since ADFS does not have tid and does not set client_info + if (authType === exports.AuthorityType.Adfs || authType === exports.AuthorityType.Dsts) { + return accountId; + } + // for cases where there is clientInfo + if (serverClientInfo) { + try { + var clientInfo = buildClientInfo(serverClientInfo, cryptoObj); + if (!StringUtils.isEmpty(clientInfo.uid) && !StringUtils.isEmpty(clientInfo.utid)) { + return "" + clientInfo.uid + Separators.CLIENT_INFO_SEPARATOR + clientInfo.utid; + } + } + catch (e) { } + } + // default to "sub" claim + logger.verbose("No client info in response"); + return accountId; + }; + /** + * Validates an entity: checks for all expected params + * @param entity + */ + AccountEntity.isAccountEntity = function (entity) { + if (!entity) { + return false; + } + return (entity.hasOwnProperty("homeAccountId") && + entity.hasOwnProperty("environment") && + entity.hasOwnProperty("realm") && + entity.hasOwnProperty("localAccountId") && + entity.hasOwnProperty("username") && + entity.hasOwnProperty("authorityType")); + }; + /** + * Helper function to determine whether 2 accountInfo objects represent the same account + * @param accountA + * @param accountB + * @param compareClaims - If set to true idTokenClaims will also be compared to determine account equality + */ + AccountEntity.accountInfoIsEqual = function (accountA, accountB, compareClaims) { + if (!accountA || !accountB) { + return false; + } + var claimsMatch = true; // default to true so as to not fail comparison below if compareClaims: false + if (compareClaims) { + var accountAClaims = (accountA.idTokenClaims || {}); + var accountBClaims = (accountB.idTokenClaims || {}); + // issued at timestamp and nonce are expected to change each time a new id token is acquired + claimsMatch = (accountAClaims.iat === accountBClaims.iat) && + (accountAClaims.nonce === accountBClaims.nonce); + } + return (accountA.homeAccountId === accountB.homeAccountId) && + (accountA.localAccountId === accountB.localAccountId) && + (accountA.username === accountB.username) && + (accountA.tenantId === accountB.tenantId) && + (accountA.environment === accountB.environment) && + (accountA.nativeAccountId === accountB.nativeAccountId) && + claimsMatch; + }; + return AccountEntity; +}()); + +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. + */ +/** + * JWT Token representation class. Parses token string and generates claims object. + */ +var AuthToken = /** @class */ (function () { + function AuthToken(rawToken, crypto) { + if (StringUtils.isEmpty(rawToken)) { + throw ClientAuthError.createTokenNullOrEmptyError(rawToken); + } + this.rawToken = rawToken; + this.claims = AuthToken.extractTokenClaims(rawToken, crypto); + } + /** + * Extract token by decoding the rawToken + * + * @param encodedToken + */ + AuthToken.extractTokenClaims = function (encodedToken, crypto) { + var decodedToken = StringUtils.decodeAuthToken(encodedToken); + // token will be decoded to get the username + try { + var base64TokenPayload = decodedToken.JWSPayload; + // base64Decode() should throw an error if there is an issue + var base64Decoded = crypto.base64Decode(base64TokenPayload); + return JSON.parse(base64Decoded); + } + catch (err) { + throw ClientAuthError.createTokenParsingError(err); + } + }; + /** + * Determine if the token's max_age has transpired + */ + AuthToken.checkMaxAge = function (authTime, maxAge) { + /* + * per https://openid.net/specs/openid-connect-core-1_0.html#AuthRequest + * To force an immediate re-authentication: If an app requires that a user re-authenticate prior to access, + * provide a value of 0 for the max_age parameter and the AS will force a fresh login. + */ + var fiveMinuteSkew = 300000; // five minutes in milliseconds + if ((maxAge === 0) || ((Date.now() - fiveMinuteSkew) > (authTime + maxAge))) { + throw ClientAuthError.createMaxAgeTranspiredError(); + } + }; + return AuthToken; +}()); + +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. + */ +/** + * Interface class which implement cache storage functions used by MSAL to perform validity checks, and store tokens. + */ +var CacheManager = /** @class */ (function () { + function CacheManager(clientId, cryptoImpl, logger) { + this.clientId = clientId; + this.cryptoImpl = cryptoImpl; + this.commonLogger = logger.clone(name, version); + } + /** + * Returns all accounts in cache + */ + CacheManager.prototype.getAllAccounts = function () { + var _this = this; + var allAccountKeys = this.getAccountKeys(); + if (allAccountKeys.length < 1) { + return []; + } + var accountEntities = allAccountKeys.reduce(function (accounts, key) { + var entity = _this.getAccount(key); + if (!entity) { + return accounts; + } + accounts.push(entity); + return accounts; + }, []); + if (accountEntities.length < 1) { + return []; + } + else { + var allAccounts = accountEntities.map(function (accountEntity) { + return _this.getAccountInfoFromEntity(accountEntity); + }); + return allAccounts; + } + }; + /** + * Gets accountInfo object based on provided filters + */ + CacheManager.prototype.getAccountInfoFilteredBy = function (accountFilter) { + var allAccounts = this.getAccountsFilteredBy(accountFilter); + if (allAccounts.length > 0) { + return this.getAccountInfoFromEntity(allAccounts[0]); + } + else { + return null; + } + }; + CacheManager.prototype.getAccountInfoFromEntity = function (accountEntity) { + var accountInfo = accountEntity.getAccountInfo(); + var idToken = this.getIdToken(accountInfo); + if (idToken) { + accountInfo.idToken = idToken.secret; + accountInfo.idTokenClaims = new AuthToken(idToken.secret, this.cryptoImpl).claims; + } + return accountInfo; + }; + /** + * saves a cache record + * @param cacheRecord + */ + CacheManager.prototype.saveCacheRecord = function (cacheRecord) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + if (!cacheRecord) { + throw ClientAuthError.createNullOrUndefinedCacheRecord(); + } + if (!!cacheRecord.account) { + this.setAccount(cacheRecord.account); + } + if (!!cacheRecord.idToken) { + this.setIdTokenCredential(cacheRecord.idToken); + } + if (!!!cacheRecord.accessToken) return [3 /*break*/, 2]; + return [4 /*yield*/, this.saveAccessToken(cacheRecord.accessToken)]; + case 1: + _a.sent(); + _a.label = 2; + case 2: + if (!!cacheRecord.refreshToken) { + this.setRefreshTokenCredential(cacheRecord.refreshToken); + } + if (!!cacheRecord.appMetadata) { + this.setAppMetadata(cacheRecord.appMetadata); + } + return [2 /*return*/]; + } + }); + }); + }; + /** + * saves access token credential + * @param credential + */ + CacheManager.prototype.saveAccessToken = function (credential) { + return __awaiter(this, void 0, void 0, function () { + var accessTokenFilter, tokenKeys, currentScopes, removedAccessTokens; + var _this = this; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + accessTokenFilter = { + clientId: credential.clientId, + credentialType: credential.credentialType, + environment: credential.environment, + homeAccountId: credential.homeAccountId, + realm: credential.realm, + tokenType: credential.tokenType, + requestedClaimsHash: credential.requestedClaimsHash + }; + tokenKeys = this.getTokenKeys(); + currentScopes = ScopeSet.fromString(credential.target); + removedAccessTokens = []; + tokenKeys.accessToken.forEach(function (key) { + if (!_this.accessTokenKeyMatchesFilter(key, accessTokenFilter, false)) { + return; + } + var tokenEntity = _this.getAccessTokenCredential(key); + if (tokenEntity && _this.credentialMatchesFilter(tokenEntity, accessTokenFilter)) { + var tokenScopeSet = ScopeSet.fromString(tokenEntity.target); + if (tokenScopeSet.intersectingScopeSets(currentScopes)) { + removedAccessTokens.push(_this.removeAccessToken(key)); + } + } + }); + return [4 /*yield*/, Promise.all(removedAccessTokens)]; + case 1: + _a.sent(); + this.setAccessTokenCredential(credential); + return [2 /*return*/]; + } + }); + }); + }; + /** + * retrieve accounts matching all provided filters; if no filter is set, get all accounts + * not checking for casing as keys are all generated in lower case, remember to convert to lower case if object properties are compared + * @param homeAccountId + * @param environment + * @param realm + */ + CacheManager.prototype.getAccountsFilteredBy = function (accountFilter) { + var _this = this; + var allAccountKeys = this.getAccountKeys(); + var matchingAccounts = []; + allAccountKeys.forEach(function (cacheKey) { + if (!_this.isAccountKey(cacheKey, accountFilter.homeAccountId, accountFilter.realm)) { + // Don't parse value if the key doesn't match the account filters + return; + } + var entity = _this.getAccount(cacheKey); + if (!entity) { + return; + } + if (!!accountFilter.homeAccountId && !_this.matchHomeAccountId(entity, accountFilter.homeAccountId)) { + return; + } + if (!!accountFilter.localAccountId && !_this.matchLocalAccountId(entity, accountFilter.localAccountId)) { + return; + } + if (!!accountFilter.username && !_this.matchUsername(entity, accountFilter.username)) { + return; + } + if (!!accountFilter.environment && !_this.matchEnvironment(entity, accountFilter.environment)) { + return; + } + if (!!accountFilter.realm && !_this.matchRealm(entity, accountFilter.realm)) { + return; + } + if (!!accountFilter.nativeAccountId && !_this.matchNativeAccountId(entity, accountFilter.nativeAccountId)) { + return; + } + matchingAccounts.push(entity); + }); + return matchingAccounts; + }; + /** + * Returns true if the given key matches our account key schema. Also matches homeAccountId and/or tenantId if provided + * @param key + * @param homeAccountId + * @param tenantId + * @returns + */ + CacheManager.prototype.isAccountKey = function (key, homeAccountId, tenantId) { + if (key.split(Separators.CACHE_KEY_SEPARATOR).length < 3) { + // Account cache keys contain 3 items separated by '-' (each item may also contain '-') + return false; + } + if (homeAccountId && !key.toLowerCase().includes(homeAccountId.toLowerCase())) { + return false; + } + if (tenantId && !key.toLowerCase().includes(tenantId.toLowerCase())) { + return false; + } + // Do not check environment as aliasing can cause false negatives + return true; + }; + /** + * Returns true if the given key matches our credential key schema. + * @param key + */ + CacheManager.prototype.isCredentialKey = function (key) { + if (key.split(Separators.CACHE_KEY_SEPARATOR).length < 6) { + // Credential cache keys contain 6 items separated by '-' (each item may also contain '-') + return false; + } + var lowerCaseKey = key.toLowerCase(); + // Credential keys must indicate what credential type they represent + if (lowerCaseKey.indexOf(exports.CredentialType.ID_TOKEN.toLowerCase()) === -1 && + lowerCaseKey.indexOf(exports.CredentialType.ACCESS_TOKEN.toLowerCase()) === -1 && + lowerCaseKey.indexOf(exports.CredentialType.ACCESS_TOKEN_WITH_AUTH_SCHEME.toLowerCase()) === -1 && + lowerCaseKey.indexOf(exports.CredentialType.REFRESH_TOKEN.toLowerCase()) === -1) { + return false; + } + if (lowerCaseKey.indexOf(exports.CredentialType.REFRESH_TOKEN.toLowerCase()) > -1) { + // Refresh tokens must contain the client id or family id + var clientIdValidation = "" + exports.CredentialType.REFRESH_TOKEN + Separators.CACHE_KEY_SEPARATOR + this.clientId + Separators.CACHE_KEY_SEPARATOR; + var familyIdValidation = "" + exports.CredentialType.REFRESH_TOKEN + Separators.CACHE_KEY_SEPARATOR + THE_FAMILY_ID + Separators.CACHE_KEY_SEPARATOR; + if (lowerCaseKey.indexOf(clientIdValidation.toLowerCase()) === -1 && lowerCaseKey.indexOf(familyIdValidation.toLowerCase()) === -1) { + return false; + } + } + else if (lowerCaseKey.indexOf(this.clientId.toLowerCase()) === -1) { + // Tokens must contain the clientId + return false; + } + return true; + }; + /** + * Returns whether or not the given credential entity matches the filter + * @param entity + * @param filter + * @returns + */ + CacheManager.prototype.credentialMatchesFilter = function (entity, filter) { + if (!!filter.clientId && !this.matchClientId(entity, filter.clientId)) { + return false; + } + if (!!filter.userAssertionHash && !this.matchUserAssertionHash(entity, filter.userAssertionHash)) { + return false; + } + /* + * homeAccountId can be undefined, and we want to filter out cached items that have a homeAccountId of "" + * because we don't want a client_credential request to return a cached token that has a homeAccountId + */ + if ((typeof filter.homeAccountId === "string") && !this.matchHomeAccountId(entity, filter.homeAccountId)) { + return false; + } + if (!!filter.environment && !this.matchEnvironment(entity, filter.environment)) { + return false; + } + if (!!filter.realm && !this.matchRealm(entity, filter.realm)) { + return false; + } + if (!!filter.credentialType && !this.matchCredentialType(entity, filter.credentialType)) { + return false; + } + if (!!filter.familyId && !this.matchFamilyId(entity, filter.familyId)) { + return false; + } + /* + * idTokens do not have "target", target specific refreshTokens do exist for some types of authentication + * Resource specific refresh tokens case will be added when the support is deemed necessary + */ + if (!!filter.target && !this.matchTarget(entity, filter.target)) { + return false; + } + // If request OR cached entity has requested Claims Hash, check if they match + if (filter.requestedClaimsHash || entity.requestedClaimsHash) { + // Don't match if either is undefined or they are different + if (entity.requestedClaimsHash !== filter.requestedClaimsHash) { + return false; + } + } + // Access Token with Auth Scheme specific matching + if (entity.credentialType === exports.CredentialType.ACCESS_TOKEN_WITH_AUTH_SCHEME) { + if (!!filter.tokenType && !this.matchTokenType(entity, filter.tokenType)) { + return false; + } + // KeyId (sshKid) in request must match cached SSH certificate keyId because SSH cert is bound to a specific key + if (filter.tokenType === exports.AuthenticationScheme.SSH) { + if (filter.keyId && !this.matchKeyId(entity, filter.keyId)) { + return false; + } + } + } + return true; + }; + /** + * retrieve appMetadata matching all provided filters; if no filter is set, get all appMetadata + * @param filter + */ + CacheManager.prototype.getAppMetadataFilteredBy = function (filter) { + return this.getAppMetadataFilteredByInternal(filter.environment, filter.clientId); + }; + /** + * Support function to help match appMetadata + * @param environment + * @param clientId + */ + CacheManager.prototype.getAppMetadataFilteredByInternal = function (environment, clientId) { + var _this = this; + var allCacheKeys = this.getKeys(); + var matchingAppMetadata = {}; + allCacheKeys.forEach(function (cacheKey) { + // don't parse any non-appMetadata type cache entities + if (!_this.isAppMetadata(cacheKey)) { + return; + } + // Attempt retrieval + var entity = _this.getAppMetadata(cacheKey); + if (!entity) { + return; + } + if (!!environment && !_this.matchEnvironment(entity, environment)) { + return; + } + if (!!clientId && !_this.matchClientId(entity, clientId)) { + return; + } + matchingAppMetadata[cacheKey] = entity; + }); + return matchingAppMetadata; + }; + /** + * retrieve authorityMetadata that contains a matching alias + * @param filter + */ + CacheManager.prototype.getAuthorityMetadataByAlias = function (host) { + var _this = this; + var allCacheKeys = this.getAuthorityMetadataKeys(); + var matchedEntity = null; + allCacheKeys.forEach(function (cacheKey) { + // don't parse any non-authorityMetadata type cache entities + if (!_this.isAuthorityMetadata(cacheKey) || cacheKey.indexOf(_this.clientId) === -1) { + return; + } + // Attempt retrieval + var entity = _this.getAuthorityMetadata(cacheKey); + if (!entity) { + return; + } + if (entity.aliases.indexOf(host) === -1) { + return; + } + matchedEntity = entity; + }); + return matchedEntity; + }; + /** + * Removes all accounts and related tokens from cache. + */ + CacheManager.prototype.removeAllAccounts = function () { + return __awaiter(this, void 0, void 0, function () { + var allAccountKeys, removedAccounts; + var _this = this; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + allAccountKeys = this.getAccountKeys(); + removedAccounts = []; + allAccountKeys.forEach(function (cacheKey) { + removedAccounts.push(_this.removeAccount(cacheKey)); + }); + return [4 /*yield*/, Promise.all(removedAccounts)]; + case 1: + _a.sent(); + return [2 /*return*/]; + } + }); + }); + }; + /** + * Removes the account and related tokens for a given account key + * @param account + */ + CacheManager.prototype.removeAccount = function (accountKey) { + return __awaiter(this, void 0, void 0, function () { + var account; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + account = this.getAccount(accountKey); + if (!account) { + throw ClientAuthError.createNoAccountFoundError(); + } + return [4 /*yield*/, this.removeAccountContext(account)]; + case 1: + _a.sent(); + this.removeItem(accountKey); + return [2 /*return*/]; + } + }); + }); + }; + /** + * Removes credentials associated with the provided account + * @param account + */ + CacheManager.prototype.removeAccountContext = function (account) { + return __awaiter(this, void 0, void 0, function () { + var allTokenKeys, accountId, removedCredentials; + var _this = this; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + allTokenKeys = this.getTokenKeys(); + accountId = account.generateAccountId(); + removedCredentials = []; + allTokenKeys.idToken.forEach(function (key) { + if (key.indexOf(accountId) === 0) { + _this.removeIdToken(key); + } + }); + allTokenKeys.accessToken.forEach(function (key) { + if (key.indexOf(accountId) === 0) { + removedCredentials.push(_this.removeAccessToken(key)); + } + }); + allTokenKeys.refreshToken.forEach(function (key) { + if (key.indexOf(accountId) === 0) { + _this.removeRefreshToken(key); + } + }); + return [4 /*yield*/, Promise.all(removedCredentials)]; + case 1: + _a.sent(); + return [2 /*return*/]; + } + }); + }); + }; + /** + * returns a boolean if the given credential is removed + * @param credential + */ + CacheManager.prototype.removeAccessToken = function (key) { + return __awaiter(this, void 0, void 0, function () { + var credential, accessTokenWithAuthSchemeEntity, kid; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + credential = this.getAccessTokenCredential(key); + if (!credential) { + return [2 /*return*/]; + } + if (!(credential.credentialType.toLowerCase() === exports.CredentialType.ACCESS_TOKEN_WITH_AUTH_SCHEME.toLowerCase())) return [3 /*break*/, 4]; + if (!(credential.tokenType === exports.AuthenticationScheme.POP)) return [3 /*break*/, 4]; + accessTokenWithAuthSchemeEntity = credential; + kid = accessTokenWithAuthSchemeEntity.keyId; + if (!kid) return [3 /*break*/, 4]; + _a.label = 1; + case 1: + _a.trys.push([1, 3, , 4]); + return [4 /*yield*/, this.cryptoImpl.removeTokenBindingKey(kid)]; + case 2: + _a.sent(); + return [3 /*break*/, 4]; + case 3: + _a.sent(); + throw ClientAuthError.createBindingKeyNotRemovedError(); + case 4: return [2 /*return*/, this.removeItem(key)]; + } + }); + }); + }; + /** + * Removes all app metadata objects from cache. + */ + CacheManager.prototype.removeAppMetadata = function () { + var _this = this; + var allCacheKeys = this.getKeys(); + allCacheKeys.forEach(function (cacheKey) { + if (_this.isAppMetadata(cacheKey)) { + _this.removeItem(cacheKey); + } + }); + return true; + }; + /** + * Retrieve the cached credentials into a cacherecord + * @param account + * @param clientId + * @param scopes + * @param environment + * @param authScheme + */ + CacheManager.prototype.readCacheRecord = function (account, request, environment) { + var tokenKeys = this.getTokenKeys(); + var cachedAccount = this.readAccountFromCache(account); + var cachedIdToken = this.getIdToken(account, tokenKeys); + var cachedAccessToken = this.getAccessToken(account, request, tokenKeys); + var cachedRefreshToken = this.getRefreshToken(account, false, tokenKeys); + var cachedAppMetadata = this.readAppMetadataFromCache(environment); + if (cachedAccount && cachedIdToken) { + cachedAccount.idTokenClaims = new AuthToken(cachedIdToken.secret, this.cryptoImpl).claims; + } + return { + account: cachedAccount, + idToken: cachedIdToken, + accessToken: cachedAccessToken, + refreshToken: cachedRefreshToken, + appMetadata: cachedAppMetadata, + }; + }; + /** + * Retrieve AccountEntity from cache + * @param account + */ + CacheManager.prototype.readAccountFromCache = function (account) { + var accountKey = AccountEntity.generateAccountCacheKey(account); + return this.getAccount(accountKey); + }; + /** + * Retrieve IdTokenEntity from cache + * @param clientId + * @param account + * @param inputRealm + */ + CacheManager.prototype.getIdToken = function (account, tokenKeys) { + this.commonLogger.trace("CacheManager - getIdToken called"); + var idTokenFilter = { + homeAccountId: account.homeAccountId, + environment: account.environment, + credentialType: exports.CredentialType.ID_TOKEN, + clientId: this.clientId, + realm: account.tenantId, + }; + var idTokens = this.getIdTokensByFilter(idTokenFilter, tokenKeys); + var numIdTokens = idTokens.length; + if (numIdTokens < 1) { + this.commonLogger.info("CacheManager:getIdToken - No token found"); + return null; + } + else if (numIdTokens > 1) { + throw ClientAuthError.createMultipleMatchingTokensInCacheError(); + } + this.commonLogger.info("CacheManager:getIdToken - Returning id token"); + return idTokens[0]; + }; + /** + * Gets all idTokens matching the given filter + * @param filter + * @returns + */ + CacheManager.prototype.getIdTokensByFilter = function (filter, tokenKeys) { + var _this = this; + var idTokenKeys = tokenKeys && tokenKeys.idToken || this.getTokenKeys().idToken; + var idTokens = []; + idTokenKeys.forEach(function (key) { + if (!_this.idTokenKeyMatchesFilter(key, __assign({ clientId: _this.clientId }, filter))) { + return; + } + var idToken = _this.getIdTokenCredential(key); + if (idToken && _this.credentialMatchesFilter(idToken, filter)) { + idTokens.push(idToken); + } + }); + return idTokens; + }; + /** + * Validate the cache key against filter before retrieving and parsing cache value + * @param key + * @param filter + * @returns + */ + CacheManager.prototype.idTokenKeyMatchesFilter = function (inputKey, filter) { + var key = inputKey.toLowerCase(); + if (filter.clientId && key.indexOf(filter.clientId.toLowerCase()) === -1) { + return false; + } + if (filter.homeAccountId && key.indexOf(filter.homeAccountId.toLowerCase()) === -1) { + return false; + } + return true; + }; + /** + * Removes idToken from the cache + * @param key + */ + CacheManager.prototype.removeIdToken = function (key) { + this.removeItem(key); + }; + /** + * Removes refresh token from the cache + * @param key + */ + CacheManager.prototype.removeRefreshToken = function (key) { + this.removeItem(key); + }; + /** + * Retrieve AccessTokenEntity from cache + * @param clientId + * @param account + * @param scopes + * @param authScheme + */ + CacheManager.prototype.getAccessToken = function (account, request, tokenKeys) { + var _this = this; + this.commonLogger.trace("CacheManager - getAccessToken called"); + var scopes = ScopeSet.createSearchScopes(request.scopes); + var authScheme = request.authenticationScheme || exports.AuthenticationScheme.BEARER; + /* + * Distinguish between Bearer and PoP/SSH token cache types + * Cast to lowercase to handle "bearer" from ADFS + */ + var credentialType = (authScheme && authScheme.toLowerCase() !== exports.AuthenticationScheme.BEARER.toLowerCase()) ? exports.CredentialType.ACCESS_TOKEN_WITH_AUTH_SCHEME : exports.CredentialType.ACCESS_TOKEN; + var accessTokenFilter = { + homeAccountId: account.homeAccountId, + environment: account.environment, + credentialType: credentialType, + clientId: this.clientId, + realm: account.tenantId, + target: scopes, + tokenType: authScheme, + keyId: request.sshKid, + requestedClaimsHash: request.requestedClaimsHash, + }; + var accessTokenKeys = tokenKeys && tokenKeys.accessToken || this.getTokenKeys().accessToken; + var accessTokens = []; + accessTokenKeys.forEach(function (key) { + // Validate key + if (_this.accessTokenKeyMatchesFilter(key, accessTokenFilter, true)) { + var accessToken = _this.getAccessTokenCredential(key); + // Validate value + if (accessToken && _this.credentialMatchesFilter(accessToken, accessTokenFilter)) { + accessTokens.push(accessToken); + } + } + }); + var numAccessTokens = accessTokens.length; + if (numAccessTokens < 1) { + this.commonLogger.info("CacheManager:getAccessToken - No token found"); + return null; + } + else if (numAccessTokens > 1) { + throw ClientAuthError.createMultipleMatchingTokensInCacheError(); + } + this.commonLogger.info("CacheManager:getAccessToken - Returning access token"); + return accessTokens[0]; + }; + /** + * Validate the cache key against filter before retrieving and parsing cache value + * @param key + * @param filter + * @param keyMustContainAllScopes + * @returns + */ + CacheManager.prototype.accessTokenKeyMatchesFilter = function (inputKey, filter, keyMustContainAllScopes) { + var key = inputKey.toLowerCase(); + if (filter.clientId && key.indexOf(filter.clientId.toLowerCase()) === -1) { + return false; + } + if (filter.homeAccountId && key.indexOf(filter.homeAccountId.toLowerCase()) === -1) { + return false; + } + if (filter.realm && key.indexOf(filter.realm.toLowerCase()) === -1) { + return false; + } + if (filter.requestedClaimsHash && key.indexOf(filter.requestedClaimsHash.toLowerCase()) === -1) { + return false; + } + if (filter.target) { + var scopes = filter.target.asArray(); + for (var i = 0; i < scopes.length; i++) { + if (keyMustContainAllScopes && !key.includes(scopes[i].toLowerCase())) { + // When performing a cache lookup a missing scope would be a cache miss + return false; + } + else if (!keyMustContainAllScopes && key.includes(scopes[i].toLowerCase())) { + // When performing a cache write, any token with a subset of requested scopes should be replaced + return true; + } + } + } + return true; + }; + /** + * Gets all access tokens matching the filter + * @param filter + * @returns + */ + CacheManager.prototype.getAccessTokensByFilter = function (filter) { + var _this = this; + var tokenKeys = this.getTokenKeys(); + var accessTokens = []; + tokenKeys.accessToken.forEach(function (key) { + if (!_this.accessTokenKeyMatchesFilter(key, filter, true)) { + return; + } + var accessToken = _this.getAccessTokenCredential(key); + if (accessToken && _this.credentialMatchesFilter(accessToken, filter)) { + accessTokens.push(accessToken); + } + }); + return accessTokens; + }; + /** + * Helper to retrieve the appropriate refresh token from cache + * @param clientId + * @param account + * @param familyRT + */ + CacheManager.prototype.getRefreshToken = function (account, familyRT, tokenKeys) { + var _this = this; + this.commonLogger.trace("CacheManager - getRefreshToken called"); + var id = familyRT ? THE_FAMILY_ID : undefined; + var refreshTokenFilter = { + homeAccountId: account.homeAccountId, + environment: account.environment, + credentialType: exports.CredentialType.REFRESH_TOKEN, + clientId: this.clientId, + familyId: id, + }; + var refreshTokenKeys = tokenKeys && tokenKeys.refreshToken || this.getTokenKeys().refreshToken; + var refreshTokens = []; + refreshTokenKeys.forEach(function (key) { + // Validate key + if (_this.refreshTokenKeyMatchesFilter(key, refreshTokenFilter)) { + var refreshToken = _this.getRefreshTokenCredential(key); + // Validate value + if (refreshToken && _this.credentialMatchesFilter(refreshToken, refreshTokenFilter)) { + refreshTokens.push(refreshToken); + } + } + }); + var numRefreshTokens = refreshTokens.length; + if (numRefreshTokens < 1) { + this.commonLogger.info("CacheManager:getRefreshToken - No refresh token found."); + return null; + } + // address the else case after remove functions address environment aliases + this.commonLogger.info("CacheManager:getRefreshToken - returning refresh token"); + return refreshTokens[0]; + }; + /** + * Validate the cache key against filter before retrieving and parsing cache value + * @param key + * @param filter + */ + CacheManager.prototype.refreshTokenKeyMatchesFilter = function (inputKey, filter) { + var key = inputKey.toLowerCase(); + if (filter.familyId && key.indexOf(filter.familyId.toLowerCase()) === -1) { + return false; + } + // If familyId is used, clientId is not in the key + if (!filter.familyId && filter.clientId && key.indexOf(filter.clientId.toLowerCase()) === -1) { + return false; + } + if (filter.homeAccountId && key.indexOf(filter.homeAccountId.toLowerCase()) === -1) { + return false; + } + return true; + }; + /** + * Retrieve AppMetadataEntity from cache + */ + CacheManager.prototype.readAppMetadataFromCache = function (environment) { + var appMetadataFilter = { + environment: environment, + clientId: this.clientId, + }; + var appMetadata = this.getAppMetadataFilteredBy(appMetadataFilter); + var appMetadataEntries = Object.keys(appMetadata).map(function (key) { return appMetadata[key]; }); + var numAppMetadata = appMetadataEntries.length; + if (numAppMetadata < 1) { + return null; + } + else if (numAppMetadata > 1) { + throw ClientAuthError.createMultipleMatchingAppMetadataInCacheError(); + } + return appMetadataEntries[0]; + }; + /** + * Return the family_id value associated with FOCI + * @param environment + * @param clientId + */ + CacheManager.prototype.isAppMetadataFOCI = function (environment) { + var appMetadata = this.readAppMetadataFromCache(environment); + return !!(appMetadata && appMetadata.familyId === THE_FAMILY_ID); + }; + /** + * helper to match account ids + * @param value + * @param homeAccountId + */ + CacheManager.prototype.matchHomeAccountId = function (entity, homeAccountId) { + return !!((typeof entity.homeAccountId === "string") && (homeAccountId === entity.homeAccountId)); + }; + /** + * helper to match account ids + * @param entity + * @param localAccountId + * @returns + */ + CacheManager.prototype.matchLocalAccountId = function (entity, localAccountId) { + return !!((typeof entity.localAccountId === "string") && (localAccountId === entity.localAccountId)); + }; + /** + * helper to match usernames + * @param entity + * @param username + * @returns + */ + CacheManager.prototype.matchUsername = function (entity, username) { + return !!((typeof entity.username === "string") && (username.toLowerCase() === entity.username.toLowerCase())); + }; + /** + * helper to match assertion + * @param value + * @param oboAssertion + */ + CacheManager.prototype.matchUserAssertionHash = function (entity, userAssertionHash) { + return !!(entity.userAssertionHash && userAssertionHash === entity.userAssertionHash); + }; + /** + * helper to match environment + * @param value + * @param environment + */ + CacheManager.prototype.matchEnvironment = function (entity, environment) { + var cloudMetadata = this.getAuthorityMetadataByAlias(environment); + if (cloudMetadata && cloudMetadata.aliases.indexOf(entity.environment) > -1) { + return true; + } + return false; + }; + /** + * helper to match credential type + * @param entity + * @param credentialType + */ + CacheManager.prototype.matchCredentialType = function (entity, credentialType) { + return (entity.credentialType && credentialType.toLowerCase() === entity.credentialType.toLowerCase()); + }; + /** + * helper to match client ids + * @param entity + * @param clientId + */ + CacheManager.prototype.matchClientId = function (entity, clientId) { + return !!(entity.clientId && clientId === entity.clientId); + }; + /** + * helper to match family ids + * @param entity + * @param familyId + */ + CacheManager.prototype.matchFamilyId = function (entity, familyId) { + return !!(entity.familyId && familyId === entity.familyId); + }; + /** + * helper to match realm + * @param entity + * @param realm + */ + CacheManager.prototype.matchRealm = function (entity, realm) { + return !!(entity.realm && realm === entity.realm); + }; + /** + * helper to match nativeAccountId + * @param entity + * @param nativeAccountId + * @returns boolean indicating the match result + */ + CacheManager.prototype.matchNativeAccountId = function (entity, nativeAccountId) { + return !!(entity.nativeAccountId && nativeAccountId === entity.nativeAccountId); + }; + /** + * Returns true if the target scopes are a subset of the current entity's scopes, false otherwise. + * @param entity + * @param target + */ + CacheManager.prototype.matchTarget = function (entity, target) { + var isNotAccessTokenCredential = (entity.credentialType !== exports.CredentialType.ACCESS_TOKEN && entity.credentialType !== exports.CredentialType.ACCESS_TOKEN_WITH_AUTH_SCHEME); + if (isNotAccessTokenCredential || !entity.target) { + return false; + } + var entityScopeSet = ScopeSet.fromString(entity.target); + return entityScopeSet.containsScopeSet(target); + }; + /** + * Returns true if the credential's tokenType or Authentication Scheme matches the one in the request, false otherwise + * @param entity + * @param tokenType + */ + CacheManager.prototype.matchTokenType = function (entity, tokenType) { + return !!(entity.tokenType && entity.tokenType === tokenType); + }; + /** + * Returns true if the credential's keyId matches the one in the request, false otherwise + * @param entity + * @param tokenType + */ + CacheManager.prototype.matchKeyId = function (entity, keyId) { + return !!(entity.keyId && entity.keyId === keyId); + }; + /** + * returns if a given cache entity is of the type appmetadata + * @param key + */ + CacheManager.prototype.isAppMetadata = function (key) { + return key.indexOf(APP_METADATA) !== -1; + }; + /** + * returns if a given cache entity is of the type authoritymetadata + * @param key + */ + CacheManager.prototype.isAuthorityMetadata = function (key) { + return key.indexOf(AUTHORITY_METADATA_CONSTANTS.CACHE_KEY) !== -1; + }; + /** + * returns cache key used for cloud instance metadata + */ + CacheManager.prototype.generateAuthorityMetadataCacheKey = function (authority) { + return AUTHORITY_METADATA_CONSTANTS.CACHE_KEY + "-" + this.clientId + "-" + authority; + }; + /** + * Helper to convert serialized data to object + * @param obj + * @param json + */ + CacheManager.toObject = function (obj, json) { + for (var propertyName in json) { + obj[propertyName] = json[propertyName]; + } + return obj; + }; + return CacheManager; +}()); +var DefaultStorageClass = /** @class */ (function (_super) { + __extends(DefaultStorageClass, _super); + function DefaultStorageClass() { + return _super !== null && _super.apply(this, arguments) || this; + } + DefaultStorageClass.prototype.setAccount = function () { + var notImplErr = "Storage interface - setAccount() has not been implemented for the cacheStorage interface."; + throw AuthError.createUnexpectedError(notImplErr); + }; + DefaultStorageClass.prototype.getAccount = function () { + var notImplErr = "Storage interface - getAccount() has not been implemented for the cacheStorage interface."; + throw AuthError.createUnexpectedError(notImplErr); + }; + DefaultStorageClass.prototype.setIdTokenCredential = function () { + var notImplErr = "Storage interface - setIdTokenCredential() has not been implemented for the cacheStorage interface."; + throw AuthError.createUnexpectedError(notImplErr); + }; + DefaultStorageClass.prototype.getIdTokenCredential = function () { + var notImplErr = "Storage interface - getIdTokenCredential() has not been implemented for the cacheStorage interface."; + throw AuthError.createUnexpectedError(notImplErr); + }; + DefaultStorageClass.prototype.setAccessTokenCredential = function () { + var notImplErr = "Storage interface - setAccessTokenCredential() has not been implemented for the cacheStorage interface."; + throw AuthError.createUnexpectedError(notImplErr); + }; + DefaultStorageClass.prototype.getAccessTokenCredential = function () { + var notImplErr = "Storage interface - getAccessTokenCredential() has not been implemented for the cacheStorage interface."; + throw AuthError.createUnexpectedError(notImplErr); + }; + DefaultStorageClass.prototype.setRefreshTokenCredential = function () { + var notImplErr = "Storage interface - setRefreshTokenCredential() has not been implemented for the cacheStorage interface."; + throw AuthError.createUnexpectedError(notImplErr); + }; + DefaultStorageClass.prototype.getRefreshTokenCredential = function () { + var notImplErr = "Storage interface - getRefreshTokenCredential() has not been implemented for the cacheStorage interface."; + throw AuthError.createUnexpectedError(notImplErr); + }; + DefaultStorageClass.prototype.setAppMetadata = function () { + var notImplErr = "Storage interface - setAppMetadata() has not been implemented for the cacheStorage interface."; + throw AuthError.createUnexpectedError(notImplErr); + }; + DefaultStorageClass.prototype.getAppMetadata = function () { + var notImplErr = "Storage interface - getAppMetadata() has not been implemented for the cacheStorage interface."; + throw AuthError.createUnexpectedError(notImplErr); + }; + DefaultStorageClass.prototype.setServerTelemetry = function () { + var notImplErr = "Storage interface - setServerTelemetry() has not been implemented for the cacheStorage interface."; + throw AuthError.createUnexpectedError(notImplErr); + }; + DefaultStorageClass.prototype.getServerTelemetry = function () { + var notImplErr = "Storage interface - getServerTelemetry() has not been implemented for the cacheStorage interface."; + throw AuthError.createUnexpectedError(notImplErr); + }; + DefaultStorageClass.prototype.setAuthorityMetadata = function () { + var notImplErr = "Storage interface - setAuthorityMetadata() has not been implemented for the cacheStorage interface."; + throw AuthError.createUnexpectedError(notImplErr); + }; + DefaultStorageClass.prototype.getAuthorityMetadata = function () { + var notImplErr = "Storage interface - getAuthorityMetadata() has not been implemented for the cacheStorage interface."; + throw AuthError.createUnexpectedError(notImplErr); + }; + DefaultStorageClass.prototype.getAuthorityMetadataKeys = function () { + var notImplErr = "Storage interface - getAuthorityMetadataKeys() has not been implemented for the cacheStorage interface."; + throw AuthError.createUnexpectedError(notImplErr); + }; + DefaultStorageClass.prototype.setThrottlingCache = function () { + var notImplErr = "Storage interface - setThrottlingCache() has not been implemented for the cacheStorage interface."; + throw AuthError.createUnexpectedError(notImplErr); + }; + DefaultStorageClass.prototype.getThrottlingCache = function () { + var notImplErr = "Storage interface - getThrottlingCache() has not been implemented for the cacheStorage interface."; + throw AuthError.createUnexpectedError(notImplErr); + }; + DefaultStorageClass.prototype.removeItem = function () { + var notImplErr = "Storage interface - removeItem() has not been implemented for the cacheStorage interface."; + throw AuthError.createUnexpectedError(notImplErr); + }; + DefaultStorageClass.prototype.containsKey = function () { + var notImplErr = "Storage interface - containsKey() has not been implemented for the cacheStorage interface."; + throw AuthError.createUnexpectedError(notImplErr); + }; + DefaultStorageClass.prototype.getKeys = function () { + var notImplErr = "Storage interface - getKeys() has not been implemented for the cacheStorage interface."; + throw AuthError.createUnexpectedError(notImplErr); + }; + DefaultStorageClass.prototype.getAccountKeys = function () { + var notImplErr = "Storage interface - getAccountKeys() has not been implemented for the cacheStorage interface."; + throw AuthError.createUnexpectedError(notImplErr); + }; + DefaultStorageClass.prototype.getTokenKeys = function () { + var notImplErr = "Storage interface - getTokenKeys() has not been implemented for the cacheStorage interface."; + throw AuthError.createUnexpectedError(notImplErr); + }; + DefaultStorageClass.prototype.clear = function () { + return __awaiter(this, void 0, void 0, function () { + var notImplErr; + return __generator(this, function (_a) { + notImplErr = "Storage interface - clear() has not been implemented for the cacheStorage interface."; + throw AuthError.createUnexpectedError(notImplErr); + }); + }); + }; + DefaultStorageClass.prototype.updateCredentialCacheKey = function () { + var notImplErr = "Storage interface - updateCredentialCacheKey() has not been implemented for the cacheStorage interface."; + throw AuthError.createUnexpectedError(notImplErr); + }; + return DefaultStorageClass; +}(CacheManager)); + +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. + */ +// Token renewal offset default in seconds +var DEFAULT_TOKEN_RENEWAL_OFFSET_SEC = 300; +var DEFAULT_SYSTEM_OPTIONS = { + tokenRenewalOffsetSeconds: DEFAULT_TOKEN_RENEWAL_OFFSET_SEC, + preventCorsPreflight: false +}; +var DEFAULT_LOGGER_IMPLEMENTATION = { + loggerCallback: function () { + // allow users to not set loggerCallback + }, + piiLoggingEnabled: false, + logLevel: exports.LogLevel.Info, + correlationId: Constants.EMPTY_STRING +}; +var DEFAULT_CACHE_OPTIONS = { + claimsBasedCachingEnabled: true +}; +var DEFAULT_NETWORK_IMPLEMENTATION = { + sendGetRequestAsync: function () { + return __awaiter(this, void 0, void 0, function () { + var notImplErr; + return __generator(this, function (_a) { + notImplErr = "Network interface - sendGetRequestAsync() has not been implemented"; + throw AuthError.createUnexpectedError(notImplErr); + }); + }); + }, + sendPostRequestAsync: function () { + return __awaiter(this, void 0, void 0, function () { + var notImplErr; + return __generator(this, function (_a) { + notImplErr = "Network interface - sendPostRequestAsync() has not been implemented"; + throw AuthError.createUnexpectedError(notImplErr); + }); + }); + } +}; +var DEFAULT_LIBRARY_INFO = { + sku: Constants.SKU, + version: version, + cpu: Constants.EMPTY_STRING, + os: Constants.EMPTY_STRING +}; +var DEFAULT_CLIENT_CREDENTIALS = { + clientSecret: Constants.EMPTY_STRING, + clientAssertion: undefined +}; +var DEFAULT_AZURE_CLOUD_OPTIONS = { + azureCloudInstance: exports.AzureCloudInstance.None, + tenant: "" + Constants.DEFAULT_COMMON_TENANT +}; +var DEFAULT_TELEMETRY_OPTIONS = { + application: { + appName: "", + appVersion: "" + } +}; +/** + * Function that sets the default options when not explicitly configured from app developer + * + * @param Configuration + * + * @returns Configuration + */ +function buildClientConfiguration(_a) { + var userAuthOptions = _a.authOptions, userSystemOptions = _a.systemOptions, userLoggerOption = _a.loggerOptions, userCacheOptions = _a.cacheOptions, storageImplementation = _a.storageInterface, networkImplementation = _a.networkInterface, cryptoImplementation = _a.cryptoInterface, clientCredentials = _a.clientCredentials, libraryInfo = _a.libraryInfo, telemetry = _a.telemetry, serverTelemetryManager = _a.serverTelemetryManager, persistencePlugin = _a.persistencePlugin, serializableCache = _a.serializableCache; + var loggerOptions = __assign(__assign({}, DEFAULT_LOGGER_IMPLEMENTATION), userLoggerOption); + return { + authOptions: buildAuthOptions(userAuthOptions), + systemOptions: __assign(__assign({}, DEFAULT_SYSTEM_OPTIONS), userSystemOptions), + loggerOptions: loggerOptions, + cacheOptions: __assign(__assign({}, DEFAULT_CACHE_OPTIONS), userCacheOptions), + storageInterface: storageImplementation || new DefaultStorageClass(userAuthOptions.clientId, DEFAULT_CRYPTO_IMPLEMENTATION, new Logger(loggerOptions)), + networkInterface: networkImplementation || DEFAULT_NETWORK_IMPLEMENTATION, + cryptoInterface: cryptoImplementation || DEFAULT_CRYPTO_IMPLEMENTATION, + clientCredentials: clientCredentials || DEFAULT_CLIENT_CREDENTIALS, + libraryInfo: __assign(__assign({}, DEFAULT_LIBRARY_INFO), libraryInfo), + telemetry: __assign(__assign({}, DEFAULT_TELEMETRY_OPTIONS), telemetry), + serverTelemetryManager: serverTelemetryManager || null, + persistencePlugin: persistencePlugin || null, + serializableCache: serializableCache || null, + }; +} +/** + * Construct authoptions from the client and platform passed values + * @param authOptions + */ +function buildAuthOptions(authOptions) { + return __assign({ clientCapabilities: [], azureCloudOptions: DEFAULT_AZURE_CLOUD_OPTIONS, skipAuthorityMetadataCache: false }, authOptions); +} + +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. + */ +/** + * Error thrown when there is an error with the server code, for example, unavailability. + */ +var ServerError = /** @class */ (function (_super) { + __extends(ServerError, _super); + function ServerError(errorCode, errorMessage, subError) { + var _this = _super.call(this, errorCode, errorMessage, subError) || this; + _this.name = "ServerError"; + Object.setPrototypeOf(_this, ServerError.prototype); + return _this; + } + return ServerError; +}(AuthError)); + +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. + */ +var ThrottlingUtils = /** @class */ (function () { + function ThrottlingUtils() { + } + /** + * Prepares a RequestThumbprint to be stored as a key. + * @param thumbprint + */ + ThrottlingUtils.generateThrottlingStorageKey = function (thumbprint) { + return ThrottlingConstants.THROTTLING_PREFIX + "." + JSON.stringify(thumbprint); + }; + /** + * Performs necessary throttling checks before a network request. + * @param cacheManager + * @param thumbprint + */ + ThrottlingUtils.preProcess = function (cacheManager, thumbprint) { + var _a; + var key = ThrottlingUtils.generateThrottlingStorageKey(thumbprint); + var value = cacheManager.getThrottlingCache(key); + if (value) { + if (value.throttleTime < Date.now()) { + cacheManager.removeItem(key); + return; + } + throw new ServerError(((_a = value.errorCodes) === null || _a === void 0 ? void 0 : _a.join(" ")) || Constants.EMPTY_STRING, value.errorMessage, value.subError); + } + }; + /** + * Performs necessary throttling checks after a network request. + * @param cacheManager + * @param thumbprint + * @param response + */ + ThrottlingUtils.postProcess = function (cacheManager, thumbprint, response) { + if (ThrottlingUtils.checkResponseStatus(response) || ThrottlingUtils.checkResponseForRetryAfter(response)) { + var thumbprintValue = { + throttleTime: ThrottlingUtils.calculateThrottleTime(parseInt(response.headers[exports.HeaderNames.RETRY_AFTER])), + error: response.body.error, + errorCodes: response.body.error_codes, + errorMessage: response.body.error_description, + subError: response.body.suberror + }; + cacheManager.setThrottlingCache(ThrottlingUtils.generateThrottlingStorageKey(thumbprint), thumbprintValue); + } + }; + /** + * Checks a NetworkResponse object's status codes against 429 or 5xx + * @param response + */ + ThrottlingUtils.checkResponseStatus = function (response) { + return response.status === 429 || response.status >= 500 && response.status < 600; + }; + /** + * Checks a NetworkResponse object's RetryAfter header + * @param response + */ + ThrottlingUtils.checkResponseForRetryAfter = function (response) { + if (response.headers) { + return response.headers.hasOwnProperty(exports.HeaderNames.RETRY_AFTER) && (response.status < 200 || response.status >= 300); + } + return false; + }; + /** + * Calculates the Unix-time value for a throttle to expire given throttleTime in seconds. + * @param throttleTime + */ + ThrottlingUtils.calculateThrottleTime = function (throttleTime) { + var time = throttleTime <= 0 ? 0 : throttleTime; + var currentSeconds = Date.now() / 1000; + return Math.floor(Math.min(currentSeconds + (time || ThrottlingConstants.DEFAULT_THROTTLE_TIME_SECONDS), currentSeconds + ThrottlingConstants.DEFAULT_MAX_THROTTLE_TIME_SECONDS) * 1000); + }; + ThrottlingUtils.removeThrottle = function (cacheManager, clientId, request, homeAccountIdentifier) { + var thumbprint = { + clientId: clientId, + authority: request.authority, + scopes: request.scopes, + homeAccountIdentifier: homeAccountIdentifier, + claims: request.claims, + authenticationScheme: request.authenticationScheme, + resourceRequestMethod: request.resourceRequestMethod, + resourceRequestUri: request.resourceRequestUri, + shrClaims: request.shrClaims, + sshKid: request.sshKid + }; + var key = this.generateThrottlingStorageKey(thumbprint); + cacheManager.removeItem(key); + }; + return ThrottlingUtils; +}()); + +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. + */ +var NetworkManager = /** @class */ (function () { + function NetworkManager(networkClient, cacheManager) { + this.networkClient = networkClient; + this.cacheManager = cacheManager; + } + /** + * Wraps sendPostRequestAsync with necessary preflight and postflight logic + * @param thumbprint + * @param tokenEndpoint + * @param options + */ + NetworkManager.prototype.sendPostRequest = function (thumbprint, tokenEndpoint, options) { + return __awaiter(this, void 0, void 0, function () { + var response, e_1; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + ThrottlingUtils.preProcess(this.cacheManager, thumbprint); + _a.label = 1; + case 1: + _a.trys.push([1, 3, , 4]); + return [4 /*yield*/, this.networkClient.sendPostRequestAsync(tokenEndpoint, options)]; + case 2: + response = _a.sent(); + return [3 /*break*/, 4]; + case 3: + e_1 = _a.sent(); + if (e_1 instanceof AuthError) { + throw e_1; + } + else { + throw ClientAuthError.createNetworkError(tokenEndpoint, e_1); + } + case 4: + ThrottlingUtils.postProcess(this.cacheManager, thumbprint, response); + return [2 /*return*/, response]; + } + }); + }); + }; + return NetworkManager; +}()); + +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. + */ +exports.CcsCredentialType = void 0; +(function (CcsCredentialType) { + CcsCredentialType["HOME_ACCOUNT_ID"] = "home_account_id"; + CcsCredentialType["UPN"] = "UPN"; +})(exports.CcsCredentialType || (exports.CcsCredentialType = {})); + +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. + */ +/** + * Validates server consumable params from the "request" objects + */ +var RequestValidator = /** @class */ (function () { + function RequestValidator() { + } + /** + * Utility to check if the `redirectUri` in the request is a non-null value + * @param redirectUri + */ + RequestValidator.validateRedirectUri = function (redirectUri) { + if (StringUtils.isEmpty(redirectUri)) { + throw ClientConfigurationError.createRedirectUriEmptyError(); + } + }; + /** + * Utility to validate prompt sent by the user in the request + * @param prompt + */ + RequestValidator.validatePrompt = function (prompt) { + var promptValues = []; + for (var value in PromptValue) { + promptValues.push(PromptValue[value]); + } + if (promptValues.indexOf(prompt) < 0) { + throw ClientConfigurationError.createInvalidPromptError(prompt); + } + }; + RequestValidator.validateClaims = function (claims) { + try { + JSON.parse(claims); + } + catch (e) { + throw ClientConfigurationError.createInvalidClaimsRequestError(); + } + }; + /** + * Utility to validate code_challenge and code_challenge_method + * @param codeChallenge + * @param codeChallengeMethod + */ + RequestValidator.validateCodeChallengeParams = function (codeChallenge, codeChallengeMethod) { + if (StringUtils.isEmpty(codeChallenge) || StringUtils.isEmpty(codeChallengeMethod)) { + throw ClientConfigurationError.createInvalidCodeChallengeParamsError(); + } + else { + this.validateCodeChallengeMethod(codeChallengeMethod); + } + }; + /** + * Utility to validate code_challenge_method + * @param codeChallengeMethod + */ + RequestValidator.validateCodeChallengeMethod = function (codeChallengeMethod) { + if ([ + CodeChallengeMethodValues.PLAIN, + CodeChallengeMethodValues.S256 + ].indexOf(codeChallengeMethod) < 0) { + throw ClientConfigurationError.createInvalidCodeChallengeMethodError(); + } + }; + /** + * Removes unnecessary, duplicate, and empty string query parameters from extraQueryParameters + * @param request + */ + RequestValidator.sanitizeEQParams = function (eQParams, queryParams) { + if (!eQParams) { + return {}; + } + // Remove any query parameters already included in SSO params + queryParams.forEach(function (value, key) { + if (eQParams[key]) { + delete eQParams[key]; + } + }); + // remove empty string parameters + // eslint-disable-next-line @typescript-eslint/no-unused-vars + return Object.fromEntries(Object.entries(eQParams).filter(function (_a) { + _a[0]; var value = _a[1]; + return value !== ""; + })); + }; + return RequestValidator; +}()); + +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. + */ +var RequestParameterBuilder = /** @class */ (function () { + function RequestParameterBuilder() { + this.parameters = new Map(); + } + /** + * add response_type = code + */ + RequestParameterBuilder.prototype.addResponseTypeCode = function () { + this.parameters.set(exports.AADServerParamKeys.RESPONSE_TYPE, encodeURIComponent(Constants.CODE_RESPONSE_TYPE)); + }; + /** + * add response_type = token id_token + */ + RequestParameterBuilder.prototype.addResponseTypeForTokenAndIdToken = function () { + this.parameters.set(exports.AADServerParamKeys.RESPONSE_TYPE, encodeURIComponent(Constants.TOKEN_RESPONSE_TYPE + " " + Constants.ID_TOKEN_RESPONSE_TYPE)); + }; + /** + * add response_mode. defaults to query. + * @param responseMode + */ + RequestParameterBuilder.prototype.addResponseMode = function (responseMode) { + this.parameters.set(exports.AADServerParamKeys.RESPONSE_MODE, encodeURIComponent((responseMode) ? responseMode : exports.ResponseMode.QUERY)); + }; + /** + * Add flag to indicate STS should attempt to use WAM if available + */ + RequestParameterBuilder.prototype.addNativeBroker = function () { + this.parameters.set(exports.AADServerParamKeys.NATIVE_BROKER, encodeURIComponent("1")); + }; + /** + * add scopes. set addOidcScopes to false to prevent default scopes in non-user scenarios + * @param scopeSet + * @param addOidcScopes + */ + RequestParameterBuilder.prototype.addScopes = function (scopes, addOidcScopes) { + if (addOidcScopes === void 0) { addOidcScopes = true; } + var requestScopes = addOidcScopes ? __spreadArrays(scopes || [], OIDC_DEFAULT_SCOPES) : scopes || []; + var scopeSet = new ScopeSet(requestScopes); + this.parameters.set(exports.AADServerParamKeys.SCOPE, encodeURIComponent(scopeSet.printScopes())); + }; + /** + * add clientId + * @param clientId + */ + RequestParameterBuilder.prototype.addClientId = function (clientId) { + this.parameters.set(exports.AADServerParamKeys.CLIENT_ID, encodeURIComponent(clientId)); + }; + /** + * add redirect_uri + * @param redirectUri + */ + RequestParameterBuilder.prototype.addRedirectUri = function (redirectUri) { + RequestValidator.validateRedirectUri(redirectUri); + this.parameters.set(exports.AADServerParamKeys.REDIRECT_URI, encodeURIComponent(redirectUri)); + }; + /** + * add post logout redirectUri + * @param redirectUri + */ + RequestParameterBuilder.prototype.addPostLogoutRedirectUri = function (redirectUri) { + RequestValidator.validateRedirectUri(redirectUri); + this.parameters.set(exports.AADServerParamKeys.POST_LOGOUT_URI, encodeURIComponent(redirectUri)); + }; + /** + * add id_token_hint to logout request + * @param idTokenHint + */ + RequestParameterBuilder.prototype.addIdTokenHint = function (idTokenHint) { + this.parameters.set(exports.AADServerParamKeys.ID_TOKEN_HINT, encodeURIComponent(idTokenHint)); + }; + /** + * add domain_hint + * @param domainHint + */ + RequestParameterBuilder.prototype.addDomainHint = function (domainHint) { + this.parameters.set(exports.SSOTypes.DOMAIN_HINT, encodeURIComponent(domainHint)); + }; + /** + * add login_hint + * @param loginHint + */ + RequestParameterBuilder.prototype.addLoginHint = function (loginHint) { + this.parameters.set(exports.SSOTypes.LOGIN_HINT, encodeURIComponent(loginHint)); + }; + /** + * Adds the CCS (Cache Credential Service) query parameter for login_hint + * @param loginHint + */ + RequestParameterBuilder.prototype.addCcsUpn = function (loginHint) { + this.parameters.set(exports.HeaderNames.CCS_HEADER, encodeURIComponent("UPN:" + loginHint)); + }; + /** + * Adds the CCS (Cache Credential Service) query parameter for account object + * @param loginHint + */ + RequestParameterBuilder.prototype.addCcsOid = function (clientInfo) { + this.parameters.set(exports.HeaderNames.CCS_HEADER, encodeURIComponent("Oid:" + clientInfo.uid + "@" + clientInfo.utid)); + }; + /** + * add sid + * @param sid + */ + RequestParameterBuilder.prototype.addSid = function (sid) { + this.parameters.set(exports.SSOTypes.SID, encodeURIComponent(sid)); + }; + /** + * add claims + * @param claims + */ + RequestParameterBuilder.prototype.addClaims = function (claims, clientCapabilities) { + var mergedClaims = this.addClientCapabilitiesToClaims(claims, clientCapabilities); + RequestValidator.validateClaims(mergedClaims); + this.parameters.set(exports.AADServerParamKeys.CLAIMS, encodeURIComponent(mergedClaims)); + }; + /** + * add correlationId + * @param correlationId + */ + RequestParameterBuilder.prototype.addCorrelationId = function (correlationId) { + this.parameters.set(exports.AADServerParamKeys.CLIENT_REQUEST_ID, encodeURIComponent(correlationId)); + }; + /** + * add library info query params + * @param libraryInfo + */ + RequestParameterBuilder.prototype.addLibraryInfo = function (libraryInfo) { + // Telemetry Info + this.parameters.set(exports.AADServerParamKeys.X_CLIENT_SKU, libraryInfo.sku); + this.parameters.set(exports.AADServerParamKeys.X_CLIENT_VER, libraryInfo.version); + if (libraryInfo.os) { + this.parameters.set(exports.AADServerParamKeys.X_CLIENT_OS, libraryInfo.os); + } + if (libraryInfo.cpu) { + this.parameters.set(exports.AADServerParamKeys.X_CLIENT_CPU, libraryInfo.cpu); + } + }; + /** + * Add client telemetry parameters + * @param appTelemetry + */ + RequestParameterBuilder.prototype.addApplicationTelemetry = function (appTelemetry) { + if (appTelemetry === null || appTelemetry === void 0 ? void 0 : appTelemetry.appName) { + this.parameters.set(exports.AADServerParamKeys.X_APP_NAME, appTelemetry.appName); + } + if (appTelemetry === null || appTelemetry === void 0 ? void 0 : appTelemetry.appVersion) { + this.parameters.set(exports.AADServerParamKeys.X_APP_VER, appTelemetry.appVersion); + } + }; + /** + * add prompt + * @param prompt + */ + RequestParameterBuilder.prototype.addPrompt = function (prompt) { + RequestValidator.validatePrompt(prompt); + this.parameters.set("" + exports.AADServerParamKeys.PROMPT, encodeURIComponent(prompt)); + }; + /** + * add state + * @param state + */ + RequestParameterBuilder.prototype.addState = function (state) { + if (!StringUtils.isEmpty(state)) { + this.parameters.set(exports.AADServerParamKeys.STATE, encodeURIComponent(state)); + } + }; + /** + * add nonce + * @param nonce + */ + RequestParameterBuilder.prototype.addNonce = function (nonce) { + this.parameters.set(exports.AADServerParamKeys.NONCE, encodeURIComponent(nonce)); + }; + /** + * add code_challenge and code_challenge_method + * - throw if either of them are not passed + * @param codeChallenge + * @param codeChallengeMethod + */ + RequestParameterBuilder.prototype.addCodeChallengeParams = function (codeChallenge, codeChallengeMethod) { + RequestValidator.validateCodeChallengeParams(codeChallenge, codeChallengeMethod); + if (codeChallenge && codeChallengeMethod) { + this.parameters.set(exports.AADServerParamKeys.CODE_CHALLENGE, encodeURIComponent(codeChallenge)); + this.parameters.set(exports.AADServerParamKeys.CODE_CHALLENGE_METHOD, encodeURIComponent(codeChallengeMethod)); + } + else { + throw ClientConfigurationError.createInvalidCodeChallengeParamsError(); + } + }; + /** + * add the `authorization_code` passed by the user to exchange for a token + * @param code + */ + RequestParameterBuilder.prototype.addAuthorizationCode = function (code) { + this.parameters.set(exports.AADServerParamKeys.CODE, encodeURIComponent(code)); + }; + /** + * add the `authorization_code` passed by the user to exchange for a token + * @param code + */ + RequestParameterBuilder.prototype.addDeviceCode = function (code) { + this.parameters.set(exports.AADServerParamKeys.DEVICE_CODE, encodeURIComponent(code)); + }; + /** + * add the `refreshToken` passed by the user + * @param refreshToken + */ + RequestParameterBuilder.prototype.addRefreshToken = function (refreshToken) { + this.parameters.set(exports.AADServerParamKeys.REFRESH_TOKEN, encodeURIComponent(refreshToken)); + }; + /** + * add the `code_verifier` passed by the user to exchange for a token + * @param codeVerifier + */ + RequestParameterBuilder.prototype.addCodeVerifier = function (codeVerifier) { + this.parameters.set(exports.AADServerParamKeys.CODE_VERIFIER, encodeURIComponent(codeVerifier)); + }; + /** + * add client_secret + * @param clientSecret + */ + RequestParameterBuilder.prototype.addClientSecret = function (clientSecret) { + this.parameters.set(exports.AADServerParamKeys.CLIENT_SECRET, encodeURIComponent(clientSecret)); + }; + /** + * add clientAssertion for confidential client flows + * @param clientAssertion + */ + RequestParameterBuilder.prototype.addClientAssertion = function (clientAssertion) { + if (!StringUtils.isEmpty(clientAssertion)) { + this.parameters.set(exports.AADServerParamKeys.CLIENT_ASSERTION, encodeURIComponent(clientAssertion)); + } + }; + /** + * add clientAssertionType for confidential client flows + * @param clientAssertionType + */ + RequestParameterBuilder.prototype.addClientAssertionType = function (clientAssertionType) { + if (!StringUtils.isEmpty(clientAssertionType)) { + this.parameters.set(exports.AADServerParamKeys.CLIENT_ASSERTION_TYPE, encodeURIComponent(clientAssertionType)); + } + }; + /** + * add OBO assertion for confidential client flows + * @param clientAssertion + */ + RequestParameterBuilder.prototype.addOboAssertion = function (oboAssertion) { + this.parameters.set(exports.AADServerParamKeys.OBO_ASSERTION, encodeURIComponent(oboAssertion)); + }; + /** + * add grant type + * @param grantType + */ + RequestParameterBuilder.prototype.addRequestTokenUse = function (tokenUse) { + this.parameters.set(exports.AADServerParamKeys.REQUESTED_TOKEN_USE, encodeURIComponent(tokenUse)); + }; + /** + * add grant type + * @param grantType + */ + RequestParameterBuilder.prototype.addGrantType = function (grantType) { + this.parameters.set(exports.AADServerParamKeys.GRANT_TYPE, encodeURIComponent(grantType)); + }; + /** + * add client info + * + */ + RequestParameterBuilder.prototype.addClientInfo = function () { + this.parameters.set(CLIENT_INFO, "1"); + }; + /** + * add extraQueryParams + * @param eQParams + */ + RequestParameterBuilder.prototype.addExtraQueryParameters = function (eQParams) { + var _this = this; + var sanitizedEQParams = RequestValidator.sanitizeEQParams(eQParams, this.parameters); + Object.keys(sanitizedEQParams).forEach(function (key) { + _this.parameters.set(key, eQParams[key]); + }); + }; + RequestParameterBuilder.prototype.addClientCapabilitiesToClaims = function (claims, clientCapabilities) { + var mergedClaims; + // Parse provided claims into JSON object or initialize empty object + if (!claims) { + mergedClaims = {}; + } + else { + try { + mergedClaims = JSON.parse(claims); + } + catch (e) { + throw ClientConfigurationError.createInvalidClaimsRequestError(); + } + } + if (clientCapabilities && clientCapabilities.length > 0) { + if (!mergedClaims.hasOwnProperty(exports.ClaimsRequestKeys.ACCESS_TOKEN)) { + // Add access_token key to claims object + mergedClaims[exports.ClaimsRequestKeys.ACCESS_TOKEN] = {}; + } + // Add xms_cc claim with provided clientCapabilities to access_token key + mergedClaims[exports.ClaimsRequestKeys.ACCESS_TOKEN][exports.ClaimsRequestKeys.XMS_CC] = { + values: clientCapabilities + }; + } + return JSON.stringify(mergedClaims); + }; + /** + * adds `username` for Password Grant flow + * @param username + */ + RequestParameterBuilder.prototype.addUsername = function (username) { + this.parameters.set(exports.PasswordGrantConstants.username, encodeURIComponent(username)); + }; + /** + * adds `password` for Password Grant flow + * @param password + */ + RequestParameterBuilder.prototype.addPassword = function (password) { + this.parameters.set(exports.PasswordGrantConstants.password, encodeURIComponent(password)); + }; + /** + * add pop_jwk to query params + * @param cnfString + */ + RequestParameterBuilder.prototype.addPopToken = function (cnfString) { + if (!StringUtils.isEmpty(cnfString)) { + this.parameters.set(exports.AADServerParamKeys.TOKEN_TYPE, exports.AuthenticationScheme.POP); + this.parameters.set(exports.AADServerParamKeys.REQ_CNF, encodeURIComponent(cnfString)); + } + }; + /** + * add SSH JWK and key ID to query params + */ + RequestParameterBuilder.prototype.addSshJwk = function (sshJwkString) { + if (!StringUtils.isEmpty(sshJwkString)) { + this.parameters.set(exports.AADServerParamKeys.TOKEN_TYPE, exports.AuthenticationScheme.SSH); + this.parameters.set(exports.AADServerParamKeys.REQ_CNF, encodeURIComponent(sshJwkString)); + } + }; + /** + * add server telemetry fields + * @param serverTelemetryManager + */ + RequestParameterBuilder.prototype.addServerTelemetry = function (serverTelemetryManager) { + this.parameters.set(exports.AADServerParamKeys.X_CLIENT_CURR_TELEM, serverTelemetryManager.generateCurrentRequestHeaderValue()); + this.parameters.set(exports.AADServerParamKeys.X_CLIENT_LAST_TELEM, serverTelemetryManager.generateLastRequestHeaderValue()); + }; + /** + * Adds parameter that indicates to the server that throttling is supported + */ + RequestParameterBuilder.prototype.addThrottling = function () { + this.parameters.set(exports.AADServerParamKeys.X_MS_LIB_CAPABILITY, ThrottlingConstants.X_MS_LIB_CAPABILITY_VALUE); + }; + /** + * Adds logout_hint parameter for "silent" logout which prevent server account picker + */ + RequestParameterBuilder.prototype.addLogoutHint = function (logoutHint) { + this.parameters.set(exports.AADServerParamKeys.LOGOUT_HINT, encodeURIComponent(logoutHint)); + }; + /** + * Utility to create a URL from the params map + */ + RequestParameterBuilder.prototype.createQueryString = function () { + var queryParameterArray = new Array(); + this.parameters.forEach(function (value, key) { + queryParameterArray.push(key + "=" + value); + }); + return queryParameterArray.join("&"); + }; + return RequestParameterBuilder; +}()); + +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. + */ +/** + * Base application class which will construct requests to send to and handle responses from the Microsoft STS using the authorization code flow. + */ +var BaseClient = /** @class */ (function () { + function BaseClient(configuration, performanceClient) { + // Set the configuration + this.config = buildClientConfiguration(configuration); + // Initialize the logger + this.logger = new Logger(this.config.loggerOptions, name, version); + // Initialize crypto + this.cryptoUtils = this.config.cryptoInterface; + // Initialize storage interface + this.cacheManager = this.config.storageInterface; + // Set the network interface + this.networkClient = this.config.networkInterface; + // Set the NetworkManager + this.networkManager = new NetworkManager(this.networkClient, this.cacheManager); + // Set TelemetryManager + this.serverTelemetryManager = this.config.serverTelemetryManager; + // set Authority + this.authority = this.config.authOptions.authority; + // set performance telemetry client + this.performanceClient = performanceClient; + } + /** + * Creates default headers for requests to token endpoint + */ + BaseClient.prototype.createTokenRequestHeaders = function (ccsCred) { + var headers = {}; + headers[exports.HeaderNames.CONTENT_TYPE] = Constants.URL_FORM_CONTENT_TYPE; + if (!this.config.systemOptions.preventCorsPreflight && ccsCred) { + switch (ccsCred.type) { + case exports.CcsCredentialType.HOME_ACCOUNT_ID: + try { + var clientInfo = buildClientInfoFromHomeAccountId(ccsCred.credential); + headers[exports.HeaderNames.CCS_HEADER] = "Oid:" + clientInfo.uid + "@" + clientInfo.utid; + } + catch (e) { + this.logger.verbose("Could not parse home account ID for CCS Header: " + e); + } + break; + case exports.CcsCredentialType.UPN: + headers[exports.HeaderNames.CCS_HEADER] = "UPN: " + ccsCred.credential; + break; + } + } + return headers; + }; + /** + * Http post to token endpoint + * @param tokenEndpoint + * @param queryString + * @param headers + * @param thumbprint + */ + BaseClient.prototype.executePostToTokenEndpoint = function (tokenEndpoint, queryString, headers, thumbprint) { + return __awaiter(this, void 0, void 0, function () { + var response; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: return [4 /*yield*/, this.networkManager.sendPostRequest(thumbprint, tokenEndpoint, { body: queryString, headers: headers })]; + case 1: + response = _a.sent(); + if (this.config.serverTelemetryManager && response.status < 500 && response.status !== 429) { + // Telemetry data successfully logged by server, clear Telemetry cache + this.config.serverTelemetryManager.clearTelemetryCache(); + } + return [2 /*return*/, response]; + } + }); + }); + }; + /** + * Updates the authority object of the client. Endpoint discovery must be completed. + * @param updatedAuthority + */ + BaseClient.prototype.updateAuthority = function (updatedAuthority) { + if (!updatedAuthority.discoveryComplete()) { + throw ClientAuthError.createEndpointDiscoveryIncompleteError("Updated authority has not completed endpoint discovery."); + } + this.authority = updatedAuthority; + }; + /** + * Creates query string for the /token request + * @param request + */ + BaseClient.prototype.createTokenQueryParameters = function (request) { + var parameterBuilder = new RequestParameterBuilder(); + if (request.tokenQueryParameters) { + parameterBuilder.addExtraQueryParameters(request.tokenQueryParameters); + } + return parameterBuilder.createQueryString(); + }; + return BaseClient; +}()); + +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. + */ +/** + * Base type for credentials to be stored in the cache: eg: ACCESS_TOKEN, ID_TOKEN etc + * + * Key:Value Schema: + * + * Key: ------- + * + * Value Schema: + * { + * homeAccountId: home account identifier for the auth scheme, + * environment: entity that issued the token, represented as a full host + * credentialType: Type of credential as a string, can be one of the following: RefreshToken, AccessToken, IdToken, Password, Cookie, Certificate, Other + * clientId: client ID of the application + * secret: Actual credential as a string + * familyId: Family ID identifier, usually only used for refresh tokens + * realm: Full tenant or organizational identifier that the account belongs to + * target: Permissions that are included in the token, or for refresh tokens, the resource identifier. + * tokenType: Matches the authentication scheme for which the token was issued (i.e. Bearer or pop) + * requestedClaimsHash: Matches the SHA 256 hash of the claims object included in the token request + * userAssertionHash: Matches the SHA 256 hash of the obo_assertion for the OBO flow + * } + */ +var CredentialEntity = /** @class */ (function () { + function CredentialEntity() { + } + /** + * Generate Account Id key component as per the schema: - + */ + CredentialEntity.prototype.generateAccountId = function () { + return CredentialEntity.generateAccountIdForCacheKey(this.homeAccountId, this.environment); + }; + /** + * Generate Credential Id key component as per the schema: -- + */ + CredentialEntity.prototype.generateCredentialId = function () { + return CredentialEntity.generateCredentialIdForCacheKey(this.credentialType, this.clientId, this.realm, this.familyId); + }; + /** + * Generate target key component as per schema: + */ + CredentialEntity.prototype.generateTarget = function () { + return CredentialEntity.generateTargetForCacheKey(this.target); + }; + /** + * generates credential key + */ + CredentialEntity.prototype.generateCredentialKey = function () { + return CredentialEntity.generateCredentialCacheKey(this.homeAccountId, this.environment, this.credentialType, this.clientId, this.realm, this.target, this.familyId, this.tokenType, this.requestedClaimsHash); + }; + /** + * returns the type of the cache (in this case credential) + */ + CredentialEntity.prototype.generateType = function () { + switch (this.credentialType) { + case exports.CredentialType.ID_TOKEN: + return exports.CacheType.ID_TOKEN; + case exports.CredentialType.ACCESS_TOKEN: + case exports.CredentialType.ACCESS_TOKEN_WITH_AUTH_SCHEME: + return exports.CacheType.ACCESS_TOKEN; + case exports.CredentialType.REFRESH_TOKEN: + return exports.CacheType.REFRESH_TOKEN; + default: { + throw ClientAuthError.createUnexpectedCredentialTypeError(); + } + } + }; + /** + * generates credential key + * -\----- + */ + CredentialEntity.generateCredentialCacheKey = function (homeAccountId, environment, credentialType, clientId, realm, target, familyId, tokenType, requestedClaimsHash) { + var credentialKey = [ + this.generateAccountIdForCacheKey(homeAccountId, environment), + this.generateCredentialIdForCacheKey(credentialType, clientId, realm, familyId), + this.generateTargetForCacheKey(target), + this.generateClaimsHashForCacheKey(requestedClaimsHash), + this.generateSchemeForCacheKey(tokenType) + ]; + return credentialKey.join(Separators.CACHE_KEY_SEPARATOR).toLowerCase(); + }; + /** + * generates Account Id for keys + * @param homeAccountId + * @param environment + */ + CredentialEntity.generateAccountIdForCacheKey = function (homeAccountId, environment) { + var accountId = [homeAccountId, environment]; + return accountId.join(Separators.CACHE_KEY_SEPARATOR).toLowerCase(); + }; + /** + * Generates Credential Id for keys + * @param credentialType + * @param realm + * @param clientId + * @param familyId + */ + CredentialEntity.generateCredentialIdForCacheKey = function (credentialType, clientId, realm, familyId) { + var clientOrFamilyId = credentialType === exports.CredentialType.REFRESH_TOKEN + ? familyId || clientId + : clientId; + var credentialId = [ + credentialType, + clientOrFamilyId, + realm || Constants.EMPTY_STRING, + ]; + return credentialId.join(Separators.CACHE_KEY_SEPARATOR).toLowerCase(); + }; + /** + * Generate target key component as per schema: + */ + CredentialEntity.generateTargetForCacheKey = function (scopes) { + return (scopes || Constants.EMPTY_STRING).toLowerCase(); + }; + /** + * Generate requested claims key component as per schema: + */ + CredentialEntity.generateClaimsHashForCacheKey = function (requestedClaimsHash) { + return (requestedClaimsHash || Constants.EMPTY_STRING).toLowerCase(); + }; + /** + * Generate scheme key componenet as per schema: + */ + CredentialEntity.generateSchemeForCacheKey = function (tokenType) { + /* + * PoP Tokens and SSH certs include scheme in cache key + * Cast to lowercase to handle "bearer" from ADFS + */ + return (tokenType && tokenType.toLowerCase() !== exports.AuthenticationScheme.BEARER.toLowerCase()) ? tokenType.toLowerCase() : Constants.EMPTY_STRING; + }; + return CredentialEntity; +}()); + +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. + */ +/** + * ID_TOKEN Cache + * + * Key:Value Schema: + * + * Key Example: uid.utid-login.microsoftonline.com-idtoken-clientId-contoso.com- + * + * Value Schema: + * { + * homeAccountId: home account identifier for the auth scheme, + * environment: entity that issued the token, represented as a full host + * credentialType: Type of credential as a string, can be one of the following: RefreshToken, AccessToken, IdToken, Password, Cookie, Certificate, Other + * clientId: client ID of the application + * secret: Actual credential as a string + * realm: Full tenant or organizational identifier that the account belongs to + * } + */ +var IdTokenEntity = /** @class */ (function (_super) { + __extends(IdTokenEntity, _super); + function IdTokenEntity() { + return _super !== null && _super.apply(this, arguments) || this; + } + /** + * Create IdTokenEntity + * @param homeAccountId + * @param authenticationResult + * @param clientId + * @param authority + */ + IdTokenEntity.createIdTokenEntity = function (homeAccountId, environment, idToken, clientId, tenantId) { + var idTokenEntity = new IdTokenEntity(); + idTokenEntity.credentialType = exports.CredentialType.ID_TOKEN; + idTokenEntity.homeAccountId = homeAccountId; + idTokenEntity.environment = environment; + idTokenEntity.clientId = clientId; + idTokenEntity.secret = idToken; + idTokenEntity.realm = tenantId; + return idTokenEntity; + }; + /** + * Validates an entity: checks for all expected params + * @param entity + */ + IdTokenEntity.isIdTokenEntity = function (entity) { + if (!entity) { + return false; + } + return (entity.hasOwnProperty("homeAccountId") && + entity.hasOwnProperty("environment") && + entity.hasOwnProperty("credentialType") && + entity.hasOwnProperty("realm") && + entity.hasOwnProperty("clientId") && + entity.hasOwnProperty("secret") && + entity["credentialType"] === exports.CredentialType.ID_TOKEN); + }; + return IdTokenEntity; +}(CredentialEntity)); + +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. + */ +/** + * Utility class which exposes functions for managing date and time operations. + */ +var TimeUtils = /** @class */ (function () { + function TimeUtils() { + } + /** + * return the current time in Unix time (seconds). + */ + TimeUtils.nowSeconds = function () { + // Date.getTime() returns in milliseconds. + return Math.round(new Date().getTime() / 1000.0); + }; + /** + * check if a token is expired based on given UTC time in seconds. + * @param expiresOn + */ + TimeUtils.isTokenExpired = function (expiresOn, offset) { + // check for access token expiry + var expirationSec = Number(expiresOn) || 0; + var offsetCurrentTimeSec = TimeUtils.nowSeconds() + offset; + // If current time + offset is greater than token expiration time, then token is expired. + return (offsetCurrentTimeSec > expirationSec); + }; + /** + * If the current time is earlier than the time that a token was cached at, we must discard the token + * i.e. The system clock was turned back after acquiring the cached token + * @param cachedAt + * @param offset + */ + TimeUtils.wasClockTurnedBack = function (cachedAt) { + var cachedAtSec = Number(cachedAt); + return cachedAtSec > TimeUtils.nowSeconds(); + }; + /** + * Waits for t number of milliseconds + * @param t number + * @param value T + */ + TimeUtils.delay = function (t, value) { + return new Promise(function (resolve) { return setTimeout(function () { return resolve(value); }, t); }); + }; + return TimeUtils; +}()); + +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. + */ +/** + * ACCESS_TOKEN Credential Type + * + * Key:Value Schema: + * + * Key Example: uid.utid-login.microsoftonline.com-accesstoken-clientId-contoso.com-user.read + * + * Value Schema: + * { + * homeAccountId: home account identifier for the auth scheme, + * environment: entity that issued the token, represented as a full host + * credentialType: Type of credential as a string, can be one of the following: RefreshToken, AccessToken, IdToken, Password, Cookie, Certificate, Other + * clientId: client ID of the application + * secret: Actual credential as a string + * familyId: Family ID identifier, usually only used for refresh tokens + * realm: Full tenant or organizational identifier that the account belongs to + * target: Permissions that are included in the token, or for refresh tokens, the resource identifier. + * cachedAt: Absolute device time when entry was created in the cache. + * expiresOn: Token expiry time, calculated based on current UTC time in seconds. Represented as a string. + * extendedExpiresOn: Additional extended expiry time until when token is valid in case of server-side outage. Represented as string in UTC seconds. + * keyId: used for POP and SSH tokenTypes + * tokenType: Type of the token issued. Usually "Bearer" + * } + */ +var AccessTokenEntity = /** @class */ (function (_super) { + __extends(AccessTokenEntity, _super); + function AccessTokenEntity() { + return _super !== null && _super.apply(this, arguments) || this; + } + /** + * Create AccessTokenEntity + * @param homeAccountId + * @param environment + * @param accessToken + * @param clientId + * @param tenantId + * @param scopes + * @param expiresOn + * @param extExpiresOn + */ + AccessTokenEntity.createAccessTokenEntity = function (homeAccountId, environment, accessToken, clientId, tenantId, scopes, expiresOn, extExpiresOn, cryptoUtils, refreshOn, tokenType, userAssertionHash, keyId, requestedClaims, requestedClaimsHash) { + var _a, _b; + var atEntity = new AccessTokenEntity(); + atEntity.homeAccountId = homeAccountId; + atEntity.credentialType = exports.CredentialType.ACCESS_TOKEN; + atEntity.secret = accessToken; + var currentTime = TimeUtils.nowSeconds(); + atEntity.cachedAt = currentTime.toString(); + /* + * Token expiry time. + * This value should be  calculated based on the current UTC time measured locally and the value  expires_in Represented as a string in JSON. + */ + atEntity.expiresOn = expiresOn.toString(); + atEntity.extendedExpiresOn = extExpiresOn.toString(); + if (refreshOn) { + atEntity.refreshOn = refreshOn.toString(); + } + atEntity.environment = environment; + atEntity.clientId = clientId; + atEntity.realm = tenantId; + atEntity.target = scopes; + atEntity.userAssertionHash = userAssertionHash; + atEntity.tokenType = StringUtils.isEmpty(tokenType) ? exports.AuthenticationScheme.BEARER : tokenType; + if (requestedClaims) { + atEntity.requestedClaims = requestedClaims; + atEntity.requestedClaimsHash = requestedClaimsHash; + } + /* + * Create Access Token With Auth Scheme instead of regular access token + * Cast to lower to handle "bearer" from ADFS + */ + if (((_a = atEntity.tokenType) === null || _a === void 0 ? void 0 : _a.toLowerCase()) !== exports.AuthenticationScheme.BEARER.toLowerCase()) { + atEntity.credentialType = exports.CredentialType.ACCESS_TOKEN_WITH_AUTH_SCHEME; + switch (atEntity.tokenType) { + case exports.AuthenticationScheme.POP: + // Make sure keyId is present and add it to credential + var tokenClaims = AuthToken.extractTokenClaims(accessToken, cryptoUtils); + if (!((_b = tokenClaims === null || tokenClaims === void 0 ? void 0 : tokenClaims.cnf) === null || _b === void 0 ? void 0 : _b.kid)) { + throw ClientAuthError.createTokenClaimsRequiredError(); + } + atEntity.keyId = tokenClaims.cnf.kid; + break; + case exports.AuthenticationScheme.SSH: + atEntity.keyId = keyId; + } + } + return atEntity; + }; + /** + * Validates an entity: checks for all expected params + * @param entity + */ + AccessTokenEntity.isAccessTokenEntity = function (entity) { + if (!entity) { + return false; + } + return (entity.hasOwnProperty("homeAccountId") && + entity.hasOwnProperty("environment") && + entity.hasOwnProperty("credentialType") && + entity.hasOwnProperty("realm") && + entity.hasOwnProperty("clientId") && + entity.hasOwnProperty("secret") && + entity.hasOwnProperty("target") && + (entity["credentialType"] === exports.CredentialType.ACCESS_TOKEN || entity["credentialType"] === exports.CredentialType.ACCESS_TOKEN_WITH_AUTH_SCHEME)); + }; + return AccessTokenEntity; +}(CredentialEntity)); + +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. + */ +/** + * REFRESH_TOKEN Cache + * + * Key:Value Schema: + * + * Key Example: uid.utid-login.microsoftonline.com-refreshtoken-clientId-- + * + * Value: + * { + * homeAccountId: home account identifier for the auth scheme, + * environment: entity that issued the token, represented as a full host + * credentialType: Type of credential as a string, can be one of the following: RefreshToken, AccessToken, IdToken, Password, Cookie, Certificate, Other + * clientId: client ID of the application + * secret: Actual credential as a string + * familyId: Family ID identifier, '1' represents Microsoft Family + * realm: Full tenant or organizational identifier that the account belongs to + * target: Permissions that are included in the token, or for refresh tokens, the resource identifier. + * } + */ +var RefreshTokenEntity = /** @class */ (function (_super) { + __extends(RefreshTokenEntity, _super); + function RefreshTokenEntity() { + return _super !== null && _super.apply(this, arguments) || this; + } + /** + * Create RefreshTokenEntity + * @param homeAccountId + * @param authenticationResult + * @param clientId + * @param authority + */ + RefreshTokenEntity.createRefreshTokenEntity = function (homeAccountId, environment, refreshToken, clientId, familyId, userAssertionHash) { + var rtEntity = new RefreshTokenEntity(); + rtEntity.clientId = clientId; + rtEntity.credentialType = exports.CredentialType.REFRESH_TOKEN; + rtEntity.environment = environment; + rtEntity.homeAccountId = homeAccountId; + rtEntity.secret = refreshToken; + rtEntity.userAssertionHash = userAssertionHash; + if (familyId) + rtEntity.familyId = familyId; + return rtEntity; + }; + /** + * Validates an entity: checks for all expected params + * @param entity + */ + RefreshTokenEntity.isRefreshTokenEntity = function (entity) { + if (!entity) { + return false; + } + return (entity.hasOwnProperty("homeAccountId") && + entity.hasOwnProperty("environment") && + entity.hasOwnProperty("credentialType") && + entity.hasOwnProperty("clientId") && + entity.hasOwnProperty("secret") && + entity["credentialType"] === exports.CredentialType.REFRESH_TOKEN); + }; + return RefreshTokenEntity; +}(CredentialEntity)); + +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. + */ +/** + * InteractionRequiredServerErrorMessage contains string constants used by error codes and messages returned by the server indicating interaction is required + */ +var InteractionRequiredServerErrorMessage = [ + "interaction_required", + "consent_required", + "login_required" +]; +var InteractionRequiredAuthSubErrorMessage = [ + "message_only", + "additional_action", + "basic_action", + "user_password_expired", + "consent_required" +]; +/** + * Interaction required errors defined by the SDK + */ +var InteractionRequiredAuthErrorMessage = { + noTokensFoundError: { + code: "no_tokens_found", + desc: "No refresh token found in the cache. Please sign-in." + }, + native_account_unavailable: { + code: "native_account_unavailable", + desc: "The requested account is not available in the native broker. It may have been deleted or logged out. Please sign-in again using an interactive API." + } +}; +/** + * Error thrown when user interaction is required. + */ +var InteractionRequiredAuthError = /** @class */ (function (_super) { + __extends(InteractionRequiredAuthError, _super); + function InteractionRequiredAuthError(errorCode, errorMessage, subError, timestamp, traceId, correlationId, claims) { + var _this = _super.call(this, errorCode, errorMessage, subError) || this; + Object.setPrototypeOf(_this, InteractionRequiredAuthError.prototype); + _this.timestamp = timestamp || Constants.EMPTY_STRING; + _this.traceId = traceId || Constants.EMPTY_STRING; + _this.correlationId = correlationId || Constants.EMPTY_STRING; + _this.claims = claims || Constants.EMPTY_STRING; + _this.name = "InteractionRequiredAuthError"; + return _this; + } + /** + * Helper function used to determine if an error thrown by the server requires interaction to resolve + * @param errorCode + * @param errorString + * @param subError + */ + InteractionRequiredAuthError.isInteractionRequiredError = function (errorCode, errorString, subError) { + var isInteractionRequiredErrorCode = !!errorCode && InteractionRequiredServerErrorMessage.indexOf(errorCode) > -1; + var isInteractionRequiredSubError = !!subError && InteractionRequiredAuthSubErrorMessage.indexOf(subError) > -1; + var isInteractionRequiredErrorDesc = !!errorString && InteractionRequiredServerErrorMessage.some(function (irErrorCode) { + return errorString.indexOf(irErrorCode) > -1; + }); + return isInteractionRequiredErrorCode || isInteractionRequiredErrorDesc || isInteractionRequiredSubError; + }; + /** + * Creates an error thrown when the authorization code required for a token request is null or empty. + */ + InteractionRequiredAuthError.createNoTokensFoundError = function () { + return new InteractionRequiredAuthError(InteractionRequiredAuthErrorMessage.noTokensFoundError.code, InteractionRequiredAuthErrorMessage.noTokensFoundError.desc); + }; + /** + * Creates an error thrown when the native broker returns ACCOUNT_UNAVAILABLE status, indicating that the account was removed and interactive sign-in is required + * @returns + */ + InteractionRequiredAuthError.createNativeAccountUnavailableError = function () { + return new InteractionRequiredAuthError(InteractionRequiredAuthErrorMessage.native_account_unavailable.code, InteractionRequiredAuthErrorMessage.native_account_unavailable.desc); + }; + return InteractionRequiredAuthError; +}(AuthError)); + +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. + */ +var CacheRecord = /** @class */ (function () { + function CacheRecord(accountEntity, idTokenEntity, accessTokenEntity, refreshTokenEntity, appMetadataEntity) { + this.account = accountEntity || null; + this.idToken = idTokenEntity || null; + this.accessToken = accessTokenEntity || null; + this.refreshToken = refreshTokenEntity || null; + this.appMetadata = appMetadataEntity || null; + } + return CacheRecord; +}()); + +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. + */ +/** + * Class which provides helpers for OAuth 2.0 protocol specific values + */ +var ProtocolUtils = /** @class */ (function () { + function ProtocolUtils() { + } + /** + * Appends user state with random guid, or returns random guid. + * @param userState + * @param randomGuid + */ + ProtocolUtils.setRequestState = function (cryptoObj, userState, meta) { + var libraryState = ProtocolUtils.generateLibraryState(cryptoObj, meta); + return !StringUtils.isEmpty(userState) ? "" + libraryState + Constants.RESOURCE_DELIM + userState : libraryState; + }; + /** + * Generates the state value used by the common library. + * @param randomGuid + * @param cryptoObj + */ + ProtocolUtils.generateLibraryState = function (cryptoObj, meta) { + if (!cryptoObj) { + throw ClientAuthError.createNoCryptoObjectError("generateLibraryState"); + } + // Create a state object containing a unique id and the timestamp of the request creation + var stateObj = { + id: cryptoObj.createNewGuid() + }; + if (meta) { + stateObj.meta = meta; + } + var stateString = JSON.stringify(stateObj); + return cryptoObj.base64Encode(stateString); + }; + /** + * Parses the state into the RequestStateObject, which contains the LibraryState info and the state passed by the user. + * @param state + * @param cryptoObj + */ + ProtocolUtils.parseRequestState = function (cryptoObj, state) { + if (!cryptoObj) { + throw ClientAuthError.createNoCryptoObjectError("parseRequestState"); + } + if (StringUtils.isEmpty(state)) { + throw ClientAuthError.createInvalidStateError(state, "Null, undefined or empty state"); + } + try { + // Split the state between library state and user passed state and decode them separately + var splitState = state.split(Constants.RESOURCE_DELIM); + var libraryState = splitState[0]; + var userState = splitState.length > 1 ? splitState.slice(1).join(Constants.RESOURCE_DELIM) : Constants.EMPTY_STRING; + var libraryStateString = cryptoObj.base64Decode(libraryState); + var libraryStateObj = JSON.parse(libraryStateString); + return { + userRequestState: !StringUtils.isEmpty(userState) ? userState : Constants.EMPTY_STRING, + libraryState: libraryStateObj + }; + } + catch (e) { + throw ClientAuthError.createInvalidStateError(state, e); + } + }; + return ProtocolUtils; +}()); + +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. + */ +/** + * Url object class which can perform various transformations on url strings. + */ +var UrlString = /** @class */ (function () { + function UrlString(url) { + this._urlString = url; + if (StringUtils.isEmpty(this._urlString)) { + // Throws error if url is empty + throw ClientConfigurationError.createUrlEmptyError(); + } + if (StringUtils.isEmpty(this.getHash())) { + this._urlString = UrlString.canonicalizeUri(url); + } + } + Object.defineProperty(UrlString.prototype, "urlString", { + get: function () { + return this._urlString; + }, + enumerable: false, + configurable: true + }); + /** + * Ensure urls are lower case and end with a / character. + * @param url + */ + UrlString.canonicalizeUri = function (url) { + if (url) { + var lowerCaseUrl = url.toLowerCase(); + if (StringUtils.endsWith(lowerCaseUrl, "?")) { + lowerCaseUrl = lowerCaseUrl.slice(0, -1); + } + else if (StringUtils.endsWith(lowerCaseUrl, "?/")) { + lowerCaseUrl = lowerCaseUrl.slice(0, -2); + } + if (!StringUtils.endsWith(lowerCaseUrl, "/")) { + lowerCaseUrl += "/"; + } + return lowerCaseUrl; + } + return url; + }; + /** + * Throws if urlString passed is not a valid authority URI string. + */ + UrlString.prototype.validateAsUri = function () { + // Attempts to parse url for uri components + var components; + try { + components = this.getUrlComponents(); + } + catch (e) { + throw ClientConfigurationError.createUrlParseError(e); + } + // Throw error if URI or path segments are not parseable. + if (!components.HostNameAndPort || !components.PathSegments) { + throw ClientConfigurationError.createUrlParseError("Given url string: " + this.urlString); + } + // Throw error if uri is insecure. + if (!components.Protocol || components.Protocol.toLowerCase() !== "https:") { + throw ClientConfigurationError.createInsecureAuthorityUriError(this.urlString); + } + }; + /** + * Given a url and a query string return the url with provided query string appended + * @param url + * @param queryString + */ + UrlString.appendQueryString = function (url, queryString) { + if (StringUtils.isEmpty(queryString)) { + return url; + } + return url.indexOf("?") < 0 ? url + "?" + queryString : url + "&" + queryString; + }; + /** + * Returns a url with the hash removed + * @param url + */ + UrlString.removeHashFromUrl = function (url) { + return UrlString.canonicalizeUri(url.split("#")[0]); + }; + /** + * Given a url like https://a:b/common/d?e=f#g, and a tenantId, returns https://a:b/tenantId/d + * @param href The url + * @param tenantId The tenant id to replace + */ + UrlString.prototype.replaceTenantPath = function (tenantId) { + var urlObject = this.getUrlComponents(); + var pathArray = urlObject.PathSegments; + if (tenantId && (pathArray.length !== 0 && (pathArray[0] === AADAuthorityConstants.COMMON || pathArray[0] === AADAuthorityConstants.ORGANIZATIONS))) { + pathArray[0] = tenantId; + } + return UrlString.constructAuthorityUriFromObject(urlObject); + }; + /** + * Returns the anchor part(#) of the URL + */ + UrlString.prototype.getHash = function () { + return UrlString.parseHash(this.urlString); + }; + /** + * Parses out the components from a url string. + * @returns An object with the various components. Please cache this value insted of calling this multiple times on the same url. + */ + UrlString.prototype.getUrlComponents = function () { + // https://gist.github.com/curtisz/11139b2cfcaef4a261e0 + var regEx = RegExp("^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\\?([^#]*))?(#(.*))?"); + // If url string does not match regEx, we throw an error + var match = this.urlString.match(regEx); + if (!match) { + throw ClientConfigurationError.createUrlParseError("Given url string: " + this.urlString); + } + // Url component object + var urlComponents = { + Protocol: match[1], + HostNameAndPort: match[4], + AbsolutePath: match[5], + QueryString: match[7] + }; + var pathSegments = urlComponents.AbsolutePath.split("/"); + pathSegments = pathSegments.filter(function (val) { return val && val.length > 0; }); // remove empty elements + urlComponents.PathSegments = pathSegments; + if (!StringUtils.isEmpty(urlComponents.QueryString) && urlComponents.QueryString.endsWith("/")) { + urlComponents.QueryString = urlComponents.QueryString.substring(0, urlComponents.QueryString.length - 1); + } + return urlComponents; + }; + UrlString.getDomainFromUrl = function (url) { + var regEx = RegExp("^([^:/?#]+://)?([^/?#]*)"); + var match = url.match(regEx); + if (!match) { + throw ClientConfigurationError.createUrlParseError("Given url string: " + url); + } + return match[2]; + }; + UrlString.getAbsoluteUrl = function (relativeUrl, baseUrl) { + if (relativeUrl[0] === Constants.FORWARD_SLASH) { + var url = new UrlString(baseUrl); + var baseComponents = url.getUrlComponents(); + return baseComponents.Protocol + "//" + baseComponents.HostNameAndPort + relativeUrl; + } + return relativeUrl; + }; + /** + * Parses hash string from given string. Returns empty string if no hash symbol is found. + * @param hashString + */ + UrlString.parseHash = function (hashString) { + var hashIndex1 = hashString.indexOf("#"); + var hashIndex2 = hashString.indexOf("#/"); + if (hashIndex2 > -1) { + return hashString.substring(hashIndex2 + 2); + } + else if (hashIndex1 > -1) { + return hashString.substring(hashIndex1 + 1); + } + return Constants.EMPTY_STRING; + }; + /** + * Parses query string from given string. Returns empty string if no query symbol is found. + * @param queryString + */ + UrlString.parseQueryString = function (queryString) { + var queryIndex1 = queryString.indexOf("?"); + var queryIndex2 = queryString.indexOf("/?"); + if (queryIndex2 > -1) { + return queryString.substring(queryIndex2 + 2); + } + else if (queryIndex1 > -1) { + return queryString.substring(queryIndex1 + 1); + } + return Constants.EMPTY_STRING; + }; + UrlString.constructAuthorityUriFromObject = function (urlObject) { + return new UrlString(urlObject.Protocol + "//" + urlObject.HostNameAndPort + "/" + urlObject.PathSegments.join("/")); + }; + /** + * Returns URL hash as server auth code response object. + */ + UrlString.getDeserializedHash = function (hash) { + // Check if given hash is empty + if (StringUtils.isEmpty(hash)) { + return {}; + } + // Strip the # symbol if present + var parsedHash = UrlString.parseHash(hash); + // If # symbol was not present, above will return empty string, so give original hash value + var deserializedHash = StringUtils.queryStringToObject(StringUtils.isEmpty(parsedHash) ? hash : parsedHash); + // Check if deserialization didn't work + if (!deserializedHash) { + throw ClientAuthError.createHashNotDeserializedError(JSON.stringify(deserializedHash)); + } + return deserializedHash; + }; + /** + * Returns URL query string as server auth code response object. + */ + UrlString.getDeserializedQueryString = function (query) { + // Check if given query is empty + if (StringUtils.isEmpty(query)) { + return {}; + } + // Strip the ? symbol if present + var parsedQueryString = UrlString.parseQueryString(query); + // If ? symbol was not present, above will return empty string, so give original query value + var deserializedQueryString = StringUtils.queryStringToObject(StringUtils.isEmpty(parsedQueryString) ? query : parsedQueryString); + // Check if deserialization didn't work + if (!deserializedQueryString) { + throw ClientAuthError.createHashNotDeserializedError(JSON.stringify(deserializedQueryString)); + } + return deserializedQueryString; + }; + /** + * Check if the hash of the URL string contains known properties + */ + UrlString.hashContainsKnownProperties = function (hash) { + if (StringUtils.isEmpty(hash) || hash.indexOf("=") < 0) { + // Hash doesn't contain key/value pairs + return false; + } + var parameters = UrlString.getDeserializedHash(hash); + return !!(parameters.code || + parameters.error_description || + parameters.error || + parameters.state); + }; + return UrlString; +}()); + +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. + */ +/** + * Enumeration of operations that are instrumented by have their performance measured by the PerformanceClient. + * + * @export + * @enum {number} + */ +exports.PerformanceEvents = void 0; +(function (PerformanceEvents) { + /** + * acquireTokenByCode API (msal-browser and msal-node). + * Used to acquire tokens by trading an authorization code against the token endpoint. + */ + PerformanceEvents["AcquireTokenByCode"] = "acquireTokenByCode"; + /** + * acquireTokenByRefreshToken API (msal-browser and msal-node). + * Used to renew an access token using a refresh token against the token endpoint. + */ + PerformanceEvents["AcquireTokenByRefreshToken"] = "acquireTokenByRefreshToken"; + /** + * acquireTokenSilent API (msal-browser and msal-node). + * Used to silently acquire a new access token (from the cache or the network). + */ + PerformanceEvents["AcquireTokenSilent"] = "acquireTokenSilent"; + /** + * acquireTokenSilentAsync (msal-browser). + * Internal API for acquireTokenSilent. + */ + PerformanceEvents["AcquireTokenSilentAsync"] = "acquireTokenSilentAsync"; + /** + * acquireTokenPopup (msal-browser). + * Used to acquire a new access token interactively through pop ups + */ + PerformanceEvents["AcquireTokenPopup"] = "acquireTokenPopup"; + /** + * getPublicKeyThumbprint API in CryptoOpts class (msal-browser). + * Used to generate a public/private keypair and generate a public key thumbprint for pop requests. + */ + PerformanceEvents["CryptoOptsGetPublicKeyThumbprint"] = "cryptoOptsGetPublicKeyThumbprint"; + /** + * signJwt API in CryptoOpts class (msal-browser). + * Used to signed a pop token. + */ + PerformanceEvents["CryptoOptsSignJwt"] = "cryptoOptsSignJwt"; + /** + * acquireToken API in the SilentCacheClient class (msal-browser). + * Used to read access tokens from the cache. + */ + PerformanceEvents["SilentCacheClientAcquireToken"] = "silentCacheClientAcquireToken"; + /** + * acquireToken API in the SilentIframeClient class (msal-browser). + * Used to acquire a new set of tokens from the authorize endpoint in a hidden iframe. + */ + PerformanceEvents["SilentIframeClientAcquireToken"] = "silentIframeClientAcquireToken"; + /** + * acquireToken API in SilentRereshClient (msal-browser). + * Used to acquire a new set of tokens from the token endpoint using a refresh token. + */ + PerformanceEvents["SilentRefreshClientAcquireToken"] = "silentRefreshClientAcquireToken"; + /** + * ssoSilent API (msal-browser). + * Used to silently acquire an authorization code and set of tokens using a hidden iframe. + */ + PerformanceEvents["SsoSilent"] = "ssoSilent"; + /** + * getDiscoveredAuthority API in StandardInteractionClient class (msal-browser). + * Used to load authority metadata for a request. + */ + PerformanceEvents["StandardInteractionClientGetDiscoveredAuthority"] = "standardInteractionClientGetDiscoveredAuthority"; + /** + * acquireToken APIs in msal-browser. + * Used to make an /authorize endpoint call with native brokering enabled. + */ + PerformanceEvents["FetchAccountIdWithNativeBroker"] = "fetchAccountIdWithNativeBroker"; + /** + * acquireToken API in NativeInteractionClient class (msal-browser). + * Used to acquire a token from Native component when native brokering is enabled. + */ + PerformanceEvents["NativeInteractionClientAcquireToken"] = "nativeInteractionClientAcquireToken"; + /** + * Time spent creating default headers for requests to token endpoint + */ + PerformanceEvents["BaseClientCreateTokenRequestHeaders"] = "baseClientCreateTokenRequestHeaders"; + /** + * Used to measure the time taken for completing embedded-broker handshake (PW-Broker). + */ + PerformanceEvents["BrokerHandhshake"] = "brokerHandshake"; + /** + * acquireTokenByRefreshToken API in BrokerClientApplication (PW-Broker) . + */ + PerformanceEvents["AcquireTokenByRefreshTokenInBroker"] = "acquireTokenByRefreshTokenInBroker"; + /** + * Time taken for token acquisition by broker + */ + PerformanceEvents["AcquireTokenByBroker"] = "acquireTokenByBroker"; + /** + * Time spent on the network for refresh token acquisition + */ + PerformanceEvents["RefreshTokenClientExecuteTokenRequest"] = "refreshTokenClientExecuteTokenRequest"; + /** + * Time taken for acquiring refresh token , records RT size + */ + PerformanceEvents["RefreshTokenClientAcquireToken"] = "refreshTokenClientAcquireToken"; + /** + * Time taken for acquiring cached refresh token + */ + PerformanceEvents["RefreshTokenClientAcquireTokenWithCachedRefreshToken"] = "refreshTokenClientAcquireTokenWithCachedRefreshToken"; + /** + * acquireTokenByRefreshToken API in RefreshTokenClient (msal-common). + */ + PerformanceEvents["RefreshTokenClientAcquireTokenByRefreshToken"] = "refreshTokenClientAcquireTokenByRefreshToken"; + /** + * Helper function to create token request body in RefreshTokenClient (msal-common). + */ + PerformanceEvents["RefreshTokenClientCreateTokenRequestBody"] = "refreshTokenClientCreateTokenRequestBody"; + /** + * acquireTokenFromCache (msal-browser). + * Internal API for acquiring token from cache + */ + PerformanceEvents["AcquireTokenFromCache"] = "acquireTokenFromCache"; + /** + * acquireTokenBySilentIframe (msal-browser). + * Internal API for acquiring token by silent Iframe + */ + PerformanceEvents["AcquireTokenBySilentIframe"] = "acquireTokenBySilentIframe"; + /** + * Internal API for initializing base request in BaseInteractionClient (msal-browser) + */ + PerformanceEvents["InitializeBaseRequest"] = "initializeBaseRequest"; + /** + * Internal API for initializing silent request in SilentCacheClient (msal-browser) + */ + PerformanceEvents["InitializeSilentRequest"] = "initializeSilentRequest"; + PerformanceEvents["InitializeClientApplication"] = "initializeClientApplication"; + /** + * Helper function in SilentIframeClient class (msal-browser). + */ + PerformanceEvents["SilentIframeClientTokenHelper"] = "silentIframeClientTokenHelper"; + /** + * SilentHandler + */ + PerformanceEvents["SilentHandlerInitiateAuthRequest"] = "silentHandlerInitiateAuthRequest"; + PerformanceEvents["SilentHandlerMonitorIframeForHash"] = "silentHandlerMonitorIframeForHash"; + PerformanceEvents["SilentHandlerLoadFrame"] = "silentHandlerLoadFrame"; + /** + * Helper functions in StandardInteractionClient class (msal-browser) + */ + PerformanceEvents["StandardInteractionClientCreateAuthCodeClient"] = "standardInteractionClientCreateAuthCodeClient"; + PerformanceEvents["StandardInteractionClientGetClientConfiguration"] = "standardInteractionClientGetClientConfiguration"; + PerformanceEvents["StandardInteractionClientInitializeAuthorizationRequest"] = "standardInteractionClientInitializeAuthorizationRequest"; + PerformanceEvents["StandardInteractionClientInitializeAuthorizationCodeRequest"] = "standardInteractionClientInitializeAuthorizationCodeRequest"; + /** + * getAuthCodeUrl API (msal-browser and msal-node). + */ + PerformanceEvents["GetAuthCodeUrl"] = "getAuthCodeUrl"; + /** + * Functions from InteractionHandler (msal-browser) + */ + PerformanceEvents["HandleCodeResponseFromServer"] = "handleCodeResponseFromServer"; + PerformanceEvents["HandleCodeResponseFromHash"] = "handleCodeResponseFromHash"; + PerformanceEvents["UpdateTokenEndpointAuthority"] = "updateTokenEndpointAuthority"; + /** + * APIs in Authorization Code Client (msal-common) + */ + PerformanceEvents["AuthClientAcquireToken"] = "authClientAcquireToken"; + PerformanceEvents["AuthClientExecuteTokenRequest"] = "authClientExecuteTokenRequest"; + PerformanceEvents["AuthClientCreateTokenRequestBody"] = "authClientCreateTokenRequestBody"; + PerformanceEvents["AuthClientCreateQueryString"] = "authClientCreateQueryString"; + /** + * Generate functions in PopTokenGenerator (msal-common) + */ + PerformanceEvents["PopTokenGenerateCnf"] = "popTokenGenerateCnf"; + PerformanceEvents["PopTokenGenerateKid"] = "popTokenGenerateKid"; + /** + * handleServerTokenResponse API in ResponseHandler (msal-common) + */ + PerformanceEvents["HandleServerTokenResponse"] = "handleServerTokenResponse"; + /** + * Authority functions + */ + PerformanceEvents["AuthorityFactoryCreateDiscoveredInstance"] = "authorityFactoryCreateDiscoveredInstance"; + PerformanceEvents["AuthorityResolveEndpointsAsync"] = "authorityResolveEndpointsAsync"; + PerformanceEvents["AuthorityGetCloudDiscoveryMetadataFromNetwork"] = "authorityGetCloudDiscoveryMetadataFromNetwork"; + PerformanceEvents["AuthorityUpdateCloudDiscoveryMetadata"] = "authorityUpdateCloudDiscoveryMetadata"; + PerformanceEvents["AuthorityGetEndpointMetadataFromNetwork"] = "authorityGetEndpointMetadataFromNetwork"; + PerformanceEvents["AuthorityUpdateEndpointMetadata"] = "authorityUpdateEndpointMetadata"; + PerformanceEvents["AuthorityUpdateMetadataWithRegionalInformation"] = "authorityUpdateMetadataWithRegionalInformation"; + /** + * Region Discovery functions + */ + PerformanceEvents["RegionDiscoveryDetectRegion"] = "regionDiscoveryDetectRegion"; + PerformanceEvents["RegionDiscoveryGetRegionFromIMDS"] = "regionDiscoveryGetRegionFromIMDS"; + PerformanceEvents["RegionDiscoveryGetCurrentVersion"] = "regionDiscoveryGetCurrentVersion"; + PerformanceEvents["AcquireTokenByCodeAsync"] = "acquireTokenByCodeAsync"; + PerformanceEvents["GetEndpointMetadataFromNetwork"] = "getEndpointMetadataFromNetwork"; + PerformanceEvents["GetCloudDiscoveryMetadataFromNetworkMeasurement"] = "getCloudDiscoveryMetadataFromNetworkMeasurement"; + PerformanceEvents["HandleRedirectPromiseMeasurement"] = "handleRedirectPromiseMeasurement"; + PerformanceEvents["UpdateCloudDiscoveryMetadataMeasurement"] = "updateCloudDiscoveryMetadataMeasurement"; + PerformanceEvents["UsernamePasswordClientAcquireToken"] = "usernamePasswordClientAcquireToken"; + PerformanceEvents["NativeMessageHandlerHandshake"] = "nativeMessageHandlerHandshake"; +})(exports.PerformanceEvents || (exports.PerformanceEvents = {})); +/** + * State of the performance event. + * + * @export + * @enum {number} + */ +exports.PerformanceEventStatus = void 0; +(function (PerformanceEventStatus) { + PerformanceEventStatus[PerformanceEventStatus["NotStarted"] = 0] = "NotStarted"; + PerformanceEventStatus[PerformanceEventStatus["InProgress"] = 1] = "InProgress"; + PerformanceEventStatus[PerformanceEventStatus["Completed"] = 2] = "Completed"; +})(exports.PerformanceEventStatus || (exports.PerformanceEventStatus = {})); +var IntFields = new Set([ + "accessTokenSize", + "durationMs", + "idTokenSize", + "matsSilentStatus", + "matsHttpStatus", + "refreshTokenSize", + "queuedTimeMs", + "startTimeMs", + "status", +]); + +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. + */ +var KeyLocation; +(function (KeyLocation) { + KeyLocation["SW"] = "sw"; + KeyLocation["UHW"] = "uhw"; +})(KeyLocation || (KeyLocation = {})); +var PopTokenGenerator = /** @class */ (function () { + function PopTokenGenerator(cryptoUtils, performanceClient) { + this.cryptoUtils = cryptoUtils; + this.performanceClient = performanceClient; + } + /** + * Generates the req_cnf validated at the RP in the POP protocol for SHR parameters + * and returns an object containing the keyid, the full req_cnf string and the req_cnf string hash + * @param request + * @returns + */ + PopTokenGenerator.prototype.generateCnf = function (request) { + var _a, _b; + return __awaiter(this, void 0, void 0, function () { + var reqCnf, reqCnfString, _c; + return __generator(this, function (_d) { + switch (_d.label) { + case 0: + (_a = this.performanceClient) === null || _a === void 0 ? void 0 : _a.addQueueMeasurement(exports.PerformanceEvents.PopTokenGenerateCnf, request.correlationId); + (_b = this.performanceClient) === null || _b === void 0 ? void 0 : _b.setPreQueueTime(exports.PerformanceEvents.PopTokenGenerateKid, request.correlationId); + return [4 /*yield*/, this.generateKid(request)]; + case 1: + reqCnf = _d.sent(); + reqCnfString = this.cryptoUtils.base64Encode(JSON.stringify(reqCnf)); + _c = { + kid: reqCnf.kid, + reqCnfString: reqCnfString + }; + return [4 /*yield*/, this.cryptoUtils.hashString(reqCnfString)]; + case 2: return [2 /*return*/, (_c.reqCnfHash = _d.sent(), + _c)]; + } + }); + }); + }; + /** + * Generates key_id for a SHR token request + * @param request + * @returns + */ + PopTokenGenerator.prototype.generateKid = function (request) { + var _a; + return __awaiter(this, void 0, void 0, function () { + var kidThumbprint; + return __generator(this, function (_b) { + switch (_b.label) { + case 0: + (_a = this.performanceClient) === null || _a === void 0 ? void 0 : _a.addQueueMeasurement(exports.PerformanceEvents.PopTokenGenerateKid, request.correlationId); + return [4 /*yield*/, this.cryptoUtils.getPublicKeyThumbprint(request)]; + case 1: + kidThumbprint = _b.sent(); + return [2 /*return*/, { + kid: kidThumbprint, + xms_ksl: KeyLocation.SW + }]; + } + }); + }); + }; + /** + * Signs the POP access_token with the local generated key-pair + * @param accessToken + * @param request + * @returns + */ + PopTokenGenerator.prototype.signPopToken = function (accessToken, keyId, request) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2 /*return*/, this.signPayload(accessToken, keyId, request)]; + }); + }); + }; + /** + * Utility function to generate the signed JWT for an access_token + * @param payload + * @param kid + * @param request + * @param claims + * @returns + */ + PopTokenGenerator.prototype.signPayload = function (payload, keyId, request, claims) { + return __awaiter(this, void 0, void 0, function () { + var resourceRequestMethod, resourceRequestUri, shrClaims, shrNonce, resourceUrlString, resourceUrlComponents; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + resourceRequestMethod = request.resourceRequestMethod, resourceRequestUri = request.resourceRequestUri, shrClaims = request.shrClaims, shrNonce = request.shrNonce; + resourceUrlString = (resourceRequestUri) ? new UrlString(resourceRequestUri) : undefined; + resourceUrlComponents = resourceUrlString === null || resourceUrlString === void 0 ? void 0 : resourceUrlString.getUrlComponents(); + return [4 /*yield*/, this.cryptoUtils.signJwt(__assign({ at: payload, ts: TimeUtils.nowSeconds(), m: resourceRequestMethod === null || resourceRequestMethod === void 0 ? void 0 : resourceRequestMethod.toUpperCase(), u: resourceUrlComponents === null || resourceUrlComponents === void 0 ? void 0 : resourceUrlComponents.HostNameAndPort, nonce: shrNonce || this.cryptoUtils.createNewGuid(), p: resourceUrlComponents === null || resourceUrlComponents === void 0 ? void 0 : resourceUrlComponents.AbsolutePath, q: (resourceUrlComponents === null || resourceUrlComponents === void 0 ? void 0 : resourceUrlComponents.QueryString) ? [[], resourceUrlComponents.QueryString] : undefined, client_claims: shrClaims || undefined }, claims), keyId, request.correlationId)]; + case 1: return [2 /*return*/, _a.sent()]; + } + }); + }); + }; + return PopTokenGenerator; +}()); + +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. + */ +/** + * APP_METADATA Cache + * + * Key:Value Schema: + * + * Key: appmetadata-- + * + * Value: + * { + * clientId: client ID of the application + * environment: entity that issued the token, represented as a full host + * familyId: Family ID identifier, '1' represents Microsoft Family + * } + */ +var AppMetadataEntity = /** @class */ (function () { + function AppMetadataEntity() { + } + /** + * Generate AppMetadata Cache Key as per the schema: appmetadata-- + */ + AppMetadataEntity.prototype.generateAppMetadataKey = function () { + return AppMetadataEntity.generateAppMetadataCacheKey(this.environment, this.clientId); + }; + /** + * Generate AppMetadata Cache Key + */ + AppMetadataEntity.generateAppMetadataCacheKey = function (environment, clientId) { + var appMetaDataKeyArray = [ + APP_METADATA, + environment, + clientId, + ]; + return appMetaDataKeyArray.join(Separators.CACHE_KEY_SEPARATOR).toLowerCase(); + }; + /** + * Creates AppMetadataEntity + * @param clientId + * @param environment + * @param familyId + */ + AppMetadataEntity.createAppMetadataEntity = function (clientId, environment, familyId) { + var appMetadata = new AppMetadataEntity(); + appMetadata.clientId = clientId; + appMetadata.environment = environment; + if (familyId) { + appMetadata.familyId = familyId; + } + return appMetadata; + }; + /** + * Validates an entity: checks for all expected params + * @param entity + */ + AppMetadataEntity.isAppMetadataEntity = function (key, entity) { + if (!entity) { + return false; + } + return (key.indexOf(APP_METADATA) === 0 && + entity.hasOwnProperty("clientId") && + entity.hasOwnProperty("environment")); + }; + return AppMetadataEntity; +}()); + +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. + */ +/** + * This class instance helps track the memory changes facilitating + * decisions to read from and write to the persistent cache + */ var TokenCacheContext = /** @class */ (function () { + function TokenCacheContext(tokenCache, hasChanged) { + this.cache = tokenCache; + this.hasChanged = hasChanged; + } + Object.defineProperty(TokenCacheContext.prototype, "cacheHasChanged", { + /** + * boolean which indicates the changes in cache + */ + get: function () { + return this.hasChanged; + }, + enumerable: false, + configurable: true + }); + Object.defineProperty(TokenCacheContext.prototype, "tokenCache", { + /** + * function to retrieve the token cache + */ + get: function () { + return this.cache; + }, + enumerable: false, + configurable: true + }); + return TokenCacheContext; +}()); + +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. + */ +/** + * Class that handles response parsing. + */ +var ResponseHandler = /** @class */ (function () { + function ResponseHandler(clientId, cacheStorage, cryptoObj, logger, serializableCache, persistencePlugin, performanceClient) { + this.clientId = clientId; + this.cacheStorage = cacheStorage; + this.cryptoObj = cryptoObj; + this.logger = logger; + this.serializableCache = serializableCache; + this.persistencePlugin = persistencePlugin; + this.performanceClient = performanceClient; + } + /** + * Function which validates server authorization code response. + * @param serverResponseHash + * @param cachedState + * @param cryptoObj + */ + ResponseHandler.prototype.validateServerAuthorizationCodeResponse = function (serverResponseHash, cachedState, cryptoObj) { + if (!serverResponseHash.state || !cachedState) { + throw !serverResponseHash.state ? ClientAuthError.createStateNotFoundError("Server State") : ClientAuthError.createStateNotFoundError("Cached State"); + } + if (decodeURIComponent(serverResponseHash.state) !== decodeURIComponent(cachedState)) { + throw ClientAuthError.createStateMismatchError(); + } + // Check for error + if (serverResponseHash.error || serverResponseHash.error_description || serverResponseHash.suberror) { + if (InteractionRequiredAuthError.isInteractionRequiredError(serverResponseHash.error, serverResponseHash.error_description, serverResponseHash.suberror)) { + throw new InteractionRequiredAuthError(serverResponseHash.error || Constants.EMPTY_STRING, serverResponseHash.error_description, serverResponseHash.suberror, serverResponseHash.timestamp || Constants.EMPTY_STRING, serverResponseHash.trace_id || Constants.EMPTY_STRING, serverResponseHash.correlation_id || Constants.EMPTY_STRING, serverResponseHash.claims || Constants.EMPTY_STRING); + } + throw new ServerError(serverResponseHash.error || Constants.EMPTY_STRING, serverResponseHash.error_description, serverResponseHash.suberror); + } + if (serverResponseHash.client_info) { + buildClientInfo(serverResponseHash.client_info, cryptoObj); + } + }; + /** + * Function which validates server authorization token response. + * @param serverResponse + */ + ResponseHandler.prototype.validateTokenResponse = function (serverResponse) { + // Check for error + if (serverResponse.error || serverResponse.error_description || serverResponse.suberror) { + if (InteractionRequiredAuthError.isInteractionRequiredError(serverResponse.error, serverResponse.error_description, serverResponse.suberror)) { + throw new InteractionRequiredAuthError(serverResponse.error, serverResponse.error_description, serverResponse.suberror, serverResponse.timestamp || Constants.EMPTY_STRING, serverResponse.trace_id || Constants.EMPTY_STRING, serverResponse.correlation_id || Constants.EMPTY_STRING, serverResponse.claims || Constants.EMPTY_STRING); + } + var errString = serverResponse.error_codes + " - [" + serverResponse.timestamp + "]: " + serverResponse.error_description + " - Correlation ID: " + serverResponse.correlation_id + " - Trace ID: " + serverResponse.trace_id; + throw new ServerError(serverResponse.error, errString, serverResponse.suberror); + } + }; + /** + * Returns a constructed token response based on given string. Also manages the cache updates and cleanups. + * @param serverTokenResponse + * @param authority + */ + ResponseHandler.prototype.handleServerTokenResponse = function (serverTokenResponse, authority, reqTimestamp, request, authCodePayload, userAssertionHash, handlingRefreshTokenResponse, forceCacheRefreshTokenResponse, serverRequestId) { + var _a; + return __awaiter(this, void 0, void 0, function () { + var idTokenObj, authTime, requestStateObj, cacheRecord, cacheContext, key, account; + return __generator(this, function (_b) { + switch (_b.label) { + case 0: + (_a = this.performanceClient) === null || _a === void 0 ? void 0 : _a.addQueueMeasurement(exports.PerformanceEvents.HandleServerTokenResponse, serverTokenResponse.correlation_id); + if (serverTokenResponse.id_token) { + idTokenObj = new AuthToken(serverTokenResponse.id_token || Constants.EMPTY_STRING, this.cryptoObj); + // token nonce check (TODO: Add a warning if no nonce is given?) + if (authCodePayload && !StringUtils.isEmpty(authCodePayload.nonce)) { + if (idTokenObj.claims.nonce !== authCodePayload.nonce) { + throw ClientAuthError.createNonceMismatchError(); + } + } + // token max_age check + if (request.maxAge || (request.maxAge === 0)) { + authTime = idTokenObj.claims.auth_time; + if (!authTime) { + throw ClientAuthError.createAuthTimeNotFoundError(); + } + AuthToken.checkMaxAge(authTime, request.maxAge); + } + } + // generate homeAccountId + this.homeAccountIdentifier = AccountEntity.generateHomeAccountId(serverTokenResponse.client_info || Constants.EMPTY_STRING, authority.authorityType, this.logger, this.cryptoObj, idTokenObj); + if (!!authCodePayload && !!authCodePayload.state) { + requestStateObj = ProtocolUtils.parseRequestState(this.cryptoObj, authCodePayload.state); + } + // Add keyId from request to serverTokenResponse if defined + serverTokenResponse.key_id = serverTokenResponse.key_id || request.sshKid || undefined; + cacheRecord = this.generateCacheRecord(serverTokenResponse, authority, reqTimestamp, request, idTokenObj, userAssertionHash, authCodePayload); + _b.label = 1; + case 1: + _b.trys.push([1, , 5, 8]); + if (!(this.persistencePlugin && this.serializableCache)) return [3 /*break*/, 3]; + this.logger.verbose("Persistence enabled, calling beforeCacheAccess"); + cacheContext = new TokenCacheContext(this.serializableCache, true); + return [4 /*yield*/, this.persistencePlugin.beforeCacheAccess(cacheContext)]; + case 2: + _b.sent(); + _b.label = 3; + case 3: + /* + * When saving a refreshed tokens to the cache, it is expected that the account that was used is present in the cache. + * If not present, we should return null, as it's the case that another application called removeAccount in between + * the calls to getAllAccounts and acquireTokenSilent. We should not overwrite that removal, unless explicitly flagged by + * the developer, as in the case of refresh token flow used in ADAL Node to MSAL Node migration. + */ + if (handlingRefreshTokenResponse && !forceCacheRefreshTokenResponse && cacheRecord.account) { + key = cacheRecord.account.generateAccountKey(); + account = this.cacheStorage.getAccount(key); + if (!account) { + this.logger.warning("Account used to refresh tokens not in persistence, refreshed tokens will not be stored in the cache"); + return [2 /*return*/, ResponseHandler.generateAuthenticationResult(this.cryptoObj, authority, cacheRecord, false, request, idTokenObj, requestStateObj, undefined, serverRequestId)]; + } + } + return [4 /*yield*/, this.cacheStorage.saveCacheRecord(cacheRecord)]; + case 4: + _b.sent(); + return [3 /*break*/, 8]; + case 5: + if (!(this.persistencePlugin && this.serializableCache && cacheContext)) return [3 /*break*/, 7]; + this.logger.verbose("Persistence enabled, calling afterCacheAccess"); + return [4 /*yield*/, this.persistencePlugin.afterCacheAccess(cacheContext)]; + case 6: + _b.sent(); + _b.label = 7; + case 7: return [7 /*endfinally*/]; + case 8: return [2 /*return*/, ResponseHandler.generateAuthenticationResult(this.cryptoObj, authority, cacheRecord, false, request, idTokenObj, requestStateObj, serverTokenResponse, serverRequestId)]; + } + }); + }); + }; + /** + * Generates CacheRecord + * @param serverTokenResponse + * @param idTokenObj + * @param authority + */ + ResponseHandler.prototype.generateCacheRecord = function (serverTokenResponse, authority, reqTimestamp, request, idTokenObj, userAssertionHash, authCodePayload) { + var env = authority.getPreferredCache(); + if (StringUtils.isEmpty(env)) { + throw ClientAuthError.createInvalidCacheEnvironmentError(); + } + // IdToken: non AAD scenarios can have empty realm + var cachedIdToken; + var cachedAccount; + if (!StringUtils.isEmpty(serverTokenResponse.id_token) && !!idTokenObj) { + cachedIdToken = IdTokenEntity.createIdTokenEntity(this.homeAccountIdentifier, env, serverTokenResponse.id_token || Constants.EMPTY_STRING, this.clientId, idTokenObj.claims.tid || Constants.EMPTY_STRING); + cachedAccount = this.generateAccountEntity(serverTokenResponse, idTokenObj, authority, authCodePayload); + } + // AccessToken + var cachedAccessToken = null; + if (!StringUtils.isEmpty(serverTokenResponse.access_token)) { + // If scopes not returned in server response, use request scopes + var responseScopes = serverTokenResponse.scope ? ScopeSet.fromString(serverTokenResponse.scope) : new ScopeSet(request.scopes || []); + /* + * Use timestamp calculated before request + * Server may return timestamps as strings, parse to numbers if so. + */ + var expiresIn = (typeof serverTokenResponse.expires_in === "string" ? parseInt(serverTokenResponse.expires_in, 10) : serverTokenResponse.expires_in) || 0; + var extExpiresIn = (typeof serverTokenResponse.ext_expires_in === "string" ? parseInt(serverTokenResponse.ext_expires_in, 10) : serverTokenResponse.ext_expires_in) || 0; + var refreshIn = (typeof serverTokenResponse.refresh_in === "string" ? parseInt(serverTokenResponse.refresh_in, 10) : serverTokenResponse.refresh_in) || undefined; + var tokenExpirationSeconds = reqTimestamp + expiresIn; + var extendedTokenExpirationSeconds = tokenExpirationSeconds + extExpiresIn; + var refreshOnSeconds = refreshIn && refreshIn > 0 ? reqTimestamp + refreshIn : undefined; + // non AAD scenarios can have empty realm + cachedAccessToken = AccessTokenEntity.createAccessTokenEntity(this.homeAccountIdentifier, env, serverTokenResponse.access_token || Constants.EMPTY_STRING, this.clientId, idTokenObj ? idTokenObj.claims.tid || Constants.EMPTY_STRING : authority.tenant, responseScopes.printScopes(), tokenExpirationSeconds, extendedTokenExpirationSeconds, this.cryptoObj, refreshOnSeconds, serverTokenResponse.token_type, userAssertionHash, serverTokenResponse.key_id, request.claims, request.requestedClaimsHash); + } + // refreshToken + var cachedRefreshToken = null; + if (!StringUtils.isEmpty(serverTokenResponse.refresh_token)) { + cachedRefreshToken = RefreshTokenEntity.createRefreshTokenEntity(this.homeAccountIdentifier, env, serverTokenResponse.refresh_token || Constants.EMPTY_STRING, this.clientId, serverTokenResponse.foci, userAssertionHash); + } + // appMetadata + var cachedAppMetadata = null; + if (!StringUtils.isEmpty(serverTokenResponse.foci)) { + cachedAppMetadata = AppMetadataEntity.createAppMetadataEntity(this.clientId, env, serverTokenResponse.foci); + } + return new CacheRecord(cachedAccount, cachedIdToken, cachedAccessToken, cachedRefreshToken, cachedAppMetadata); + }; + /** + * Generate Account + * @param serverTokenResponse + * @param idToken + * @param authority + */ + ResponseHandler.prototype.generateAccountEntity = function (serverTokenResponse, idToken, authority, authCodePayload) { + var authorityType = authority.authorityType; + var cloudGraphHostName = authCodePayload ? authCodePayload.cloud_graph_host_name : Constants.EMPTY_STRING; + var msGraphhost = authCodePayload ? authCodePayload.msgraph_host : Constants.EMPTY_STRING; + // ADFS does not require client_info in the response + if (authorityType === exports.AuthorityType.Adfs) { + this.logger.verbose("Authority type is ADFS, creating ADFS account"); + return AccountEntity.createGenericAccount(this.homeAccountIdentifier, idToken, authority, cloudGraphHostName, msGraphhost); + } + // This fallback applies to B2C as well as they fall under an AAD account type. + if (StringUtils.isEmpty(serverTokenResponse.client_info) && authority.protocolMode === "AAD") { + throw ClientAuthError.createClientInfoEmptyError(); + } + return serverTokenResponse.client_info ? + AccountEntity.createAccount(serverTokenResponse.client_info, this.homeAccountIdentifier, idToken, authority, cloudGraphHostName, msGraphhost) : + AccountEntity.createGenericAccount(this.homeAccountIdentifier, idToken, authority, cloudGraphHostName, msGraphhost); + }; + /** + * Creates an @AuthenticationResult from @CacheRecord , @IdToken , and a boolean that states whether or not the result is from cache. + * + * Optionally takes a state string that is set as-is in the response. + * + * @param cacheRecord + * @param idTokenObj + * @param fromTokenCache + * @param stateString + */ + ResponseHandler.generateAuthenticationResult = function (cryptoObj, authority, cacheRecord, fromTokenCache, request, idTokenObj, requestState, serverTokenResponse, requestId) { + var _a, _b, _c; + return __awaiter(this, void 0, void 0, function () { + var accessToken, responseScopes, expiresOn, extExpiresOn, familyId, popTokenGenerator, _d, secret, keyId, uid, tid; + return __generator(this, function (_e) { + switch (_e.label) { + case 0: + accessToken = Constants.EMPTY_STRING; + responseScopes = []; + expiresOn = null; + familyId = Constants.EMPTY_STRING; + if (!cacheRecord.accessToken) return [3 /*break*/, 4]; + if (!(cacheRecord.accessToken.tokenType === exports.AuthenticationScheme.POP)) return [3 /*break*/, 2]; + popTokenGenerator = new PopTokenGenerator(cryptoObj); + _d = cacheRecord.accessToken, secret = _d.secret, keyId = _d.keyId; + if (!keyId) { + throw ClientAuthError.createKeyIdMissingError(); + } + return [4 /*yield*/, popTokenGenerator.signPopToken(secret, keyId, request)]; + case 1: + accessToken = _e.sent(); + return [3 /*break*/, 3]; + case 2: + accessToken = cacheRecord.accessToken.secret; + _e.label = 3; + case 3: + responseScopes = ScopeSet.fromString(cacheRecord.accessToken.target).asArray(); + expiresOn = new Date(Number(cacheRecord.accessToken.expiresOn) * 1000); + extExpiresOn = new Date(Number(cacheRecord.accessToken.extendedExpiresOn) * 1000); + _e.label = 4; + case 4: + if (cacheRecord.appMetadata) { + familyId = cacheRecord.appMetadata.familyId === THE_FAMILY_ID ? THE_FAMILY_ID : Constants.EMPTY_STRING; + } + uid = (idTokenObj === null || idTokenObj === void 0 ? void 0 : idTokenObj.claims.oid) || (idTokenObj === null || idTokenObj === void 0 ? void 0 : idTokenObj.claims.sub) || Constants.EMPTY_STRING; + tid = (idTokenObj === null || idTokenObj === void 0 ? void 0 : idTokenObj.claims.tid) || Constants.EMPTY_STRING; + // for hybrid + native bridge enablement, send back the native account Id + if ((serverTokenResponse === null || serverTokenResponse === void 0 ? void 0 : serverTokenResponse.spa_accountid) && !!cacheRecord.account) { + cacheRecord.account.nativeAccountId = serverTokenResponse === null || serverTokenResponse === void 0 ? void 0 : serverTokenResponse.spa_accountid; + } + return [2 /*return*/, { + authority: authority.canonicalAuthority, + uniqueId: uid, + tenantId: tid, + scopes: responseScopes, + account: cacheRecord.account ? cacheRecord.account.getAccountInfo() : null, + idToken: idTokenObj ? idTokenObj.rawToken : Constants.EMPTY_STRING, + idTokenClaims: idTokenObj ? idTokenObj.claims : {}, + accessToken: accessToken, + fromCache: fromTokenCache, + expiresOn: expiresOn, + correlationId: request.correlationId, + requestId: requestId || Constants.EMPTY_STRING, + extExpiresOn: extExpiresOn, + familyId: familyId, + tokenType: ((_a = cacheRecord.accessToken) === null || _a === void 0 ? void 0 : _a.tokenType) || Constants.EMPTY_STRING, + state: requestState ? requestState.userRequestState : Constants.EMPTY_STRING, + cloudGraphHostName: ((_b = cacheRecord.account) === null || _b === void 0 ? void 0 : _b.cloudGraphHostName) || Constants.EMPTY_STRING, + msGraphHost: ((_c = cacheRecord.account) === null || _c === void 0 ? void 0 : _c.msGraphHost) || Constants.EMPTY_STRING, + code: serverTokenResponse === null || serverTokenResponse === void 0 ? void 0 : serverTokenResponse.spa_code, + fromNativeBroker: false, + }]; + } + }); + }); + }; + return ResponseHandler; +}()); + +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. + */ +/** + * Oauth2.0 Authorization Code client + */ +var AuthorizationCodeClient = /** @class */ (function (_super) { + __extends(AuthorizationCodeClient, _super); + function AuthorizationCodeClient(configuration, performanceClient) { + var _this = _super.call(this, configuration, performanceClient) || this; + // Flag to indicate if client is for hybrid spa auth code redemption + _this.includeRedirectUri = true; + return _this; + } + /** + * Creates the URL of the authorization request letting the user input credentials and consent to the + * application. The URL target the /authorize endpoint of the authority configured in the + * application object. + * + * Once the user inputs their credentials and consents, the authority will send a response to the redirect URI + * sent in the request and should contain an authorization code, which can then be used to acquire tokens via + * acquireToken(AuthorizationCodeRequest) + * @param request + */ + AuthorizationCodeClient.prototype.getAuthCodeUrl = function (request) { + var _a, _b; + return __awaiter(this, void 0, void 0, function () { + var queryString; + return __generator(this, function (_c) { + switch (_c.label) { + case 0: + (_a = this.performanceClient) === null || _a === void 0 ? void 0 : _a.addQueueMeasurement(exports.PerformanceEvents.GetAuthCodeUrl, request.correlationId); + (_b = this.performanceClient) === null || _b === void 0 ? void 0 : _b.setPreQueueTime(exports.PerformanceEvents.AuthClientCreateQueryString, request.correlationId); + return [4 /*yield*/, this.createAuthCodeUrlQueryString(request)]; + case 1: + queryString = _c.sent(); + return [2 /*return*/, UrlString.appendQueryString(this.authority.authorizationEndpoint, queryString)]; + } + }); + }); + }; + /** + * API to acquire a token in exchange of 'authorization_code` acquired by the user in the first leg of the + * authorization_code_grant + * @param request + */ + AuthorizationCodeClient.prototype.acquireToken = function (request, authCodePayload) { + var _a, _b, _c, _d, _e, _f; + return __awaiter(this, void 0, void 0, function () { + var atsMeasurement, reqTimestamp, response, requestId, httpVerAuthority, responseHandler; + var _this = this; + return __generator(this, function (_g) { + switch (_g.label) { + case 0: + if (!request || !request.code) { + throw ClientAuthError.createTokenRequestCannotBeMadeError(); + } + (_a = this.performanceClient) === null || _a === void 0 ? void 0 : _a.addQueueMeasurement(exports.PerformanceEvents.AuthClientAcquireToken, request.correlationId); + atsMeasurement = (_b = this.performanceClient) === null || _b === void 0 ? void 0 : _b.startMeasurement("AuthCodeClientAcquireToken", request.correlationId); + this.logger.info("in acquireToken call in auth-code client"); + reqTimestamp = TimeUtils.nowSeconds(); + (_c = this.performanceClient) === null || _c === void 0 ? void 0 : _c.setPreQueueTime(exports.PerformanceEvents.AuthClientExecuteTokenRequest, request.correlationId); + return [4 /*yield*/, this.executeTokenRequest(this.authority, request)]; + case 1: + response = _g.sent(); + requestId = (_d = response.headers) === null || _d === void 0 ? void 0 : _d[exports.HeaderNames.X_MS_REQUEST_ID]; + httpVerAuthority = (_e = response.headers) === null || _e === void 0 ? void 0 : _e[exports.HeaderNames.X_MS_HTTP_VERSION]; + if (httpVerAuthority) { + atsMeasurement === null || atsMeasurement === void 0 ? void 0 : atsMeasurement.addStaticFields({ + httpVerAuthority: httpVerAuthority + }); + } + responseHandler = new ResponseHandler(this.config.authOptions.clientId, this.cacheManager, this.cryptoUtils, this.logger, this.config.serializableCache, this.config.persistencePlugin, this.performanceClient); + // Validate response. This function throws a server error if an error is returned by the server. + responseHandler.validateTokenResponse(response.body); + (_f = this.performanceClient) === null || _f === void 0 ? void 0 : _f.setPreQueueTime(exports.PerformanceEvents.HandleServerTokenResponse, request.correlationId); + return [2 /*return*/, responseHandler.handleServerTokenResponse(response.body, this.authority, reqTimestamp, request, authCodePayload, undefined, undefined, undefined, requestId).then(function (result) { + atsMeasurement === null || atsMeasurement === void 0 ? void 0 : atsMeasurement.endMeasurement({ + success: true + }); + return result; + }) + .catch(function (error) { + _this.logger.verbose("Error in fetching token in ACC", request.correlationId); + atsMeasurement === null || atsMeasurement === void 0 ? void 0 : atsMeasurement.endMeasurement({ + errorCode: error.errorCode, + subErrorCode: error.subError, + success: false + }); + throw error; + })]; + } + }); + }); + }; + /** + * Handles the hash fragment response from public client code request. Returns a code response used by + * the client to exchange for a token in acquireToken. + * @param hashFragment + */ + AuthorizationCodeClient.prototype.handleFragmentResponse = function (hashFragment, cachedState) { + // Handle responses. + var responseHandler = new ResponseHandler(this.config.authOptions.clientId, this.cacheManager, this.cryptoUtils, this.logger, null, null); + // Deserialize hash fragment response parameters. + var hashUrlString = new UrlString(hashFragment); + // Deserialize hash fragment response parameters. + var serverParams = UrlString.getDeserializedHash(hashUrlString.getHash()); + // Get code response + responseHandler.validateServerAuthorizationCodeResponse(serverParams, cachedState, this.cryptoUtils); + // throw when there is no auth code in the response + if (!serverParams.code) { + throw ClientAuthError.createNoAuthCodeInServerResponseError(); + } + return __assign(__assign({}, serverParams), { + // Code param is optional in ServerAuthorizationCodeResponse but required in AuthorizationCodePaylod + code: serverParams.code }); + }; + /** + * Used to log out the current user, and redirect the user to the postLogoutRedirectUri. + * Default behaviour is to redirect the user to `window.location.href`. + * @param authorityUri + */ + AuthorizationCodeClient.prototype.getLogoutUri = function (logoutRequest) { + // Throw error if logoutRequest is null/undefined + if (!logoutRequest) { + throw ClientConfigurationError.createEmptyLogoutRequestError(); + } + var queryString = this.createLogoutUrlQueryString(logoutRequest); + // Construct logout URI + return UrlString.appendQueryString(this.authority.endSessionEndpoint, queryString); + }; + /** + * Executes POST request to token endpoint + * @param authority + * @param request + */ + AuthorizationCodeClient.prototype.executeTokenRequest = function (authority, request) { + var _a, _b; + return __awaiter(this, void 0, void 0, function () { + var queryParametersString, endpoint, requestBody, ccsCredential, clientInfo, headers, thumbprint; + return __generator(this, function (_c) { + switch (_c.label) { + case 0: + (_a = this.performanceClient) === null || _a === void 0 ? void 0 : _a.addQueueMeasurement(exports.PerformanceEvents.AuthClientExecuteTokenRequest, request.correlationId); + (_b = this.performanceClient) === null || _b === void 0 ? void 0 : _b.setPreQueueTime(exports.PerformanceEvents.AuthClientCreateTokenRequestBody, request.correlationId); + queryParametersString = this.createTokenQueryParameters(request); + endpoint = UrlString.appendQueryString(authority.tokenEndpoint, queryParametersString); + return [4 /*yield*/, this.createTokenRequestBody(request)]; + case 1: + requestBody = _c.sent(); + ccsCredential = undefined; + if (request.clientInfo) { + try { + clientInfo = buildClientInfo(request.clientInfo, this.cryptoUtils); + ccsCredential = { + credential: "" + clientInfo.uid + Separators.CLIENT_INFO_SEPARATOR + clientInfo.utid, + type: exports.CcsCredentialType.HOME_ACCOUNT_ID + }; + } + catch (e) { + this.logger.verbose("Could not parse client info for CCS Header: " + e); + } + } + headers = this.createTokenRequestHeaders(ccsCredential || request.ccsCredential); + thumbprint = { + clientId: this.config.authOptions.clientId, + authority: authority.canonicalAuthority, + scopes: request.scopes, + claims: request.claims, + authenticationScheme: request.authenticationScheme, + resourceRequestMethod: request.resourceRequestMethod, + resourceRequestUri: request.resourceRequestUri, + shrClaims: request.shrClaims, + sshKid: request.sshKid + }; + return [2 /*return*/, this.executePostToTokenEndpoint(endpoint, requestBody, headers, thumbprint)]; + } + }); + }); + }; + /** + * Generates a map for all the params to be sent to the service + * @param request + */ + AuthorizationCodeClient.prototype.createTokenRequestBody = function (request) { + var _a, _b; + return __awaiter(this, void 0, void 0, function () { + var parameterBuilder, clientAssertion, popTokenGenerator, reqCnfData, correlationId, ccsCred, clientInfo, clientInfo; + var _c; + return __generator(this, function (_d) { + switch (_d.label) { + case 0: + (_a = this.performanceClient) === null || _a === void 0 ? void 0 : _a.addQueueMeasurement(exports.PerformanceEvents.AuthClientCreateTokenRequestBody, request.correlationId); + parameterBuilder = new RequestParameterBuilder(); + parameterBuilder.addClientId(this.config.authOptions.clientId); + /* + * For hybrid spa flow, there will be a code but no verifier + * In this scenario, don't include redirect uri as auth code will not be bound to redirect URI + */ + if (!this.includeRedirectUri) { + // Just validate + RequestValidator.validateRedirectUri(request.redirectUri); + } + else { + // Validate and include redirect uri + parameterBuilder.addRedirectUri(request.redirectUri); + } + // Add scope array, parameter builder will add default scopes and dedupe + parameterBuilder.addScopes(request.scopes); + // add code: user set, not validated + parameterBuilder.addAuthorizationCode(request.code); + // Add library metadata + parameterBuilder.addLibraryInfo(this.config.libraryInfo); + parameterBuilder.addApplicationTelemetry(this.config.telemetry.application); + parameterBuilder.addThrottling(); + if (this.serverTelemetryManager) { + parameterBuilder.addServerTelemetry(this.serverTelemetryManager); + } + // add code_verifier if passed + if (request.codeVerifier) { + parameterBuilder.addCodeVerifier(request.codeVerifier); + } + if (this.config.clientCredentials.clientSecret) { + parameterBuilder.addClientSecret(this.config.clientCredentials.clientSecret); + } + if (this.config.clientCredentials.clientAssertion) { + clientAssertion = this.config.clientCredentials.clientAssertion; + parameterBuilder.addClientAssertion(clientAssertion.assertion); + parameterBuilder.addClientAssertionType(clientAssertion.assertionType); + } + parameterBuilder.addGrantType(GrantType.AUTHORIZATION_CODE_GRANT); + parameterBuilder.addClientInfo(); + if (!(request.authenticationScheme === exports.AuthenticationScheme.POP)) return [3 /*break*/, 2]; + popTokenGenerator = new PopTokenGenerator(this.cryptoUtils, this.performanceClient); + (_b = this.performanceClient) === null || _b === void 0 ? void 0 : _b.setPreQueueTime(exports.PerformanceEvents.PopTokenGenerateCnf, request.correlationId); + return [4 /*yield*/, popTokenGenerator.generateCnf(request)]; + case 1: + reqCnfData = _d.sent(); + // SPA PoP requires full Base64Url encoded req_cnf string (unhashed) + parameterBuilder.addPopToken(reqCnfData.reqCnfString); + return [3 /*break*/, 3]; + case 2: + if (request.authenticationScheme === exports.AuthenticationScheme.SSH) { + if (request.sshJwk) { + parameterBuilder.addSshJwk(request.sshJwk); + } + else { + throw ClientConfigurationError.createMissingSshJwkError(); + } + } + _d.label = 3; + case 3: + correlationId = request.correlationId || this.config.cryptoInterface.createNewGuid(); + parameterBuilder.addCorrelationId(correlationId); + if (!StringUtils.isEmptyObj(request.claims) || this.config.authOptions.clientCapabilities && this.config.authOptions.clientCapabilities.length > 0) { + parameterBuilder.addClaims(request.claims, this.config.authOptions.clientCapabilities); + } + ccsCred = undefined; + if (request.clientInfo) { + try { + clientInfo = buildClientInfo(request.clientInfo, this.cryptoUtils); + ccsCred = { + credential: "" + clientInfo.uid + Separators.CLIENT_INFO_SEPARATOR + clientInfo.utid, + type: exports.CcsCredentialType.HOME_ACCOUNT_ID + }; + } + catch (e) { + this.logger.verbose("Could not parse client info for CCS Header: " + e); + } + } + else { + ccsCred = request.ccsCredential; + } + // Adds these as parameters in the request instead of headers to prevent CORS preflight request + if (this.config.systemOptions.preventCorsPreflight && ccsCred) { + switch (ccsCred.type) { + case exports.CcsCredentialType.HOME_ACCOUNT_ID: + try { + clientInfo = buildClientInfoFromHomeAccountId(ccsCred.credential); + parameterBuilder.addCcsOid(clientInfo); + } + catch (e) { + this.logger.verbose("Could not parse home account ID for CCS Header: " + e); + } + break; + case exports.CcsCredentialType.UPN: + parameterBuilder.addCcsUpn(ccsCred.credential); + break; + } + } + if (request.tokenBodyParameters) { + parameterBuilder.addExtraQueryParameters(request.tokenBodyParameters); + } + // Add hybrid spa parameters if not already provided + if (request.enableSpaAuthorizationCode && (!request.tokenBodyParameters || !request.tokenBodyParameters[exports.AADServerParamKeys.RETURN_SPA_CODE])) { + parameterBuilder.addExtraQueryParameters((_c = {}, + _c[exports.AADServerParamKeys.RETURN_SPA_CODE] = "1", + _c)); + } + return [2 /*return*/, parameterBuilder.createQueryString()]; + } + }); + }); + }; + /** + * This API validates the `AuthorizationCodeUrlRequest` and creates a URL + * @param request + */ + AuthorizationCodeClient.prototype.createAuthCodeUrlQueryString = function (request) { + var _a; + return __awaiter(this, void 0, void 0, function () { + var parameterBuilder, requestScopes, correlationId, accountSid, accountLoginHintClaim, clientInfo, clientInfo, clientInfo, popTokenGenerator, reqCnfData; + return __generator(this, function (_b) { + switch (_b.label) { + case 0: + (_a = this.performanceClient) === null || _a === void 0 ? void 0 : _a.addQueueMeasurement(exports.PerformanceEvents.AuthClientCreateQueryString, request.correlationId); + parameterBuilder = new RequestParameterBuilder(); + parameterBuilder.addClientId(this.config.authOptions.clientId); + requestScopes = __spreadArrays(request.scopes || [], request.extraScopesToConsent || []); + parameterBuilder.addScopes(requestScopes); + // validate the redirectUri (to be a non null value) + parameterBuilder.addRedirectUri(request.redirectUri); + correlationId = request.correlationId || this.config.cryptoInterface.createNewGuid(); + parameterBuilder.addCorrelationId(correlationId); + // add response_mode. If not passed in it defaults to query. + parameterBuilder.addResponseMode(request.responseMode); + // add response_type = code + parameterBuilder.addResponseTypeCode(); + // add library info parameters + parameterBuilder.addLibraryInfo(this.config.libraryInfo); + parameterBuilder.addApplicationTelemetry(this.config.telemetry.application); + // add client_info=1 + parameterBuilder.addClientInfo(); + if (request.codeChallenge && request.codeChallengeMethod) { + parameterBuilder.addCodeChallengeParams(request.codeChallenge, request.codeChallengeMethod); + } + if (request.prompt) { + parameterBuilder.addPrompt(request.prompt); + } + if (request.domainHint) { + parameterBuilder.addDomainHint(request.domainHint); + } + // Add sid or loginHint with preference for login_hint claim (in request) -> sid -> loginHint (upn/email) -> username of AccountInfo object + if (request.prompt !== PromptValue.SELECT_ACCOUNT) { + // AAD will throw if prompt=select_account is passed with an account hint + if (request.sid && request.prompt === PromptValue.NONE) { + // SessionID is only used in silent calls + this.logger.verbose("createAuthCodeUrlQueryString: Prompt is none, adding sid from request"); + parameterBuilder.addSid(request.sid); + } + else if (request.account) { + accountSid = this.extractAccountSid(request.account); + accountLoginHintClaim = this.extractLoginHint(request.account); + // If login_hint claim is present, use it over sid/username + if (accountLoginHintClaim) { + this.logger.verbose("createAuthCodeUrlQueryString: login_hint claim present on account"); + parameterBuilder.addLoginHint(accountLoginHintClaim); + try { + clientInfo = buildClientInfoFromHomeAccountId(request.account.homeAccountId); + parameterBuilder.addCcsOid(clientInfo); + } + catch (e) { + this.logger.verbose("createAuthCodeUrlQueryString: Could not parse home account ID for CCS Header"); + } + } + else if (accountSid && request.prompt === PromptValue.NONE) { + /* + * If account and loginHint are provided, we will check account first for sid before adding loginHint + * SessionId is only used in silent calls + */ + this.logger.verbose("createAuthCodeUrlQueryString: Prompt is none, adding sid from account"); + parameterBuilder.addSid(accountSid); + try { + clientInfo = buildClientInfoFromHomeAccountId(request.account.homeAccountId); + parameterBuilder.addCcsOid(clientInfo); + } + catch (e) { + this.logger.verbose("createAuthCodeUrlQueryString: Could not parse home account ID for CCS Header"); + } + } + else if (request.loginHint) { + this.logger.verbose("createAuthCodeUrlQueryString: Adding login_hint from request"); + parameterBuilder.addLoginHint(request.loginHint); + parameterBuilder.addCcsUpn(request.loginHint); + } + else if (request.account.username) { + // Fallback to account username if provided + this.logger.verbose("createAuthCodeUrlQueryString: Adding login_hint from account"); + parameterBuilder.addLoginHint(request.account.username); + try { + clientInfo = buildClientInfoFromHomeAccountId(request.account.homeAccountId); + parameterBuilder.addCcsOid(clientInfo); + } + catch (e) { + this.logger.verbose("createAuthCodeUrlQueryString: Could not parse home account ID for CCS Header"); + } + } + } + else if (request.loginHint) { + this.logger.verbose("createAuthCodeUrlQueryString: No account, adding login_hint from request"); + parameterBuilder.addLoginHint(request.loginHint); + parameterBuilder.addCcsUpn(request.loginHint); + } + } + else { + this.logger.verbose("createAuthCodeUrlQueryString: Prompt is select_account, ignoring account hints"); + } + if (request.nonce) { + parameterBuilder.addNonce(request.nonce); + } + if (request.state) { + parameterBuilder.addState(request.state); + } + if (!StringUtils.isEmpty(request.claims) || this.config.authOptions.clientCapabilities && this.config.authOptions.clientCapabilities.length > 0) { + parameterBuilder.addClaims(request.claims, this.config.authOptions.clientCapabilities); + } + if (request.extraQueryParameters) { + parameterBuilder.addExtraQueryParameters(request.extraQueryParameters); + } + if (!request.nativeBroker) return [3 /*break*/, 2]; + // signal ests that this is a WAM call + parameterBuilder.addNativeBroker(); + if (!(request.authenticationScheme === exports.AuthenticationScheme.POP)) return [3 /*break*/, 2]; + popTokenGenerator = new PopTokenGenerator(this.cryptoUtils); + return [4 /*yield*/, popTokenGenerator.generateCnf(request)]; + case 1: + reqCnfData = _b.sent(); + parameterBuilder.addPopToken(reqCnfData.reqCnfString); + _b.label = 2; + case 2: return [2 /*return*/, parameterBuilder.createQueryString()]; + } + }); + }); + }; + /** + * This API validates the `EndSessionRequest` and creates a URL + * @param request + */ + AuthorizationCodeClient.prototype.createLogoutUrlQueryString = function (request) { + var parameterBuilder = new RequestParameterBuilder(); + if (request.postLogoutRedirectUri) { + parameterBuilder.addPostLogoutRedirectUri(request.postLogoutRedirectUri); + } + if (request.correlationId) { + parameterBuilder.addCorrelationId(request.correlationId); + } + if (request.idTokenHint) { + parameterBuilder.addIdTokenHint(request.idTokenHint); + } + if (request.state) { + parameterBuilder.addState(request.state); + } + if (request.logoutHint) { + parameterBuilder.addLogoutHint(request.logoutHint); + } + if (request.extraQueryParameters) { + parameterBuilder.addExtraQueryParameters(request.extraQueryParameters); + } + return parameterBuilder.createQueryString(); + }; + /** + * Helper to get sid from account. Returns null if idTokenClaims are not present or sid is not present. + * @param account + */ + AuthorizationCodeClient.prototype.extractAccountSid = function (account) { + var _a; + return ((_a = account.idTokenClaims) === null || _a === void 0 ? void 0 : _a.sid) || null; + }; + AuthorizationCodeClient.prototype.extractLoginHint = function (account) { + var _a; + return ((_a = account.idTokenClaims) === null || _a === void 0 ? void 0 : _a.login_hint) || null; + }; + return AuthorizationCodeClient; +}(BaseClient)); + +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. + */ +/** + * OAuth2.0 Device code client + */ +var DeviceCodeClient = /** @class */ (function (_super) { + __extends(DeviceCodeClient, _super); + function DeviceCodeClient(configuration) { + return _super.call(this, configuration) || this; + } + /** + * Gets device code from device code endpoint, calls back to with device code response, and + * polls token endpoint to exchange device code for tokens + * @param request + */ + DeviceCodeClient.prototype.acquireToken = function (request) { + return __awaiter(this, void 0, void 0, function () { + var deviceCodeResponse, reqTimestamp, response, responseHandler; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: return [4 /*yield*/, this.getDeviceCode(request)]; + case 1: + deviceCodeResponse = _a.sent(); + request.deviceCodeCallback(deviceCodeResponse); + reqTimestamp = TimeUtils.nowSeconds(); + return [4 /*yield*/, this.acquireTokenWithDeviceCode(request, deviceCodeResponse)]; + case 2: + response = _a.sent(); + responseHandler = new ResponseHandler(this.config.authOptions.clientId, this.cacheManager, this.cryptoUtils, this.logger, this.config.serializableCache, this.config.persistencePlugin); + // Validate response. This function throws a server error if an error is returned by the server. + responseHandler.validateTokenResponse(response); + return [4 /*yield*/, responseHandler.handleServerTokenResponse(response, this.authority, reqTimestamp, request)]; + case 3: return [2 /*return*/, _a.sent()]; + } + }); + }); + }; + /** + * Creates device code request and executes http GET + * @param request + */ + DeviceCodeClient.prototype.getDeviceCode = function (request) { + return __awaiter(this, void 0, void 0, function () { + var queryParametersString, endpoint, queryString, headers, thumbprint; + return __generator(this, function (_a) { + queryParametersString = this.createExtraQueryParameters(request); + endpoint = UrlString.appendQueryString(this.authority.deviceCodeEndpoint, queryParametersString); + queryString = this.createQueryString(request); + headers = this.createTokenRequestHeaders(); + thumbprint = { + clientId: this.config.authOptions.clientId, + authority: request.authority, + scopes: request.scopes, + claims: request.claims, + authenticationScheme: request.authenticationScheme, + resourceRequestMethod: request.resourceRequestMethod, + resourceRequestUri: request.resourceRequestUri, + shrClaims: request.shrClaims, + sshKid: request.sshKid + }; + return [2 /*return*/, this.executePostRequestToDeviceCodeEndpoint(endpoint, queryString, headers, thumbprint)]; + }); + }); + }; + /** + * Creates query string for the device code request + * @param request + */ + DeviceCodeClient.prototype.createExtraQueryParameters = function (request) { + var parameterBuilder = new RequestParameterBuilder(); + if (request.extraQueryParameters) { + parameterBuilder.addExtraQueryParameters(request.extraQueryParameters); + } + return parameterBuilder.createQueryString(); + }; + /** + * Executes POST request to device code endpoint + * @param deviceCodeEndpoint + * @param queryString + * @param headers + */ + DeviceCodeClient.prototype.executePostRequestToDeviceCodeEndpoint = function (deviceCodeEndpoint, queryString, headers, thumbprint) { + return __awaiter(this, void 0, void 0, function () { + var _a, userCode, deviceCode, verificationUri, expiresIn, interval, message; + return __generator(this, function (_b) { + switch (_b.label) { + case 0: return [4 /*yield*/, this.networkManager.sendPostRequest(thumbprint, deviceCodeEndpoint, { + body: queryString, + headers: headers + })]; + case 1: + _a = (_b.sent()).body, userCode = _a.user_code, deviceCode = _a.device_code, verificationUri = _a.verification_uri, expiresIn = _a.expires_in, interval = _a.interval, message = _a.message; + return [2 /*return*/, { + userCode: userCode, + deviceCode: deviceCode, + verificationUri: verificationUri, + expiresIn: expiresIn, + interval: interval, + message: message + }]; + } + }); + }); + }; + /** + * Create device code endpoint query parameters and returns string + */ + DeviceCodeClient.prototype.createQueryString = function (request) { + var parameterBuilder = new RequestParameterBuilder(); + parameterBuilder.addScopes(request.scopes); + parameterBuilder.addClientId(this.config.authOptions.clientId); + if (request.extraQueryParameters) { + parameterBuilder.addExtraQueryParameters(request.extraQueryParameters); + } + if (!StringUtils.isEmpty(request.claims) || this.config.authOptions.clientCapabilities && this.config.authOptions.clientCapabilities.length > 0) { + parameterBuilder.addClaims(request.claims, this.config.authOptions.clientCapabilities); + } + return parameterBuilder.createQueryString(); + }; + /** + * Breaks the polling with specific conditions. + * @param request CommonDeviceCodeRequest + * @param deviceCodeResponse DeviceCodeResponse + */ + DeviceCodeClient.prototype.continuePolling = function (deviceCodeExpirationTime, userSpecifiedTimeout, userSpecifiedCancelFlag) { + if (userSpecifiedCancelFlag) { + this.logger.error("Token request cancelled by setting DeviceCodeRequest.cancel = true"); + throw ClientAuthError.createDeviceCodeCancelledError(); + } + else if (userSpecifiedTimeout && userSpecifiedTimeout < deviceCodeExpirationTime && TimeUtils.nowSeconds() > userSpecifiedTimeout) { + this.logger.error("User defined timeout for device code polling reached. The timeout was set for " + userSpecifiedTimeout); + throw ClientAuthError.createUserTimeoutReachedError(); + } + else if (TimeUtils.nowSeconds() > deviceCodeExpirationTime) { + if (userSpecifiedTimeout) { + this.logger.verbose("User specified timeout ignored as the device code has expired before the timeout elapsed. The user specified timeout was set for " + userSpecifiedTimeout); + } + this.logger.error("Device code expired. Expiration time of device code was " + deviceCodeExpirationTime); + throw ClientAuthError.createDeviceCodeExpiredError(); + } + return true; + }; + /** + * Creates token request with device code response and polls token endpoint at interval set by the device code + * response + * @param request + * @param deviceCodeResponse + */ + DeviceCodeClient.prototype.acquireTokenWithDeviceCode = function (request, deviceCodeResponse) { + return __awaiter(this, void 0, void 0, function () { + var queryParametersString, endpoint, requestBody, headers, userSpecifiedTimeout, deviceCodeExpirationTime, pollingIntervalMilli, thumbprint, response; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + queryParametersString = this.createTokenQueryParameters(request); + endpoint = UrlString.appendQueryString(this.authority.tokenEndpoint, queryParametersString); + requestBody = this.createTokenRequestBody(request, deviceCodeResponse); + headers = this.createTokenRequestHeaders(); + userSpecifiedTimeout = request.timeout ? TimeUtils.nowSeconds() + request.timeout : undefined; + deviceCodeExpirationTime = TimeUtils.nowSeconds() + deviceCodeResponse.expiresIn; + pollingIntervalMilli = deviceCodeResponse.interval * 1000; + _a.label = 1; + case 1: + if (!this.continuePolling(deviceCodeExpirationTime, userSpecifiedTimeout, request.cancel)) return [3 /*break*/, 8]; + thumbprint = { + clientId: this.config.authOptions.clientId, + authority: request.authority, + scopes: request.scopes, + claims: request.claims, + authenticationScheme: request.authenticationScheme, + resourceRequestMethod: request.resourceRequestMethod, + resourceRequestUri: request.resourceRequestUri, + shrClaims: request.shrClaims, + sshKid: request.sshKid + }; + return [4 /*yield*/, this.executePostToTokenEndpoint(endpoint, requestBody, headers, thumbprint)]; + case 2: + response = _a.sent(); + if (!(response.body && response.body.error)) return [3 /*break*/, 6]; + if (!(response.body.error === Constants.AUTHORIZATION_PENDING)) return [3 /*break*/, 4]; + this.logger.info("Authorization pending. Continue polling."); + return [4 /*yield*/, TimeUtils.delay(pollingIntervalMilli)]; + case 3: + _a.sent(); + return [3 /*break*/, 5]; + case 4: + // for any other error, throw + this.logger.info("Unexpected error in polling from the server"); + throw ServerError.createPostRequestFailed(response.body.error); + case 5: return [3 /*break*/, 7]; + case 6: + this.logger.verbose("Authorization completed successfully. Polling stopped."); + return [2 /*return*/, response.body]; + case 7: return [3 /*break*/, 1]; + case 8: + /* + * The above code should've thrown by this point, but to satisfy TypeScript, + * and in the rare case the conditionals in continuePolling() may not catch everything... + */ + this.logger.error("Polling stopped for unknown reasons."); + throw ClientAuthError.createDeviceCodeUnknownError(); + } + }); + }); + }; + /** + * Creates query parameters and converts to string. + * @param request + * @param deviceCodeResponse + */ + DeviceCodeClient.prototype.createTokenRequestBody = function (request, deviceCodeResponse) { + var requestParameters = new RequestParameterBuilder(); + requestParameters.addScopes(request.scopes); + requestParameters.addClientId(this.config.authOptions.clientId); + requestParameters.addGrantType(GrantType.DEVICE_CODE_GRANT); + requestParameters.addDeviceCode(deviceCodeResponse.deviceCode); + var correlationId = request.correlationId || this.config.cryptoInterface.createNewGuid(); + requestParameters.addCorrelationId(correlationId); + requestParameters.addClientInfo(); + requestParameters.addLibraryInfo(this.config.libraryInfo); + requestParameters.addApplicationTelemetry(this.config.telemetry.application); + requestParameters.addThrottling(); + if (this.serverTelemetryManager) { + requestParameters.addServerTelemetry(this.serverTelemetryManager); + } + if (!StringUtils.isEmptyObj(request.claims) || this.config.authOptions.clientCapabilities && this.config.authOptions.clientCapabilities.length > 0) { + requestParameters.addClaims(request.claims, this.config.authOptions.clientCapabilities); + } + return requestParameters.createQueryString(); + }; + return DeviceCodeClient; +}(BaseClient)); + +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. + */ +/** + * OAuth2.0 refresh token client + */ +var RefreshTokenClient = /** @class */ (function (_super) { + __extends(RefreshTokenClient, _super); + function RefreshTokenClient(configuration, performanceClient) { + return _super.call(this, configuration, performanceClient) || this; + } + RefreshTokenClient.prototype.acquireToken = function (request) { + var _a, _b, _c, _d, _e, _f, _g; + return __awaiter(this, void 0, void 0, function () { + var atsMeasurement, reqTimestamp, response, httpVerToken, requestId, responseHandler; + var _this = this; + return __generator(this, function (_h) { + switch (_h.label) { + case 0: + (_a = this.performanceClient) === null || _a === void 0 ? void 0 : _a.addQueueMeasurement(exports.PerformanceEvents.RefreshTokenClientAcquireToken, request.correlationId); + atsMeasurement = (_b = this.performanceClient) === null || _b === void 0 ? void 0 : _b.startMeasurement(exports.PerformanceEvents.RefreshTokenClientAcquireToken, request.correlationId); + this.logger.verbose("RefreshTokenClientAcquireToken called", request.correlationId); + reqTimestamp = TimeUtils.nowSeconds(); + (_c = this.performanceClient) === null || _c === void 0 ? void 0 : _c.setPreQueueTime(exports.PerformanceEvents.RefreshTokenClientExecuteTokenRequest, request.correlationId); + return [4 /*yield*/, this.executeTokenRequest(request, this.authority)]; + case 1: + response = _h.sent(); + httpVerToken = (_d = response.headers) === null || _d === void 0 ? void 0 : _d[exports.HeaderNames.X_MS_HTTP_VERSION]; + atsMeasurement === null || atsMeasurement === void 0 ? void 0 : atsMeasurement.addStaticFields({ + refreshTokenSize: ((_e = response.body.refresh_token) === null || _e === void 0 ? void 0 : _e.length) || 0, + }); + if (httpVerToken) { + atsMeasurement === null || atsMeasurement === void 0 ? void 0 : atsMeasurement.addStaticFields({ + httpVerToken: httpVerToken, + }); + } + requestId = (_f = response.headers) === null || _f === void 0 ? void 0 : _f[exports.HeaderNames.X_MS_REQUEST_ID]; + responseHandler = new ResponseHandler(this.config.authOptions.clientId, this.cacheManager, this.cryptoUtils, this.logger, this.config.serializableCache, this.config.persistencePlugin); + responseHandler.validateTokenResponse(response.body); + (_g = this.performanceClient) === null || _g === void 0 ? void 0 : _g.setPreQueueTime(exports.PerformanceEvents.HandleServerTokenResponse, request.correlationId); + return [2 /*return*/, responseHandler.handleServerTokenResponse(response.body, this.authority, reqTimestamp, request, undefined, undefined, true, request.forceCache, requestId).then(function (result) { + atsMeasurement === null || atsMeasurement === void 0 ? void 0 : atsMeasurement.endMeasurement({ + success: true + }); + return result; + }) + .catch(function (error) { + _this.logger.verbose("Error in fetching refresh token", request.correlationId); + atsMeasurement === null || atsMeasurement === void 0 ? void 0 : atsMeasurement.endMeasurement({ + errorCode: error.errorCode, + subErrorCode: error.subError, + success: false + }); + throw error; + })]; + } + }); + }); + }; + /** + * Gets cached refresh token and attaches to request, then calls acquireToken API + * @param request + */ + RefreshTokenClient.prototype.acquireTokenByRefreshToken = function (request) { + var _a, _b, _c, _d; + return __awaiter(this, void 0, void 0, function () { + var isFOCI, noFamilyRTInCache, clientMismatchErrorWithFamilyRT; + return __generator(this, function (_e) { + // Cannot renew token if no request object is given. + if (!request) { + throw ClientConfigurationError.createEmptyTokenRequestError(); + } + (_a = this.performanceClient) === null || _a === void 0 ? void 0 : _a.addQueueMeasurement(exports.PerformanceEvents.RefreshTokenClientAcquireTokenByRefreshToken, request.correlationId); + // We currently do not support silent flow for account === null use cases; This will be revisited for confidential flow usecases + if (!request.account) { + throw ClientAuthError.createNoAccountInSilentRequestError(); + } + isFOCI = this.cacheManager.isAppMetadataFOCI(request.account.environment); + // if the app is part of the family, retrive a Family refresh token if present and make a refreshTokenRequest + if (isFOCI) { + try { + (_b = this.performanceClient) === null || _b === void 0 ? void 0 : _b.setPreQueueTime(exports.PerformanceEvents.RefreshTokenClientAcquireTokenWithCachedRefreshToken, request.correlationId); + return [2 /*return*/, this.acquireTokenWithCachedRefreshToken(request, true)]; + } + catch (e) { + noFamilyRTInCache = e instanceof InteractionRequiredAuthError && e.errorCode === InteractionRequiredAuthErrorMessage.noTokensFoundError.code; + clientMismatchErrorWithFamilyRT = e instanceof ServerError && e.errorCode === Errors.INVALID_GRANT_ERROR && e.subError === Errors.CLIENT_MISMATCH_ERROR; + // if family Refresh Token (FRT) cache acquisition fails or if client_mismatch error is seen with FRT, reattempt with application Refresh Token (ART) + if (noFamilyRTInCache || clientMismatchErrorWithFamilyRT) { + (_c = this.performanceClient) === null || _c === void 0 ? void 0 : _c.setPreQueueTime(exports.PerformanceEvents.RefreshTokenClientAcquireTokenWithCachedRefreshToken, request.correlationId); + return [2 /*return*/, this.acquireTokenWithCachedRefreshToken(request, false)]; + // throw in all other cases + } + else { + throw e; + } + } + } + // fall back to application refresh token acquisition + (_d = this.performanceClient) === null || _d === void 0 ? void 0 : _d.setPreQueueTime(exports.PerformanceEvents.RefreshTokenClientAcquireTokenWithCachedRefreshToken, request.correlationId); + return [2 /*return*/, this.acquireTokenWithCachedRefreshToken(request, false)]; + }); + }); + }; + /** + * makes a network call to acquire tokens by exchanging RefreshToken available in userCache; throws if refresh token is not cached + * @param request + */ + RefreshTokenClient.prototype.acquireTokenWithCachedRefreshToken = function (request, foci) { + var _a, _b, _c; + return __awaiter(this, void 0, void 0, function () { + var atsMeasurement, refreshToken, refreshTokenRequest; + return __generator(this, function (_d) { + (_a = this.performanceClient) === null || _a === void 0 ? void 0 : _a.addQueueMeasurement(exports.PerformanceEvents.RefreshTokenClientAcquireTokenWithCachedRefreshToken, request.correlationId); + atsMeasurement = (_b = this.performanceClient) === null || _b === void 0 ? void 0 : _b.startMeasurement(exports.PerformanceEvents.RefreshTokenClientAcquireTokenWithCachedRefreshToken, request.correlationId); + this.logger.verbose("RefreshTokenClientAcquireTokenWithCachedRefreshToken called", request.correlationId); + refreshToken = this.cacheManager.getRefreshToken(request.account, foci); + if (!refreshToken) { + atsMeasurement === null || atsMeasurement === void 0 ? void 0 : atsMeasurement.discardMeasurement(); + throw InteractionRequiredAuthError.createNoTokensFoundError(); + } + // attach cached RT size to the current measurement + atsMeasurement === null || atsMeasurement === void 0 ? void 0 : atsMeasurement.endMeasurement({ + success: true + }); + refreshTokenRequest = __assign(__assign({}, request), { refreshToken: refreshToken.secret, authenticationScheme: request.authenticationScheme || exports.AuthenticationScheme.BEARER, ccsCredential: { + credential: request.account.homeAccountId, + type: exports.CcsCredentialType.HOME_ACCOUNT_ID + } }); + (_c = this.performanceClient) === null || _c === void 0 ? void 0 : _c.setPreQueueTime(exports.PerformanceEvents.RefreshTokenClientAcquireToken, request.correlationId); + return [2 /*return*/, this.acquireToken(refreshTokenRequest)]; + }); + }); + }; + /** + * Constructs the network message and makes a NW call to the underlying secure token service + * @param request + * @param authority + */ + RefreshTokenClient.prototype.executeTokenRequest = function (request, authority) { + var _a, _b, _c; + return __awaiter(this, void 0, void 0, function () { + var acquireTokenMeasurement, queryParametersString, endpoint, requestBody, headers, thumbprint; + return __generator(this, function (_d) { + switch (_d.label) { + case 0: + (_a = this.performanceClient) === null || _a === void 0 ? void 0 : _a.addQueueMeasurement(exports.PerformanceEvents.RefreshTokenClientExecuteTokenRequest, request.correlationId); + acquireTokenMeasurement = (_b = this.performanceClient) === null || _b === void 0 ? void 0 : _b.startMeasurement(exports.PerformanceEvents.RefreshTokenClientExecuteTokenRequest, request.correlationId); + (_c = this.performanceClient) === null || _c === void 0 ? void 0 : _c.setPreQueueTime(exports.PerformanceEvents.RefreshTokenClientCreateTokenRequestBody, request.correlationId); + queryParametersString = this.createTokenQueryParameters(request); + endpoint = UrlString.appendQueryString(authority.tokenEndpoint, queryParametersString); + return [4 /*yield*/, this.createTokenRequestBody(request)]; + case 1: + requestBody = _d.sent(); + headers = this.createTokenRequestHeaders(request.ccsCredential); + thumbprint = { + clientId: this.config.authOptions.clientId, + authority: authority.canonicalAuthority, + scopes: request.scopes, + claims: request.claims, + authenticationScheme: request.authenticationScheme, + resourceRequestMethod: request.resourceRequestMethod, + resourceRequestUri: request.resourceRequestUri, + shrClaims: request.shrClaims, + sshKid: request.sshKid + }; + return [2 /*return*/, this.executePostToTokenEndpoint(endpoint, requestBody, headers, thumbprint) + .then(function (result) { + acquireTokenMeasurement === null || acquireTokenMeasurement === void 0 ? void 0 : acquireTokenMeasurement.endMeasurement({ + success: true + }); + return result; + }) + .catch(function (error) { + acquireTokenMeasurement === null || acquireTokenMeasurement === void 0 ? void 0 : acquireTokenMeasurement.endMeasurement({ + success: false + }); + throw error; + })]; + } + }); + }); + }; + /** + * Helper function to create the token request body + * @param request + */ + RefreshTokenClient.prototype.createTokenRequestBody = function (request) { + var _a, _b, _c; + return __awaiter(this, void 0, void 0, function () { + var correlationId, acquireTokenMeasurement, parameterBuilder, clientAssertion, popTokenGenerator, reqCnfData, clientInfo; + return __generator(this, function (_d) { + switch (_d.label) { + case 0: + (_a = this.performanceClient) === null || _a === void 0 ? void 0 : _a.addQueueMeasurement(exports.PerformanceEvents.RefreshTokenClientCreateTokenRequestBody, request.correlationId); + correlationId = request.correlationId; + acquireTokenMeasurement = (_b = this.performanceClient) === null || _b === void 0 ? void 0 : _b.startMeasurement(exports.PerformanceEvents.BaseClientCreateTokenRequestHeaders, correlationId); + parameterBuilder = new RequestParameterBuilder(); + parameterBuilder.addClientId(this.config.authOptions.clientId); + parameterBuilder.addScopes(request.scopes); + parameterBuilder.addGrantType(GrantType.REFRESH_TOKEN_GRANT); + parameterBuilder.addClientInfo(); + parameterBuilder.addLibraryInfo(this.config.libraryInfo); + parameterBuilder.addApplicationTelemetry(this.config.telemetry.application); + parameterBuilder.addThrottling(); + if (this.serverTelemetryManager) { + parameterBuilder.addServerTelemetry(this.serverTelemetryManager); + } + parameterBuilder.addCorrelationId(correlationId); + parameterBuilder.addRefreshToken(request.refreshToken); + if (this.config.clientCredentials.clientSecret) { + parameterBuilder.addClientSecret(this.config.clientCredentials.clientSecret); + } + if (this.config.clientCredentials.clientAssertion) { + clientAssertion = this.config.clientCredentials.clientAssertion; + parameterBuilder.addClientAssertion(clientAssertion.assertion); + parameterBuilder.addClientAssertionType(clientAssertion.assertionType); + } + if (!(request.authenticationScheme === exports.AuthenticationScheme.POP)) return [3 /*break*/, 2]; + popTokenGenerator = new PopTokenGenerator(this.cryptoUtils, this.performanceClient); + (_c = this.performanceClient) === null || _c === void 0 ? void 0 : _c.setPreQueueTime(exports.PerformanceEvents.PopTokenGenerateCnf, request.correlationId); + return [4 /*yield*/, popTokenGenerator.generateCnf(request)]; + case 1: + reqCnfData = _d.sent(); + // SPA PoP requires full Base64Url encoded req_cnf string (unhashed) + parameterBuilder.addPopToken(reqCnfData.reqCnfString); + return [3 /*break*/, 3]; + case 2: + if (request.authenticationScheme === exports.AuthenticationScheme.SSH) { + if (request.sshJwk) { + parameterBuilder.addSshJwk(request.sshJwk); + } + else { + acquireTokenMeasurement === null || acquireTokenMeasurement === void 0 ? void 0 : acquireTokenMeasurement.endMeasurement({ + success: false + }); + throw ClientConfigurationError.createMissingSshJwkError(); + } + } + _d.label = 3; + case 3: + if (!StringUtils.isEmptyObj(request.claims) || this.config.authOptions.clientCapabilities && this.config.authOptions.clientCapabilities.length > 0) { + parameterBuilder.addClaims(request.claims, this.config.authOptions.clientCapabilities); + } + if (this.config.systemOptions.preventCorsPreflight && request.ccsCredential) { + switch (request.ccsCredential.type) { + case exports.CcsCredentialType.HOME_ACCOUNT_ID: + try { + clientInfo = buildClientInfoFromHomeAccountId(request.ccsCredential.credential); + parameterBuilder.addCcsOid(clientInfo); + } + catch (e) { + this.logger.verbose("Could not parse home account ID for CCS Header: " + e); + } + break; + case exports.CcsCredentialType.UPN: + parameterBuilder.addCcsUpn(request.ccsCredential.credential); + break; + } + } + acquireTokenMeasurement === null || acquireTokenMeasurement === void 0 ? void 0 : acquireTokenMeasurement.endMeasurement({ + success: true + }); + return [2 /*return*/, parameterBuilder.createQueryString()]; + } + }); + }); + }; + return RefreshTokenClient; +}(BaseClient)); + +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. + */ +/** + * OAuth2.0 client credential grant + */ +var ClientCredentialClient = /** @class */ (function (_super) { + __extends(ClientCredentialClient, _super); + function ClientCredentialClient(configuration, appTokenProvider) { + var _this = _super.call(this, configuration) || this; + _this.appTokenProvider = appTokenProvider; + return _this; + } + /** + * Public API to acquire a token with ClientCredential Flow for Confidential clients + * @param request + */ + ClientCredentialClient.prototype.acquireToken = function (request) { + return __awaiter(this, void 0, void 0, function () { + var cachedAuthenticationResult; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + this.scopeSet = new ScopeSet(request.scopes || []); + if (!request.skipCache) return [3 /*break*/, 2]; + return [4 /*yield*/, this.executeTokenRequest(request, this.authority)]; + case 1: return [2 /*return*/, _a.sent()]; + case 2: return [4 /*yield*/, this.getCachedAuthenticationResult(request)]; + case 3: + cachedAuthenticationResult = _a.sent(); + if (!cachedAuthenticationResult) return [3 /*break*/, 4]; + return [2 /*return*/, cachedAuthenticationResult]; + case 4: return [4 /*yield*/, this.executeTokenRequest(request, this.authority)]; + case 5: return [2 /*return*/, _a.sent()]; + } + }); + }); + }; + /** + * looks up cache if the tokens are cached already + */ + ClientCredentialClient.prototype.getCachedAuthenticationResult = function (request) { + var _a, _b; + return __awaiter(this, void 0, void 0, function () { + var cachedAccessToken; + return __generator(this, function (_c) { + switch (_c.label) { + case 0: + cachedAccessToken = this.readAccessTokenFromCache(); + if (!cachedAccessToken) { + (_a = this.serverTelemetryManager) === null || _a === void 0 ? void 0 : _a.setCacheOutcome(CacheOutcome.NO_CACHED_ACCESS_TOKEN); + return [2 /*return*/, null]; + } + if (TimeUtils.isTokenExpired(cachedAccessToken.expiresOn, this.config.systemOptions.tokenRenewalOffsetSeconds)) { + (_b = this.serverTelemetryManager) === null || _b === void 0 ? void 0 : _b.setCacheOutcome(CacheOutcome.CACHED_ACCESS_TOKEN_EXPIRED); + return [2 /*return*/, null]; + } + return [4 /*yield*/, ResponseHandler.generateAuthenticationResult(this.cryptoUtils, this.authority, { + account: null, + idToken: null, + accessToken: cachedAccessToken, + refreshToken: null, + appMetadata: null + }, true, request)]; + case 1: return [2 /*return*/, _c.sent()]; + } + }); + }); + }; + /** + * Reads access token from the cache + */ + ClientCredentialClient.prototype.readAccessTokenFromCache = function () { + var accessTokenFilter = { + homeAccountId: Constants.EMPTY_STRING, + environment: this.authority.canonicalAuthorityUrlComponents.HostNameAndPort, + credentialType: exports.CredentialType.ACCESS_TOKEN, + clientId: this.config.authOptions.clientId, + realm: this.authority.tenant, + target: ScopeSet.createSearchScopes(this.scopeSet.asArray()) + }; + var accessTokens = this.cacheManager.getAccessTokensByFilter(accessTokenFilter); + if (accessTokens.length < 1) { + return null; + } + else if (accessTokens.length > 1) { + throw ClientAuthError.createMultipleMatchingTokensInCacheError(); + } + return accessTokens[0]; + }; + /** + * Makes a network call to request the token from the service + * @param request + * @param authority + */ + ClientCredentialClient.prototype.executeTokenRequest = function (request, authority) { + return __awaiter(this, void 0, void 0, function () { + var serverTokenResponse, reqTimestamp, appTokenPropviderParameters, appTokenProviderResult, queryParametersString, endpoint, requestBody, headers, thumbprint, response, responseHandler, tokenResponse; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + if (!this.appTokenProvider) return [3 /*break*/, 2]; + this.logger.info("Using appTokenProvider extensibility."); + appTokenPropviderParameters = { + correlationId: request.correlationId, + tenantId: this.config.authOptions.authority.tenant, + scopes: request.scopes, + claims: request.claims, + }; + reqTimestamp = TimeUtils.nowSeconds(); + return [4 /*yield*/, this.appTokenProvider(appTokenPropviderParameters)]; + case 1: + appTokenProviderResult = _a.sent(); + serverTokenResponse = { + access_token: appTokenProviderResult.accessToken, + expires_in: appTokenProviderResult.expiresInSeconds, + refresh_in: appTokenProviderResult.refreshInSeconds, + token_type: exports.AuthenticationScheme.BEARER + }; + return [3 /*break*/, 4]; + case 2: + queryParametersString = this.createTokenQueryParameters(request); + endpoint = UrlString.appendQueryString(authority.tokenEndpoint, queryParametersString); + requestBody = this.createTokenRequestBody(request); + headers = this.createTokenRequestHeaders(); + thumbprint = { + clientId: this.config.authOptions.clientId, + authority: request.authority, + scopes: request.scopes, + claims: request.claims, + authenticationScheme: request.authenticationScheme, + resourceRequestMethod: request.resourceRequestMethod, + resourceRequestUri: request.resourceRequestUri, + shrClaims: request.shrClaims, + sshKid: request.sshKid + }; + reqTimestamp = TimeUtils.nowSeconds(); + return [4 /*yield*/, this.executePostToTokenEndpoint(endpoint, requestBody, headers, thumbprint)]; + case 3: + response = _a.sent(); + serverTokenResponse = response.body; + _a.label = 4; + case 4: + responseHandler = new ResponseHandler(this.config.authOptions.clientId, this.cacheManager, this.cryptoUtils, this.logger, this.config.serializableCache, this.config.persistencePlugin); + responseHandler.validateTokenResponse(serverTokenResponse); + return [4 /*yield*/, responseHandler.handleServerTokenResponse(serverTokenResponse, this.authority, reqTimestamp, request)]; + case 5: + tokenResponse = _a.sent(); + return [2 /*return*/, tokenResponse]; + } + }); + }); + }; + /** + * generate the request to the server in the acceptable format + * @param request + */ + ClientCredentialClient.prototype.createTokenRequestBody = function (request) { + var parameterBuilder = new RequestParameterBuilder(); + parameterBuilder.addClientId(this.config.authOptions.clientId); + parameterBuilder.addScopes(request.scopes, false); + parameterBuilder.addGrantType(GrantType.CLIENT_CREDENTIALS_GRANT); + parameterBuilder.addLibraryInfo(this.config.libraryInfo); + parameterBuilder.addApplicationTelemetry(this.config.telemetry.application); + parameterBuilder.addThrottling(); + if (this.serverTelemetryManager) { + parameterBuilder.addServerTelemetry(this.serverTelemetryManager); + } + var correlationId = request.correlationId || this.config.cryptoInterface.createNewGuid(); + parameterBuilder.addCorrelationId(correlationId); + if (this.config.clientCredentials.clientSecret) { + parameterBuilder.addClientSecret(this.config.clientCredentials.clientSecret); + } + // Use clientAssertion from request, fallback to client assertion in base configuration + var clientAssertion = request.clientAssertion || this.config.clientCredentials.clientAssertion; + if (clientAssertion) { + parameterBuilder.addClientAssertion(clientAssertion.assertion); + parameterBuilder.addClientAssertionType(clientAssertion.assertionType); + } + if (!StringUtils.isEmptyObj(request.claims) || this.config.authOptions.clientCapabilities && this.config.authOptions.clientCapabilities.length > 0) { + parameterBuilder.addClaims(request.claims, this.config.authOptions.clientCapabilities); + } + return parameterBuilder.createQueryString(); + }; + return ClientCredentialClient; +}(BaseClient)); + +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. + */ +/** + * On-Behalf-Of client + */ +var OnBehalfOfClient = /** @class */ (function (_super) { + __extends(OnBehalfOfClient, _super); + function OnBehalfOfClient(configuration) { + return _super.call(this, configuration) || this; + } + /** + * Public API to acquire tokens with on behalf of flow + * @param request + */ + OnBehalfOfClient.prototype.acquireToken = function (request) { + return __awaiter(this, void 0, void 0, function () { + var _a; + return __generator(this, function (_b) { + switch (_b.label) { + case 0: + this.scopeSet = new ScopeSet(request.scopes || []); + // generate the user_assertion_hash for OBOAssertion + _a = this; + return [4 /*yield*/, this.cryptoUtils.hashString(request.oboAssertion)]; + case 1: + // generate the user_assertion_hash for OBOAssertion + _a.userAssertionHash = _b.sent(); + if (!request.skipCache) return [3 /*break*/, 3]; + return [4 /*yield*/, this.executeTokenRequest(request, this.authority, this.userAssertionHash)]; + case 2: return [2 /*return*/, _b.sent()]; + case 3: + _b.trys.push([3, 5, , 7]); + return [4 /*yield*/, this.getCachedAuthenticationResult(request)]; + case 4: return [2 /*return*/, _b.sent()]; + case 5: + _b.sent(); + return [4 /*yield*/, this.executeTokenRequest(request, this.authority, this.userAssertionHash)]; + case 6: + // Any failure falls back to interactive request, once we implement distributed cache, we plan to handle `createRefreshRequiredError` to refresh using the RT + return [2 /*return*/, _b.sent()]; + case 7: return [2 /*return*/]; + } + }); + }); + }; + /** + * look up cache for tokens + * Find idtoken in the cache + * Find accessToken based on user assertion and account info in the cache + * Please note we are not yet supported OBO tokens refreshed with long lived RT. User will have to send a new assertion if the current access token expires + * This is to prevent security issues when the assertion changes over time, however, longlived RT helps retaining the session + * @param request + */ + OnBehalfOfClient.prototype.getCachedAuthenticationResult = function (request) { + var _a, _b; + return __awaiter(this, void 0, void 0, function () { + var cachedAccessToken, cachedIdToken, idTokenObject, cachedAccount, localAccountId, accountInfo; + return __generator(this, function (_c) { + switch (_c.label) { + case 0: + cachedAccessToken = this.readAccessTokenFromCacheForOBO(this.config.authOptions.clientId, request); + if (!cachedAccessToken) { + // Must refresh due to non-existent access_token. + (_a = this.serverTelemetryManager) === null || _a === void 0 ? void 0 : _a.setCacheOutcome(CacheOutcome.NO_CACHED_ACCESS_TOKEN); + this.logger.info("SilentFlowClient:acquireCachedToken - No access token found in cache for the given properties."); + throw ClientAuthError.createRefreshRequiredError(); + } + else if (TimeUtils.isTokenExpired(cachedAccessToken.expiresOn, this.config.systemOptions.tokenRenewalOffsetSeconds)) { + // Access token expired, will need to renewed + (_b = this.serverTelemetryManager) === null || _b === void 0 ? void 0 : _b.setCacheOutcome(CacheOutcome.CACHED_ACCESS_TOKEN_EXPIRED); + this.logger.info("OnbehalfofFlow:getCachedAuthenticationResult - Cached access token is expired or will expire within " + this.config.systemOptions.tokenRenewalOffsetSeconds + " seconds."); + throw ClientAuthError.createRefreshRequiredError(); + } + cachedIdToken = this.readIdTokenFromCacheForOBO(cachedAccessToken.homeAccountId); + cachedAccount = null; + if (cachedIdToken) { + idTokenObject = new AuthToken(cachedIdToken.secret, this.config.cryptoInterface); + localAccountId = idTokenObject.claims.oid ? idTokenObject.claims.oid : idTokenObject.claims.sub; + accountInfo = { + homeAccountId: cachedIdToken.homeAccountId, + environment: cachedIdToken.environment, + tenantId: cachedIdToken.realm, + username: Constants.EMPTY_STRING, + localAccountId: localAccountId || Constants.EMPTY_STRING + }; + cachedAccount = this.cacheManager.readAccountFromCache(accountInfo); + } + // increment telemetry cache hit counter + if (this.config.serverTelemetryManager) { + this.config.serverTelemetryManager.incrementCacheHits(); + } + return [4 /*yield*/, ResponseHandler.generateAuthenticationResult(this.cryptoUtils, this.authority, { + account: cachedAccount, + accessToken: cachedAccessToken, + idToken: cachedIdToken, + refreshToken: null, + appMetadata: null + }, true, request, idTokenObject)]; + case 1: return [2 /*return*/, _c.sent()]; + } + }); + }); + }; + /** + * read idtoken from cache, this is a specific implementation for OBO as the requirements differ from a generic lookup in the cacheManager + * Certain use cases of OBO flow do not expect an idToken in the cache/or from the service + * @param request + */ + OnBehalfOfClient.prototype.readIdTokenFromCacheForOBO = function (atHomeAccountId) { + var idTokenFilter = { + homeAccountId: atHomeAccountId, + environment: this.authority.canonicalAuthorityUrlComponents.HostNameAndPort, + credentialType: exports.CredentialType.ID_TOKEN, + clientId: this.config.authOptions.clientId, + realm: this.authority.tenant + }; + var idTokens = this.cacheManager.getIdTokensByFilter(idTokenFilter); + // When acquiring a token on behalf of an application, there might not be an id token in the cache + if (idTokens.length < 1) { + return null; + } + return idTokens[0]; + }; + /** + * Fetches the cached access token based on incoming assertion + * @param clientId + * @param request + * @param userAssertionHash + */ + OnBehalfOfClient.prototype.readAccessTokenFromCacheForOBO = function (clientId, request) { + var authScheme = request.authenticationScheme || exports.AuthenticationScheme.BEARER; + /* + * Distinguish between Bearer and PoP/SSH token cache types + * Cast to lowercase to handle "bearer" from ADFS + */ + var credentialType = (authScheme && authScheme.toLowerCase() !== exports.AuthenticationScheme.BEARER.toLowerCase()) ? exports.CredentialType.ACCESS_TOKEN_WITH_AUTH_SCHEME : exports.CredentialType.ACCESS_TOKEN; + var accessTokenFilter = { + credentialType: credentialType, + clientId: clientId, + target: ScopeSet.createSearchScopes(this.scopeSet.asArray()), + tokenType: authScheme, + keyId: request.sshKid, + requestedClaimsHash: request.requestedClaimsHash, + userAssertionHash: this.userAssertionHash + }; + var accessTokens = this.cacheManager.getAccessTokensByFilter(accessTokenFilter); + var numAccessTokens = accessTokens.length; + if (numAccessTokens < 1) { + return null; + } + else if (numAccessTokens > 1) { + throw ClientAuthError.createMultipleMatchingTokensInCacheError(); + } + return accessTokens[0]; + }; + /** + * Make a network call to the server requesting credentials + * @param request + * @param authority + */ + OnBehalfOfClient.prototype.executeTokenRequest = function (request, authority, userAssertionHash) { + return __awaiter(this, void 0, void 0, function () { + var queryParametersString, endpoint, requestBody, headers, thumbprint, reqTimestamp, response, responseHandler, tokenResponse; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + queryParametersString = this.createTokenQueryParameters(request); + endpoint = UrlString.appendQueryString(authority.tokenEndpoint, queryParametersString); + requestBody = this.createTokenRequestBody(request); + headers = this.createTokenRequestHeaders(); + thumbprint = { + clientId: this.config.authOptions.clientId, + authority: request.authority, + scopes: request.scopes, + claims: request.claims, + authenticationScheme: request.authenticationScheme, + resourceRequestMethod: request.resourceRequestMethod, + resourceRequestUri: request.resourceRequestUri, + shrClaims: request.shrClaims, + sshKid: request.sshKid + }; + reqTimestamp = TimeUtils.nowSeconds(); + return [4 /*yield*/, this.executePostToTokenEndpoint(endpoint, requestBody, headers, thumbprint)]; + case 1: + response = _a.sent(); + responseHandler = new ResponseHandler(this.config.authOptions.clientId, this.cacheManager, this.cryptoUtils, this.logger, this.config.serializableCache, this.config.persistencePlugin); + responseHandler.validateTokenResponse(response.body); + return [4 /*yield*/, responseHandler.handleServerTokenResponse(response.body, this.authority, reqTimestamp, request, undefined, userAssertionHash)]; + case 2: + tokenResponse = _a.sent(); + return [2 /*return*/, tokenResponse]; + } + }); + }); + }; + /** + * generate a server request in accepable format + * @param request + */ + OnBehalfOfClient.prototype.createTokenRequestBody = function (request) { + var parameterBuilder = new RequestParameterBuilder(); + parameterBuilder.addClientId(this.config.authOptions.clientId); + parameterBuilder.addScopes(request.scopes); + parameterBuilder.addGrantType(GrantType.JWT_BEARER); + parameterBuilder.addClientInfo(); + parameterBuilder.addLibraryInfo(this.config.libraryInfo); + parameterBuilder.addApplicationTelemetry(this.config.telemetry.application); + parameterBuilder.addThrottling(); + if (this.serverTelemetryManager) { + parameterBuilder.addServerTelemetry(this.serverTelemetryManager); + } + var correlationId = request.correlationId || this.config.cryptoInterface.createNewGuid(); + parameterBuilder.addCorrelationId(correlationId); + parameterBuilder.addRequestTokenUse(exports.AADServerParamKeys.ON_BEHALF_OF); + parameterBuilder.addOboAssertion(request.oboAssertion); + if (this.config.clientCredentials.clientSecret) { + parameterBuilder.addClientSecret(this.config.clientCredentials.clientSecret); + } + if (this.config.clientCredentials.clientAssertion) { + var clientAssertion = this.config.clientCredentials.clientAssertion; + parameterBuilder.addClientAssertion(clientAssertion.assertion); + parameterBuilder.addClientAssertionType(clientAssertion.assertionType); + } + if (request.claims || (this.config.authOptions.clientCapabilities && this.config.authOptions.clientCapabilities.length > 0)) { + parameterBuilder.addClaims(request.claims, this.config.authOptions.clientCapabilities); + } + return parameterBuilder.createQueryString(); + }; + return OnBehalfOfClient; +}(BaseClient)); + +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. + */ +var SilentFlowClient = /** @class */ (function (_super) { + __extends(SilentFlowClient, _super); + function SilentFlowClient(configuration, performanceClient) { + return _super.call(this, configuration, performanceClient) || this; + } + /** + * Retrieves a token from cache if it is still valid, or uses the cached refresh token to renew + * the given token and returns the renewed token + * @param request + */ + SilentFlowClient.prototype.acquireToken = function (request) { + return __awaiter(this, void 0, void 0, function () { + var e_1, refreshTokenClient; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + _a.trys.push([0, 2, , 3]); + return [4 /*yield*/, this.acquireCachedToken(request)]; + case 1: return [2 /*return*/, _a.sent()]; + case 2: + e_1 = _a.sent(); + if (e_1 instanceof ClientAuthError && e_1.errorCode === ClientAuthErrorMessage.tokenRefreshRequired.code) { + refreshTokenClient = new RefreshTokenClient(this.config, this.performanceClient); + return [2 /*return*/, refreshTokenClient.acquireTokenByRefreshToken(request)]; + } + else { + throw e_1; + } + case 3: return [2 /*return*/]; + } + }); + }); + }; + /** + * Retrieves token from cache or throws an error if it must be refreshed. + * @param request + */ + SilentFlowClient.prototype.acquireCachedToken = function (request) { + var _a, _b, _c, _d, _e; + return __awaiter(this, void 0, void 0, function () { + var environment, cacheRecord; + return __generator(this, function (_f) { + switch (_f.label) { + case 0: + // Cannot renew token if no request object is given. + if (!request) { + throw ClientConfigurationError.createEmptyTokenRequestError(); + } + if (request.forceRefresh) { + // Must refresh due to present force_refresh flag. + (_a = this.serverTelemetryManager) === null || _a === void 0 ? void 0 : _a.setCacheOutcome(CacheOutcome.FORCE_REFRESH); + this.logger.info("SilentFlowClient:acquireCachedToken - Skipping cache because forceRefresh is true."); + throw ClientAuthError.createRefreshRequiredError(); + } + else if (!this.config.cacheOptions.claimsBasedCachingEnabled && !StringUtils.isEmptyObj(request.claims)) { + // Must refresh due to presence of claims in request preventing cache lookup + (_b = this.serverTelemetryManager) === null || _b === void 0 ? void 0 : _b.setCacheOutcome(CacheOutcome.CLAIMS_REQUESTED_CACHE_SKIPPED); + this.logger.info("SilentFlowClient:acquireCachedToken - Skipping cache because claims-based caching is disabled and claims were requested."); + throw ClientAuthError.createRefreshRequiredError(); + } + // We currently do not support silent flow for account === null use cases; This will be revisited for confidential flow usecases + if (!request.account) { + throw ClientAuthError.createNoAccountInSilentRequestError(); + } + environment = request.authority || this.authority.getPreferredCache(); + cacheRecord = this.cacheManager.readCacheRecord(request.account, request, environment); + if (!cacheRecord.accessToken) { + // Must refresh due to non-existent access_token. + (_c = this.serverTelemetryManager) === null || _c === void 0 ? void 0 : _c.setCacheOutcome(CacheOutcome.NO_CACHED_ACCESS_TOKEN); + this.logger.info("SilentFlowClient:acquireCachedToken - No access token found in cache for the given properties."); + throw ClientAuthError.createRefreshRequiredError(); + } + else if (TimeUtils.wasClockTurnedBack(cacheRecord.accessToken.cachedAt) || + TimeUtils.isTokenExpired(cacheRecord.accessToken.expiresOn, this.config.systemOptions.tokenRenewalOffsetSeconds)) { + // Must refresh due to expired access_token. + (_d = this.serverTelemetryManager) === null || _d === void 0 ? void 0 : _d.setCacheOutcome(CacheOutcome.CACHED_ACCESS_TOKEN_EXPIRED); + this.logger.info("SilentFlowClient:acquireCachedToken - Cached access token is expired or will expire within " + this.config.systemOptions.tokenRenewalOffsetSeconds + " seconds."); + throw ClientAuthError.createRefreshRequiredError(); + } + else if (cacheRecord.accessToken.refreshOn && TimeUtils.isTokenExpired(cacheRecord.accessToken.refreshOn, 0)) { + // Must refresh due to the refresh_in value. + (_e = this.serverTelemetryManager) === null || _e === void 0 ? void 0 : _e.setCacheOutcome(CacheOutcome.REFRESH_CACHED_ACCESS_TOKEN); + this.logger.info("SilentFlowClient:acquireCachedToken - Cached access token's refreshOn property has been exceeded'."); + throw ClientAuthError.createRefreshRequiredError(); + } + if (this.config.serverTelemetryManager) { + this.config.serverTelemetryManager.incrementCacheHits(); + } + return [4 /*yield*/, this.generateResultFromCacheRecord(cacheRecord, request)]; + case 1: return [2 /*return*/, _f.sent()]; + } + }); + }); + }; + /** + * Helper function to build response object from the CacheRecord + * @param cacheRecord + */ + SilentFlowClient.prototype.generateResultFromCacheRecord = function (cacheRecord, request) { + return __awaiter(this, void 0, void 0, function () { + var idTokenObj, authTime; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + if (cacheRecord.idToken) { + idTokenObj = new AuthToken(cacheRecord.idToken.secret, this.config.cryptoInterface); + } + // token max_age check + if (request.maxAge || (request.maxAge === 0)) { + authTime = idTokenObj === null || idTokenObj === void 0 ? void 0 : idTokenObj.claims.auth_time; + if (!authTime) { + throw ClientAuthError.createAuthTimeNotFoundError(); + } + AuthToken.checkMaxAge(authTime, request.maxAge); + } + return [4 /*yield*/, ResponseHandler.generateAuthenticationResult(this.cryptoUtils, this.authority, cacheRecord, true, request, idTokenObj)]; + case 1: return [2 /*return*/, _a.sent()]; + } + }); + }); + }; + return SilentFlowClient; +}(BaseClient)); + +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. + */ +/** + * Oauth2.0 Password grant client + * Note: We are only supporting public clients for password grant and for purely testing purposes + */ +var UsernamePasswordClient = /** @class */ (function (_super) { + __extends(UsernamePasswordClient, _super); + function UsernamePasswordClient(configuration) { + return _super.call(this, configuration) || this; + } + /** + * API to acquire a token by passing the username and password to the service in exchage of credentials + * password_grant + * @param request + */ + UsernamePasswordClient.prototype.acquireToken = function (request) { + var _a, _b; + return __awaiter(this, void 0, void 0, function () { + var atsMeasurement, reqTimestamp, response, httpVerToken, responseHandler, tokenResponse; + return __generator(this, function (_c) { + switch (_c.label) { + case 0: + atsMeasurement = (_a = this.performanceClient) === null || _a === void 0 ? void 0 : _a.startMeasurement("UsernamePasswordClientAcquireToken", request.correlationId); + this.logger.info("in acquireToken call in username-password client"); + reqTimestamp = TimeUtils.nowSeconds(); + return [4 /*yield*/, this.executeTokenRequest(this.authority, request)]; + case 1: + response = _c.sent(); + httpVerToken = (_b = response.headers) === null || _b === void 0 ? void 0 : _b[exports.HeaderNames.X_MS_HTTP_VERSION]; + atsMeasurement === null || atsMeasurement === void 0 ? void 0 : atsMeasurement.addStaticFields({ + httpVerToken: httpVerToken + }); + responseHandler = new ResponseHandler(this.config.authOptions.clientId, this.cacheManager, this.cryptoUtils, this.logger, this.config.serializableCache, this.config.persistencePlugin); + // Validate response. This function throws a server error if an error is returned by the server. + responseHandler.validateTokenResponse(response.body); + tokenResponse = responseHandler.handleServerTokenResponse(response.body, this.authority, reqTimestamp, request); + return [2 /*return*/, tokenResponse]; + } + }); + }); + }; + /** + * Executes POST request to token endpoint + * @param authority + * @param request + */ + UsernamePasswordClient.prototype.executeTokenRequest = function (authority, request) { + return __awaiter(this, void 0, void 0, function () { + var queryParametersString, endpoint, requestBody, headers, thumbprint; + return __generator(this, function (_a) { + queryParametersString = this.createTokenQueryParameters(request); + endpoint = UrlString.appendQueryString(authority.tokenEndpoint, queryParametersString); + requestBody = this.createTokenRequestBody(request); + headers = this.createTokenRequestHeaders({ + credential: request.username, + type: exports.CcsCredentialType.UPN + }); + thumbprint = { + clientId: this.config.authOptions.clientId, + authority: authority.canonicalAuthority, + scopes: request.scopes, + claims: request.claims, + authenticationScheme: request.authenticationScheme, + resourceRequestMethod: request.resourceRequestMethod, + resourceRequestUri: request.resourceRequestUri, + shrClaims: request.shrClaims, + sshKid: request.sshKid + }; + return [2 /*return*/, this.executePostToTokenEndpoint(endpoint, requestBody, headers, thumbprint)]; + }); + }); + }; + /** + * Generates a map for all the params to be sent to the service + * @param request + */ + UsernamePasswordClient.prototype.createTokenRequestBody = function (request) { + var parameterBuilder = new RequestParameterBuilder(); + parameterBuilder.addClientId(this.config.authOptions.clientId); + parameterBuilder.addUsername(request.username); + parameterBuilder.addPassword(request.password); + parameterBuilder.addScopes(request.scopes); + parameterBuilder.addResponseTypeForTokenAndIdToken(); + parameterBuilder.addGrantType(GrantType.RESOURCE_OWNER_PASSWORD_GRANT); + parameterBuilder.addClientInfo(); + parameterBuilder.addLibraryInfo(this.config.libraryInfo); + parameterBuilder.addApplicationTelemetry(this.config.telemetry.application); + parameterBuilder.addThrottling(); + if (this.serverTelemetryManager) { + parameterBuilder.addServerTelemetry(this.serverTelemetryManager); + } + var correlationId = request.correlationId || this.config.cryptoInterface.createNewGuid(); + parameterBuilder.addCorrelationId(correlationId); + if (this.config.clientCredentials.clientSecret) { + parameterBuilder.addClientSecret(this.config.clientCredentials.clientSecret); + } + if (this.config.clientCredentials.clientAssertion) { + var clientAssertion = this.config.clientCredentials.clientAssertion; + parameterBuilder.addClientAssertion(clientAssertion.assertion); + parameterBuilder.addClientAssertionType(clientAssertion.assertionType); + } + if (!StringUtils.isEmptyObj(request.claims) || this.config.authOptions.clientCapabilities && this.config.authOptions.clientCapabilities.length > 0) { + parameterBuilder.addClaims(request.claims, this.config.authOptions.clientCapabilities); + } + if (this.config.systemOptions.preventCorsPreflight && request.username) { + parameterBuilder.addCcsUpn(request.username); + } + return parameterBuilder.createQueryString(); + }; + return UsernamePasswordClient; +}(BaseClient)); + +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. + */ +function isOpenIdConfigResponse(response) { + return (response.hasOwnProperty("authorization_endpoint") && + response.hasOwnProperty("token_endpoint") && + response.hasOwnProperty("issuer") && + response.hasOwnProperty("jwks_uri")); +} + +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. + */ +var rawMetdataJSON = { "endpointMetadata": { "https://login.microsoftonline.com/common/": { "token_endpoint": "https://login.microsoftonline.com/common/oauth2/v2.0/token", "token_endpoint_auth_methods_supported": ["client_secret_post", "private_key_jwt", "client_secret_basic"], "jwks_uri": "https://login.microsoftonline.com/common/discovery/v2.0/keys", "response_modes_supported": ["query", "fragment", "form_post"], "subject_types_supported": ["pairwise"], "id_token_signing_alg_values_supported": ["RS256"], "response_types_supported": ["code", "id_token", "code id_token", "id_token token"], "scopes_supported": ["openid", "profile", "email", "offline_access"], "issuer": "https://login.microsoftonline.com/{tenantid}/v2.0", "request_uri_parameter_supported": false, "userinfo_endpoint": "https://graph.microsoft.com/oidc/userinfo", "authorization_endpoint": "https://login.microsoftonline.com/common/oauth2/v2.0/authorize", "device_authorization_endpoint": "https://login.microsoftonline.com/common/oauth2/v2.0/devicecode", "http_logout_supported": true, "frontchannel_logout_supported": true, "end_session_endpoint": "https://login.microsoftonline.com/common/oauth2/v2.0/logout", "claims_supported": ["sub", "iss", "cloud_instance_name", "cloud_instance_host_name", "cloud_graph_host_name", "msgraph_host", "aud", "exp", "iat", "auth_time", "acr", "nonce", "preferred_username", "name", "tid", "ver", "at_hash", "c_hash", "email"], "kerberos_endpoint": "https://login.microsoftonline.com/common/kerberos", "tenant_region_scope": null, "cloud_instance_name": "microsoftonline.com", "cloud_graph_host_name": "graph.windows.net", "msgraph_host": "graph.microsoft.com", "rbac_url": "https://pas.windows.net" }, "https://login.chinacloudapi.cn/common/": { "token_endpoint": "https://login.chinacloudapi.cn/common/oauth2/v2.0/token", "token_endpoint_auth_methods_supported": ["client_secret_post", "private_key_jwt", "client_secret_basic"], "jwks_uri": "https://login.chinacloudapi.cn/common/discovery/v2.0/keys", "response_modes_supported": ["query", "fragment", "form_post"], "subject_types_supported": ["pairwise"], "id_token_signing_alg_values_supported": ["RS256"], "response_types_supported": ["code", "id_token", "code id_token", "id_token token"], "scopes_supported": ["openid", "profile", "email", "offline_access"], "issuer": "https://login.partner.microsoftonline.cn/{tenantid}/v2.0", "request_uri_parameter_supported": false, "userinfo_endpoint": "https://microsoftgraph.chinacloudapi.cn/oidc/userinfo", "authorization_endpoint": "https://login.chinacloudapi.cn/common/oauth2/v2.0/authorize", "device_authorization_endpoint": "https://login.chinacloudapi.cn/common/oauth2/v2.0/devicecode", "http_logout_supported": true, "frontchannel_logout_supported": true, "end_session_endpoint": "https://login.chinacloudapi.cn/common/oauth2/v2.0/logout", "claims_supported": ["sub", "iss", "cloud_instance_name", "cloud_instance_host_name", "cloud_graph_host_name", "msgraph_host", "aud", "exp", "iat", "auth_time", "acr", "nonce", "preferred_username", "name", "tid", "ver", "at_hash", "c_hash", "email"], "kerberos_endpoint": "https://login.chinacloudapi.cn/common/kerberos", "tenant_region_scope": null, "cloud_instance_name": "partner.microsoftonline.cn", "cloud_graph_host_name": "graph.chinacloudapi.cn", "msgraph_host": "microsoftgraph.chinacloudapi.cn", "rbac_url": "https://pas.chinacloudapi.cn" }, "https://login.microsoftonline.us/common/": { "token_endpoint": "https://login.microsoftonline.us/common/oauth2/v2.0/token", "token_endpoint_auth_methods_supported": ["client_secret_post", "private_key_jwt", "client_secret_basic"], "jwks_uri": "https://login.microsoftonline.us/common/discovery/v2.0/keys", "response_modes_supported": ["query", "fragment", "form_post"], "subject_types_supported": ["pairwise"], "id_token_signing_alg_values_supported": ["RS256"], "response_types_supported": ["code", "id_token", "code id_token", "id_token token"], "scopes_supported": ["openid", "profile", "email", "offline_access"], "issuer": "https://login.microsoftonline.us/{tenantid}/v2.0", "request_uri_parameter_supported": false, "userinfo_endpoint": "https://graph.microsoft.com/oidc/userinfo", "authorization_endpoint": "https://login.microsoftonline.us/common/oauth2/v2.0/authorize", "device_authorization_endpoint": "https://login.microsoftonline.us/common/oauth2/v2.0/devicecode", "http_logout_supported": true, "frontchannel_logout_supported": true, "end_session_endpoint": "https://login.microsoftonline.us/common/oauth2/v2.0/logout", "claims_supported": ["sub", "iss", "cloud_instance_name", "cloud_instance_host_name", "cloud_graph_host_name", "msgraph_host", "aud", "exp", "iat", "auth_time", "acr", "nonce", "preferred_username", "name", "tid", "ver", "at_hash", "c_hash", "email"], "kerberos_endpoint": "https://login.microsoftonline.us/common/kerberos", "tenant_region_scope": null, "cloud_instance_name": "microsoftonline.us", "cloud_graph_host_name": "graph.windows.net", "msgraph_host": "graph.microsoft.com", "rbac_url": "https://pasff.usgovcloudapi.net" }, "https://login.microsoftonline.com/consumers/": { "token_endpoint": "https://login.microsoftonline.com/consumers/oauth2/v2.0/token", "token_endpoint_auth_methods_supported": ["client_secret_post", "private_key_jwt", "client_secret_basic"], "jwks_uri": "https://login.microsoftonline.com/consumers/discovery/v2.0/keys", "response_modes_supported": ["query", "fragment", "form_post"], "subject_types_supported": ["pairwise"], "id_token_signing_alg_values_supported": ["RS256"], "response_types_supported": ["code", "id_token", "code id_token", "id_token token"], "scopes_supported": ["openid", "profile", "email", "offline_access"], "issuer": "https://login.microsoftonline.com/9188040d-6c67-4c5b-b112-36a304b66dad/v2.0", "request_uri_parameter_supported": false, "userinfo_endpoint": "https://graph.microsoft.com/oidc/userinfo", "authorization_endpoint": "https://login.microsoftonline.com/consumers/oauth2/v2.0/authorize", "device_authorization_endpoint": "https://login.microsoftonline.com/consumers/oauth2/v2.0/devicecode", "http_logout_supported": true, "frontchannel_logout_supported": true, "end_session_endpoint": "https://login.microsoftonline.com/consumers/oauth2/v2.0/logout", "claims_supported": ["sub", "iss", "cloud_instance_name", "cloud_instance_host_name", "cloud_graph_host_name", "msgraph_host", "aud", "exp", "iat", "auth_time", "acr", "nonce", "preferred_username", "name", "tid", "ver", "at_hash", "c_hash", "email"], "kerberos_endpoint": "https://login.microsoftonline.com/consumers/kerberos", "tenant_region_scope": null, "cloud_instance_name": "microsoftonline.com", "cloud_graph_host_name": "graph.windows.net", "msgraph_host": "graph.microsoft.com", "rbac_url": "https://pas.windows.net" }, "https://login.chinacloudapi.cn/consumers/": { "token_endpoint": "https://login.chinacloudapi.cn/consumers/oauth2/v2.0/token", "token_endpoint_auth_methods_supported": ["client_secret_post", "private_key_jwt", "client_secret_basic"], "jwks_uri": "https://login.chinacloudapi.cn/consumers/discovery/v2.0/keys", "response_modes_supported": ["query", "fragment", "form_post"], "subject_types_supported": ["pairwise"], "id_token_signing_alg_values_supported": ["RS256"], "response_types_supported": ["code", "id_token", "code id_token", "id_token token"], "scopes_supported": ["openid", "profile", "email", "offline_access"], "issuer": "https://login.partner.microsoftonline.cn/9188040d-6c67-4c5b-b112-36a304b66dad/v2.0", "request_uri_parameter_supported": false, "userinfo_endpoint": "https://microsoftgraph.chinacloudapi.cn/oidc/userinfo", "authorization_endpoint": "https://login.chinacloudapi.cn/consumers/oauth2/v2.0/authorize", "device_authorization_endpoint": "https://login.chinacloudapi.cn/consumers/oauth2/v2.0/devicecode", "http_logout_supported": true, "frontchannel_logout_supported": true, "end_session_endpoint": "https://login.chinacloudapi.cn/consumers/oauth2/v2.0/logout", "claims_supported": ["sub", "iss", "cloud_instance_name", "cloud_instance_host_name", "cloud_graph_host_name", "msgraph_host", "aud", "exp", "iat", "auth_time", "acr", "nonce", "preferred_username", "name", "tid", "ver", "at_hash", "c_hash", "email"], "kerberos_endpoint": "https://login.chinacloudapi.cn/consumers/kerberos", "tenant_region_scope": null, "cloud_instance_name": "partner.microsoftonline.cn", "cloud_graph_host_name": "graph.chinacloudapi.cn", "msgraph_host": "microsoftgraph.chinacloudapi.cn", "rbac_url": "https://pas.chinacloudapi.cn" }, "https://login.microsoftonline.us/consumers/": { "token_endpoint": "https://login.microsoftonline.us/consumers/oauth2/v2.0/token", "token_endpoint_auth_methods_supported": ["client_secret_post", "private_key_jwt", "client_secret_basic"], "jwks_uri": "https://login.microsoftonline.us/consumers/discovery/v2.0/keys", "response_modes_supported": ["query", "fragment", "form_post"], "subject_types_supported": ["pairwise"], "id_token_signing_alg_values_supported": ["RS256"], "response_types_supported": ["code", "id_token", "code id_token", "id_token token"], "scopes_supported": ["openid", "profile", "email", "offline_access"], "issuer": "https://login.microsoftonline.us/9188040d-6c67-4c5b-b112-36a304b66dad/v2.0", "request_uri_parameter_supported": false, "userinfo_endpoint": "https://graph.microsoft.com/oidc/userinfo", "authorization_endpoint": "https://login.microsoftonline.us/consumers/oauth2/v2.0/authorize", "device_authorization_endpoint": "https://login.microsoftonline.us/consumers/oauth2/v2.0/devicecode", "http_logout_supported": true, "frontchannel_logout_supported": true, "end_session_endpoint": "https://login.microsoftonline.us/consumers/oauth2/v2.0/logout", "claims_supported": ["sub", "iss", "cloud_instance_name", "cloud_instance_host_name", "cloud_graph_host_name", "msgraph_host", "aud", "exp", "iat", "auth_time", "acr", "nonce", "preferred_username", "name", "tid", "ver", "at_hash", "c_hash", "email"], "kerberos_endpoint": "https://login.microsoftonline.us/consumers/kerberos", "tenant_region_scope": null, "cloud_instance_name": "microsoftonline.us", "cloud_graph_host_name": "graph.windows.net", "msgraph_host": "graph.microsoft.com", "rbac_url": "https://pasff.usgovcloudapi.net" }, "https://login.microsoftonline.com/organizations/": { "token_endpoint": "https://login.microsoftonline.com/organizations/oauth2/v2.0/token", "token_endpoint_auth_methods_supported": ["client_secret_post", "private_key_jwt", "client_secret_basic"], "jwks_uri": "https://login.microsoftonline.com/organizations/discovery/v2.0/keys", "response_modes_supported": ["query", "fragment", "form_post"], "subject_types_supported": ["pairwise"], "id_token_signing_alg_values_supported": ["RS256"], "response_types_supported": ["code", "id_token", "code id_token", "id_token token"], "scopes_supported": ["openid", "profile", "email", "offline_access"], "issuer": "https://login.microsoftonline.com/{tenantid}/v2.0", "request_uri_parameter_supported": false, "userinfo_endpoint": "https://graph.microsoft.com/oidc/userinfo", "authorization_endpoint": "https://login.microsoftonline.com/organizations/oauth2/v2.0/authorize", "device_authorization_endpoint": "https://login.microsoftonline.com/organizations/oauth2/v2.0/devicecode", "http_logout_supported": true, "frontchannel_logout_supported": true, "end_session_endpoint": "https://login.microsoftonline.com/organizations/oauth2/v2.0/logout", "claims_supported": ["sub", "iss", "cloud_instance_name", "cloud_instance_host_name", "cloud_graph_host_name", "msgraph_host", "aud", "exp", "iat", "auth_time", "acr", "nonce", "preferred_username", "name", "tid", "ver", "at_hash", "c_hash", "email"], "kerberos_endpoint": "https://login.microsoftonline.com/organizations/kerberos", "tenant_region_scope": null, "cloud_instance_name": "microsoftonline.com", "cloud_graph_host_name": "graph.windows.net", "msgraph_host": "graph.microsoft.com", "rbac_url": "https://pas.windows.net" }, "https://login.chinacloudapi.cn/organizations/": { "token_endpoint": "https://login.chinacloudapi.cn/organizations/oauth2/v2.0/token", "token_endpoint_auth_methods_supported": ["client_secret_post", "private_key_jwt", "client_secret_basic"], "jwks_uri": "https://login.chinacloudapi.cn/organizations/discovery/v2.0/keys", "response_modes_supported": ["query", "fragment", "form_post"], "subject_types_supported": ["pairwise"], "id_token_signing_alg_values_supported": ["RS256"], "response_types_supported": ["code", "id_token", "code id_token", "id_token token"], "scopes_supported": ["openid", "profile", "email", "offline_access"], "issuer": "https://login.partner.microsoftonline.cn/{tenantid}/v2.0", "request_uri_parameter_supported": false, "userinfo_endpoint": "https://microsoftgraph.chinacloudapi.cn/oidc/userinfo", "authorization_endpoint": "https://login.chinacloudapi.cn/organizations/oauth2/v2.0/authorize", "device_authorization_endpoint": "https://login.chinacloudapi.cn/organizations/oauth2/v2.0/devicecode", "http_logout_supported": true, "frontchannel_logout_supported": true, "end_session_endpoint": "https://login.chinacloudapi.cn/organizations/oauth2/v2.0/logout", "claims_supported": ["sub", "iss", "cloud_instance_name", "cloud_instance_host_name", "cloud_graph_host_name", "msgraph_host", "aud", "exp", "iat", "auth_time", "acr", "nonce", "preferred_username", "name", "tid", "ver", "at_hash", "c_hash", "email"], "kerberos_endpoint": "https://login.chinacloudapi.cn/organizations/kerberos", "tenant_region_scope": null, "cloud_instance_name": "partner.microsoftonline.cn", "cloud_graph_host_name": "graph.chinacloudapi.cn", "msgraph_host": "microsoftgraph.chinacloudapi.cn", "rbac_url": "https://pas.chinacloudapi.cn" }, "https://login.microsoftonline.us/organizations/": { "token_endpoint": "https://login.microsoftonline.us/organizations/oauth2/v2.0/token", "token_endpoint_auth_methods_supported": ["client_secret_post", "private_key_jwt", "client_secret_basic"], "jwks_uri": "https://login.microsoftonline.us/organizations/discovery/v2.0/keys", "response_modes_supported": ["query", "fragment", "form_post"], "subject_types_supported": ["pairwise"], "id_token_signing_alg_values_supported": ["RS256"], "response_types_supported": ["code", "id_token", "code id_token", "id_token token"], "scopes_supported": ["openid", "profile", "email", "offline_access"], "issuer": "https://login.microsoftonline.us/{tenantid}/v2.0", "request_uri_parameter_supported": false, "userinfo_endpoint": "https://graph.microsoft.com/oidc/userinfo", "authorization_endpoint": "https://login.microsoftonline.us/organizations/oauth2/v2.0/authorize", "device_authorization_endpoint": "https://login.microsoftonline.us/organizations/oauth2/v2.0/devicecode", "http_logout_supported": true, "frontchannel_logout_supported": true, "end_session_endpoint": "https://login.microsoftonline.us/organizations/oauth2/v2.0/logout", "claims_supported": ["sub", "iss", "cloud_instance_name", "cloud_instance_host_name", "cloud_graph_host_name", "msgraph_host", "aud", "exp", "iat", "auth_time", "acr", "nonce", "preferred_username", "name", "tid", "ver", "at_hash", "c_hash", "email"], "kerberos_endpoint": "https://login.microsoftonline.us/organizations/kerberos", "tenant_region_scope": null, "cloud_instance_name": "microsoftonline.us", "cloud_graph_host_name": "graph.windows.net", "msgraph_host": "graph.microsoft.com", "rbac_url": "https://pasff.usgovcloudapi.net" } }, "instanceDiscoveryMetadata": { "https://login.microsoftonline.com/common/": { "tenant_discovery_endpoint": "https://login.microsoftonline.com/common/v2.0/.well-known/openid-configuration", "api-version": "1.1", "metadata": [{ "preferred_network": "login.microsoftonline.com", "preferred_cache": "login.windows.net", "aliases": ["login.microsoftonline.com", "login.windows.net", "login.microsoft.com", "sts.windows.net"] }, { "preferred_network": "login.partner.microsoftonline.cn", "preferred_cache": "login.partner.microsoftonline.cn", "aliases": ["login.partner.microsoftonline.cn", "login.chinacloudapi.cn"] }, { "preferred_network": "login.microsoftonline.de", "preferred_cache": "login.microsoftonline.de", "aliases": ["login.microsoftonline.de"] }, { "preferred_network": "login.microsoftonline.us", "preferred_cache": "login.microsoftonline.us", "aliases": ["login.microsoftonline.us", "login.usgovcloudapi.net"] }, { "preferred_network": "login-us.microsoftonline.com", "preferred_cache": "login-us.microsoftonline.com", "aliases": ["login-us.microsoftonline.com"] }] }, "https://login.chinacloudapi.cn/common/": { "tenant_discovery_endpoint": "https://login.chinacloudapi.cn/common/v2.0/.well-known/openid-configuration", "api-version": "1.1", "metadata": [{ "preferred_network": "login.microsoftonline.com", "preferred_cache": "login.windows.net", "aliases": ["login.microsoftonline.com", "login.windows.net", "login.microsoft.com", "sts.windows.net"] }, { "preferred_network": "login.partner.microsoftonline.cn", "preferred_cache": "login.partner.microsoftonline.cn", "aliases": ["login.partner.microsoftonline.cn", "login.chinacloudapi.cn"] }, { "preferred_network": "login.microsoftonline.de", "preferred_cache": "login.microsoftonline.de", "aliases": ["login.microsoftonline.de"] }, { "preferred_network": "login.microsoftonline.us", "preferred_cache": "login.microsoftonline.us", "aliases": ["login.microsoftonline.us", "login.usgovcloudapi.net"] }, { "preferred_network": "login-us.microsoftonline.com", "preferred_cache": "login-us.microsoftonline.com", "aliases": ["login-us.microsoftonline.com"] }] }, "https://login.microsoftonline.us/common/": { "tenant_discovery_endpoint": "https://login.microsoftonline.us/common/v2.0/.well-known/openid-configuration", "api-version": "1.1", "metadata": [{ "preferred_network": "login.microsoftonline.com", "preferred_cache": "login.windows.net", "aliases": ["login.microsoftonline.com", "login.windows.net", "login.microsoft.com", "sts.windows.net"] }, { "preferred_network": "login.partner.microsoftonline.cn", "preferred_cache": "login.partner.microsoftonline.cn", "aliases": ["login.partner.microsoftonline.cn", "login.chinacloudapi.cn"] }, { "preferred_network": "login.microsoftonline.de", "preferred_cache": "login.microsoftonline.de", "aliases": ["login.microsoftonline.de"] }, { "preferred_network": "login.microsoftonline.us", "preferred_cache": "login.microsoftonline.us", "aliases": ["login.microsoftonline.us", "login.usgovcloudapi.net"] }, { "preferred_network": "login-us.microsoftonline.com", "preferred_cache": "login-us.microsoftonline.com", "aliases": ["login-us.microsoftonline.com"] }] }, "https://login.microsoftonline.com/consumers/": { "tenant_discovery_endpoint": "https://login.microsoftonline.com/consumers/v2.0/.well-known/openid-configuration", "api-version": "1.1", "metadata": [{ "preferred_network": "login.microsoftonline.com", "preferred_cache": "login.windows.net", "aliases": ["login.microsoftonline.com", "login.windows.net", "login.microsoft.com", "sts.windows.net"] }, { "preferred_network": "login.partner.microsoftonline.cn", "preferred_cache": "login.partner.microsoftonline.cn", "aliases": ["login.partner.microsoftonline.cn", "login.chinacloudapi.cn"] }, { "preferred_network": "login.microsoftonline.de", "preferred_cache": "login.microsoftonline.de", "aliases": ["login.microsoftonline.de"] }, { "preferred_network": "login.microsoftonline.us", "preferred_cache": "login.microsoftonline.us", "aliases": ["login.microsoftonline.us", "login.usgovcloudapi.net"] }, { "preferred_network": "login-us.microsoftonline.com", "preferred_cache": "login-us.microsoftonline.com", "aliases": ["login-us.microsoftonline.com"] }] }, "https://login.chinacloudapi.cn/consumers/": { "tenant_discovery_endpoint": "https://login.chinacloudapi.cn/consumers/v2.0/.well-known/openid-configuration", "api-version": "1.1", "metadata": [{ "preferred_network": "login.microsoftonline.com", "preferred_cache": "login.windows.net", "aliases": ["login.microsoftonline.com", "login.windows.net", "login.microsoft.com", "sts.windows.net"] }, { "preferred_network": "login.partner.microsoftonline.cn", "preferred_cache": "login.partner.microsoftonline.cn", "aliases": ["login.partner.microsoftonline.cn", "login.chinacloudapi.cn"] }, { "preferred_network": "login.microsoftonline.de", "preferred_cache": "login.microsoftonline.de", "aliases": ["login.microsoftonline.de"] }, { "preferred_network": "login.microsoftonline.us", "preferred_cache": "login.microsoftonline.us", "aliases": ["login.microsoftonline.us", "login.usgovcloudapi.net"] }, { "preferred_network": "login-us.microsoftonline.com", "preferred_cache": "login-us.microsoftonline.com", "aliases": ["login-us.microsoftonline.com"] }] }, "https://login.microsoftonline.us/consumers/": { "tenant_discovery_endpoint": "https://login.microsoftonline.us/consumers/v2.0/.well-known/openid-configuration", "api-version": "1.1", "metadata": [{ "preferred_network": "login.microsoftonline.com", "preferred_cache": "login.windows.net", "aliases": ["login.microsoftonline.com", "login.windows.net", "login.microsoft.com", "sts.windows.net"] }, { "preferred_network": "login.partner.microsoftonline.cn", "preferred_cache": "login.partner.microsoftonline.cn", "aliases": ["login.partner.microsoftonline.cn", "login.chinacloudapi.cn"] }, { "preferred_network": "login.microsoftonline.de", "preferred_cache": "login.microsoftonline.de", "aliases": ["login.microsoftonline.de"] }, { "preferred_network": "login.microsoftonline.us", "preferred_cache": "login.microsoftonline.us", "aliases": ["login.microsoftonline.us", "login.usgovcloudapi.net"] }, { "preferred_network": "login-us.microsoftonline.com", "preferred_cache": "login-us.microsoftonline.com", "aliases": ["login-us.microsoftonline.com"] }] }, "https://login.microsoftonline.com/organizations/": { "tenant_discovery_endpoint": "https://login.microsoftonline.com/organizations/v2.0/.well-known/openid-configuration", "api-version": "1.1", "metadata": [{ "preferred_network": "login.microsoftonline.com", "preferred_cache": "login.windows.net", "aliases": ["login.microsoftonline.com", "login.windows.net", "login.microsoft.com", "sts.windows.net"] }, { "preferred_network": "login.partner.microsoftonline.cn", "preferred_cache": "login.partner.microsoftonline.cn", "aliases": ["login.partner.microsoftonline.cn", "login.chinacloudapi.cn"] }, { "preferred_network": "login.microsoftonline.de", "preferred_cache": "login.microsoftonline.de", "aliases": ["login.microsoftonline.de"] }, { "preferred_network": "login.microsoftonline.us", "preferred_cache": "login.microsoftonline.us", "aliases": ["login.microsoftonline.us", "login.usgovcloudapi.net"] }, { "preferred_network": "login-us.microsoftonline.com", "preferred_cache": "login-us.microsoftonline.com", "aliases": ["login-us.microsoftonline.com"] }] }, "https://login.chinacloudapi.cn/organizations/": { "tenant_discovery_endpoint": "https://login.chinacloudapi.cn/organizations/v2.0/.well-known/openid-configuration", "api-version": "1.1", "metadata": [{ "preferred_network": "login.microsoftonline.com", "preferred_cache": "login.windows.net", "aliases": ["login.microsoftonline.com", "login.windows.net", "login.microsoft.com", "sts.windows.net"] }, { "preferred_network": "login.partner.microsoftonline.cn", "preferred_cache": "login.partner.microsoftonline.cn", "aliases": ["login.partner.microsoftonline.cn", "login.chinacloudapi.cn"] }, { "preferred_network": "login.microsoftonline.de", "preferred_cache": "login.microsoftonline.de", "aliases": ["login.microsoftonline.de"] }, { "preferred_network": "login.microsoftonline.us", "preferred_cache": "login.microsoftonline.us", "aliases": ["login.microsoftonline.us", "login.usgovcloudapi.net"] }, { "preferred_network": "login-us.microsoftonline.com", "preferred_cache": "login-us.microsoftonline.com", "aliases": ["login-us.microsoftonline.com"] }] }, "https://login.microsoftonline.us/organizations/": { "tenant_discovery_endpoint": "https://login.microsoftonline.us/organizations/v2.0/.well-known/openid-configuration", "api-version": "1.1", "metadata": [{ "preferred_network": "login.microsoftonline.com", "preferred_cache": "login.windows.net", "aliases": ["login.microsoftonline.com", "login.windows.net", "login.microsoft.com", "sts.windows.net"] }, { "preferred_network": "login.partner.microsoftonline.cn", "preferred_cache": "login.partner.microsoftonline.cn", "aliases": ["login.partner.microsoftonline.cn", "login.chinacloudapi.cn"] }, { "preferred_network": "login.microsoftonline.de", "preferred_cache": "login.microsoftonline.de", "aliases": ["login.microsoftonline.de"] }, { "preferred_network": "login.microsoftonline.us", "preferred_cache": "login.microsoftonline.us", "aliases": ["login.microsoftonline.us", "login.usgovcloudapi.net"] }, { "preferred_network": "login-us.microsoftonline.com", "preferred_cache": "login-us.microsoftonline.com", "aliases": ["login-us.microsoftonline.com"] }] } } }; +var EndpointMetadata = rawMetdataJSON.endpointMetadata; +var InstanceDiscoveryMetadata = rawMetdataJSON.instanceDiscoveryMetadata; + +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. + */ +/** + * Protocol modes supported by MSAL. + */ +exports.ProtocolMode = void 0; +(function (ProtocolMode) { + ProtocolMode["AAD"] = "AAD"; + ProtocolMode["OIDC"] = "OIDC"; +})(exports.ProtocolMode || (exports.ProtocolMode = {})); + +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. + */ +var AuthorityMetadataEntity = /** @class */ (function () { + function AuthorityMetadataEntity() { + this.expiresAt = TimeUtils.nowSeconds() + AUTHORITY_METADATA_CONSTANTS.REFRESH_TIME_SECONDS; + } + /** + * Update the entity with new aliases, preferred_cache and preferred_network values + * @param metadata + * @param fromNetwork + */ + AuthorityMetadataEntity.prototype.updateCloudDiscoveryMetadata = function (metadata, fromNetwork) { + this.aliases = metadata.aliases; + this.preferred_cache = metadata.preferred_cache; + this.preferred_network = metadata.preferred_network; + this.aliasesFromNetwork = fromNetwork; + }; + /** + * Update the entity with new endpoints + * @param metadata + * @param fromNetwork + */ + AuthorityMetadataEntity.prototype.updateEndpointMetadata = function (metadata, fromNetwork) { + this.authorization_endpoint = metadata.authorization_endpoint; + this.token_endpoint = metadata.token_endpoint; + this.end_session_endpoint = metadata.end_session_endpoint; + this.issuer = metadata.issuer; + this.endpointsFromNetwork = fromNetwork; + this.jwks_uri = metadata.jwks_uri; + }; + /** + * Save the authority that was used to create this cache entry + * @param authority + */ + AuthorityMetadataEntity.prototype.updateCanonicalAuthority = function (authority) { + this.canonical_authority = authority; + }; + /** + * Reset the exiresAt value + */ + AuthorityMetadataEntity.prototype.resetExpiresAt = function () { + this.expiresAt = TimeUtils.nowSeconds() + AUTHORITY_METADATA_CONSTANTS.REFRESH_TIME_SECONDS; + }; + /** + * Returns whether or not the data needs to be refreshed + */ + AuthorityMetadataEntity.prototype.isExpired = function () { + return this.expiresAt <= TimeUtils.nowSeconds(); + }; + /** + * Validates an entity: checks for all expected params + * @param entity + */ + AuthorityMetadataEntity.isAuthorityMetadataEntity = function (key, entity) { + if (!entity) { + return false; + } + return (key.indexOf(AUTHORITY_METADATA_CONSTANTS.CACHE_KEY) === 0 && + entity.hasOwnProperty("aliases") && + entity.hasOwnProperty("preferred_cache") && + entity.hasOwnProperty("preferred_network") && + entity.hasOwnProperty("canonical_authority") && + entity.hasOwnProperty("authorization_endpoint") && + entity.hasOwnProperty("token_endpoint") && + entity.hasOwnProperty("issuer") && + entity.hasOwnProperty("aliasesFromNetwork") && + entity.hasOwnProperty("endpointsFromNetwork") && + entity.hasOwnProperty("expiresAt") && + entity.hasOwnProperty("jwks_uri")); + }; + return AuthorityMetadataEntity; +}()); + +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. + */ +function isCloudInstanceDiscoveryResponse(response) { + return (response.hasOwnProperty("tenant_discovery_endpoint") && + response.hasOwnProperty("metadata")); +} + +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. + */ +function isCloudInstanceDiscoveryErrorResponse(response) { + return (response.hasOwnProperty("error") && + response.hasOwnProperty("error_description")); +} + +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. + */ +var RegionDiscovery = /** @class */ (function () { + function RegionDiscovery(networkInterface, performanceClient, correlationId) { + this.networkInterface = networkInterface; + this.performanceClient = performanceClient; + this.correlationId = correlationId; + } + /** + * Detect the region from the application's environment. + * + * @returns Promise + */ + RegionDiscovery.prototype.detectRegion = function (environmentRegion, regionDiscoveryMetadata) { + var _a, _b, _c, _d; + return __awaiter(this, void 0, void 0, function () { + var autodetectedRegionName, options, localIMDSVersionResponse, currentIMDSVersion, currentIMDSVersionResponse; + return __generator(this, function (_e) { + switch (_e.label) { + case 0: + (_a = this.performanceClient) === null || _a === void 0 ? void 0 : _a.addQueueMeasurement(exports.PerformanceEvents.RegionDiscoveryDetectRegion, this.correlationId); + autodetectedRegionName = environmentRegion; + if (!!autodetectedRegionName) return [3 /*break*/, 8]; + options = RegionDiscovery.IMDS_OPTIONS; + _e.label = 1; + case 1: + _e.trys.push([1, 6, , 7]); + (_b = this.performanceClient) === null || _b === void 0 ? void 0 : _b.setPreQueueTime(exports.PerformanceEvents.RegionDiscoveryGetRegionFromIMDS, this.correlationId); + return [4 /*yield*/, this.getRegionFromIMDS(Constants.IMDS_VERSION, options)]; + case 2: + localIMDSVersionResponse = _e.sent(); + if (localIMDSVersionResponse.status === ResponseCodes.httpSuccess) { + autodetectedRegionName = localIMDSVersionResponse.body; + regionDiscoveryMetadata.region_source = RegionDiscoverySources.IMDS; + } + if (!(localIMDSVersionResponse.status === ResponseCodes.httpBadRequest)) return [3 /*break*/, 5]; + (_c = this.performanceClient) === null || _c === void 0 ? void 0 : _c.setPreQueueTime(exports.PerformanceEvents.RegionDiscoveryGetCurrentVersion, this.correlationId); + return [4 /*yield*/, this.getCurrentVersion(options)]; + case 3: + currentIMDSVersion = _e.sent(); + if (!currentIMDSVersion) { + regionDiscoveryMetadata.region_source = RegionDiscoverySources.FAILED_AUTO_DETECTION; + return [2 /*return*/, null]; + } + (_d = this.performanceClient) === null || _d === void 0 ? void 0 : _d.setPreQueueTime(exports.PerformanceEvents.RegionDiscoveryGetRegionFromIMDS, this.correlationId); + return [4 /*yield*/, this.getRegionFromIMDS(currentIMDSVersion, options)]; + case 4: + currentIMDSVersionResponse = _e.sent(); + if (currentIMDSVersionResponse.status === ResponseCodes.httpSuccess) { + autodetectedRegionName = currentIMDSVersionResponse.body; + regionDiscoveryMetadata.region_source = RegionDiscoverySources.IMDS; + } + _e.label = 5; + case 5: return [3 /*break*/, 7]; + case 6: + _e.sent(); + regionDiscoveryMetadata.region_source = RegionDiscoverySources.FAILED_AUTO_DETECTION; + return [2 /*return*/, null]; + case 7: return [3 /*break*/, 9]; + case 8: + regionDiscoveryMetadata.region_source = RegionDiscoverySources.ENVIRONMENT_VARIABLE; + _e.label = 9; + case 9: + // If no region was auto detected from the environment or from the IMDS endpoint, mark the attempt as a FAILED_AUTO_DETECTION + if (!autodetectedRegionName) { + regionDiscoveryMetadata.region_source = RegionDiscoverySources.FAILED_AUTO_DETECTION; + } + return [2 /*return*/, autodetectedRegionName || null]; + } + }); + }); + }; + /** + * Make the call to the IMDS endpoint + * + * @param imdsEndpointUrl + * @returns Promise> + */ + RegionDiscovery.prototype.getRegionFromIMDS = function (version, options) { + var _a; + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_b) { + (_a = this.performanceClient) === null || _a === void 0 ? void 0 : _a.addQueueMeasurement(exports.PerformanceEvents.RegionDiscoveryGetRegionFromIMDS, this.correlationId); + return [2 /*return*/, this.networkInterface.sendGetRequestAsync(Constants.IMDS_ENDPOINT + "?api-version=" + version + "&format=text", options, Constants.IMDS_TIMEOUT)]; + }); + }); + }; + /** + * Get the most recent version of the IMDS endpoint available + * + * @returns Promise + */ + RegionDiscovery.prototype.getCurrentVersion = function (options) { + var _a; + return __awaiter(this, void 0, void 0, function () { + var response; + return __generator(this, function (_b) { + switch (_b.label) { + case 0: + (_a = this.performanceClient) === null || _a === void 0 ? void 0 : _a.addQueueMeasurement(exports.PerformanceEvents.RegionDiscoveryGetCurrentVersion, this.correlationId); + _b.label = 1; + case 1: + _b.trys.push([1, 3, , 4]); + return [4 /*yield*/, this.networkInterface.sendGetRequestAsync(Constants.IMDS_ENDPOINT + "?format=json", options)]; + case 2: + response = _b.sent(); + // When IMDS endpoint is called without the api version query param, bad request response comes back with latest version. + if (response.status === ResponseCodes.httpBadRequest && response.body && response.body["newest-versions"] && response.body["newest-versions"].length > 0) { + return [2 /*return*/, response.body["newest-versions"][0]]; + } + return [2 /*return*/, null]; + case 3: + _b.sent(); + return [2 /*return*/, null]; + case 4: return [2 /*return*/]; + } + }); + }); + }; + // Options for the IMDS endpoint request + RegionDiscovery.IMDS_OPTIONS = { + headers: { + Metadata: "true", + }, + }; + return RegionDiscovery; +}()); + +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. + */ +/** + * The authority class validates the authority URIs used by the user, and retrieves the OpenID Configuration Data from the + * endpoint. It will store the pertinent config data in this object for use during token calls. + */ +var Authority = /** @class */ (function () { + function Authority(authority, networkInterface, cacheManager, authorityOptions, logger, performanceClient, correlationId) { + this.canonicalAuthority = authority; + this._canonicalAuthority.validateAsUri(); + this.networkInterface = networkInterface; + this.cacheManager = cacheManager; + this.authorityOptions = authorityOptions; + this.regionDiscoveryMetadata = { region_used: undefined, region_source: undefined, region_outcome: undefined }; + this.logger = logger; + this.performanceClient = performanceClient; + this.correlationId = correlationId; + this.regionDiscovery = new RegionDiscovery(networkInterface, this.performanceClient, this.correlationId); + } + /** + * Get {@link AuthorityType} + * @param authorityUri {@link IUri} + * @private + */ + Authority.prototype.getAuthorityType = function (authorityUri) { + // CIAM auth url pattern is being standardized as: .ciamlogin.com + if (authorityUri.HostNameAndPort.endsWith(Constants.CIAM_AUTH_URL)) { + return exports.AuthorityType.Ciam; + } + var pathSegments = authorityUri.PathSegments; + if (pathSegments.length) { + switch (pathSegments[0].toLowerCase()) { + case Constants.ADFS: + return exports.AuthorityType.Adfs; + case Constants.DSTS: + return exports.AuthorityType.Dsts; + } + } + return exports.AuthorityType.Default; + }; + Object.defineProperty(Authority.prototype, "authorityType", { + // See above for AuthorityType + get: function () { + return this.getAuthorityType(this.canonicalAuthorityUrlComponents); + }, + enumerable: false, + configurable: true + }); + Object.defineProperty(Authority.prototype, "protocolMode", { + /** + * ProtocolMode enum representing the way endpoints are constructed. + */ + get: function () { + return this.authorityOptions.protocolMode; + }, + enumerable: false, + configurable: true + }); + Object.defineProperty(Authority.prototype, "options", { + /** + * Returns authorityOptions which can be used to reinstantiate a new authority instance + */ + get: function () { + return this.authorityOptions; + }, + enumerable: false, + configurable: true + }); + Object.defineProperty(Authority.prototype, "canonicalAuthority", { + /** + * A URL that is the authority set by the developer + */ + get: function () { + return this._canonicalAuthority.urlString; + }, + /** + * Sets canonical authority. + */ + set: function (url) { + this._canonicalAuthority = new UrlString(url); + this._canonicalAuthority.validateAsUri(); + this._canonicalAuthorityUrlComponents = null; + }, + enumerable: false, + configurable: true + }); + Object.defineProperty(Authority.prototype, "canonicalAuthorityUrlComponents", { + /** + * Get authority components. + */ + get: function () { + if (!this._canonicalAuthorityUrlComponents) { + this._canonicalAuthorityUrlComponents = this._canonicalAuthority.getUrlComponents(); + } + return this._canonicalAuthorityUrlComponents; + }, + enumerable: false, + configurable: true + }); + Object.defineProperty(Authority.prototype, "hostnameAndPort", { + /** + * Get hostname and port i.e. login.microsoftonline.com + */ + get: function () { + return this.canonicalAuthorityUrlComponents.HostNameAndPort.toLowerCase(); + }, + enumerable: false, + configurable: true + }); + Object.defineProperty(Authority.prototype, "tenant", { + /** + * Get tenant for authority. + */ + get: function () { + return this.canonicalAuthorityUrlComponents.PathSegments[0]; + }, + enumerable: false, + configurable: true + }); + Object.defineProperty(Authority.prototype, "authorizationEndpoint", { + /** + * OAuth /authorize endpoint for requests + */ + get: function () { + if (this.discoveryComplete()) { + return this.replacePath(this.metadata.authorization_endpoint); + } + else { + throw ClientAuthError.createEndpointDiscoveryIncompleteError("Discovery incomplete."); + } + }, + enumerable: false, + configurable: true + }); + Object.defineProperty(Authority.prototype, "tokenEndpoint", { + /** + * OAuth /token endpoint for requests + */ + get: function () { + if (this.discoveryComplete()) { + return this.replacePath(this.metadata.token_endpoint); + } + else { + throw ClientAuthError.createEndpointDiscoveryIncompleteError("Discovery incomplete."); + } + }, + enumerable: false, + configurable: true + }); + Object.defineProperty(Authority.prototype, "deviceCodeEndpoint", { + get: function () { + if (this.discoveryComplete()) { + return this.replacePath(this.metadata.token_endpoint.replace("/token", "/devicecode")); + } + else { + throw ClientAuthError.createEndpointDiscoveryIncompleteError("Discovery incomplete."); + } + }, + enumerable: false, + configurable: true + }); + Object.defineProperty(Authority.prototype, "endSessionEndpoint", { + /** + * OAuth logout endpoint for requests + */ + get: function () { + if (this.discoveryComplete()) { + // ROPC policies may not have end_session_endpoint set + if (!this.metadata.end_session_endpoint) { + throw ClientAuthError.createLogoutNotSupportedError(); + } + return this.replacePath(this.metadata.end_session_endpoint); + } + else { + throw ClientAuthError.createEndpointDiscoveryIncompleteError("Discovery incomplete."); + } + }, + enumerable: false, + configurable: true + }); + Object.defineProperty(Authority.prototype, "selfSignedJwtAudience", { + /** + * OAuth issuer for requests + */ + get: function () { + if (this.discoveryComplete()) { + return this.replacePath(this.metadata.issuer); + } + else { + throw ClientAuthError.createEndpointDiscoveryIncompleteError("Discovery incomplete."); + } + }, + enumerable: false, + configurable: true + }); + Object.defineProperty(Authority.prototype, "jwksUri", { + /** + * Jwks_uri for token signing keys + */ + get: function () { + if (this.discoveryComplete()) { + return this.replacePath(this.metadata.jwks_uri); + } + else { + throw ClientAuthError.createEndpointDiscoveryIncompleteError("Discovery incomplete."); + } + }, + enumerable: false, + configurable: true + }); + /** + * Returns a flag indicating that tenant name can be replaced in authority {@link IUri} + * @param authorityUri {@link IUri} + * @private + */ + Authority.prototype.canReplaceTenant = function (authorityUri) { + return authorityUri.PathSegments.length === 1 + && !Authority.reservedTenantDomains.has(authorityUri.PathSegments[0]) + && this.getAuthorityType(authorityUri) === exports.AuthorityType.Default + && this.protocolMode === exports.ProtocolMode.AAD; + }; + /** + * Replaces tenant in url path with current tenant. Defaults to common. + * @param urlString + */ + Authority.prototype.replaceTenant = function (urlString) { + return urlString.replace(/{tenant}|{tenantid}/g, this.tenant); + }; + /** + * Replaces path such as tenant or policy with the current tenant or policy. + * @param urlString + */ + Authority.prototype.replacePath = function (urlString) { + var _this = this; + var endpoint = urlString; + var cachedAuthorityUrl = new UrlString(this.metadata.canonical_authority); + var cachedAuthorityUrlComponents = cachedAuthorityUrl.getUrlComponents(); + var cachedAuthorityParts = cachedAuthorityUrlComponents.PathSegments; + var currentAuthorityParts = this.canonicalAuthorityUrlComponents.PathSegments; + currentAuthorityParts.forEach(function (currentPart, index) { + var cachedPart = cachedAuthorityParts[index]; + if (index === 0 && _this.canReplaceTenant(cachedAuthorityUrlComponents)) { + var tenantId = (new UrlString(_this.metadata.authorization_endpoint)).getUrlComponents().PathSegments[0]; + /** + * Check if AAD canonical authority contains tenant domain name, for example "testdomain.onmicrosoft.com", + * by comparing its first path segment to the corresponding authorization endpoint path segment, which is + * always resolved with tenant id by OIDC. + */ + if (cachedPart !== tenantId) { + _this.logger.verbose("Replacing tenant domain name " + cachedPart + " with id " + tenantId); + cachedPart = tenantId; + } + } + if (currentPart !== cachedPart) { + endpoint = endpoint.replace("/" + cachedPart + "/", "/" + currentPart + "/"); + } + }); + return this.replaceTenant(endpoint); + }; + Object.defineProperty(Authority.prototype, "defaultOpenIdConfigurationEndpoint", { + /** + * The default open id configuration endpoint for any canonical authority. + */ + get: function () { + if (this.authorityType === exports.AuthorityType.Adfs || + this.authorityType === exports.AuthorityType.Dsts || + this.protocolMode === exports.ProtocolMode.OIDC) { + return this.canonicalAuthority + ".well-known/openid-configuration"; + } + return this.canonicalAuthority + "v2.0/.well-known/openid-configuration"; + }, + enumerable: false, + configurable: true + }); + /** + * Boolean that returns whethr or not tenant discovery has been completed. + */ + Authority.prototype.discoveryComplete = function () { + return !!this.metadata; + }; + /** + * Perform endpoint discovery to discover aliases, preferred_cache, preferred_network + * and the /authorize, /token and logout endpoints. + */ + Authority.prototype.resolveEndpointsAsync = function () { + var _a, _b, _c; + return __awaiter(this, void 0, void 0, function () { + var metadataEntity, cloudDiscoverySource, endpointSource, cacheKey; + return __generator(this, function (_d) { + switch (_d.label) { + case 0: + (_a = this.performanceClient) === null || _a === void 0 ? void 0 : _a.addQueueMeasurement(exports.PerformanceEvents.AuthorityResolveEndpointsAsync, this.correlationId); + metadataEntity = this.cacheManager.getAuthorityMetadataByAlias(this.hostnameAndPort); + if (!metadataEntity) { + metadataEntity = new AuthorityMetadataEntity(); + metadataEntity.updateCanonicalAuthority(this.canonicalAuthority); + } + (_b = this.performanceClient) === null || _b === void 0 ? void 0 : _b.setPreQueueTime(exports.PerformanceEvents.AuthorityUpdateCloudDiscoveryMetadata, this.correlationId); + return [4 /*yield*/, this.updateCloudDiscoveryMetadata(metadataEntity)]; + case 1: + cloudDiscoverySource = _d.sent(); + this.canonicalAuthority = this.canonicalAuthority.replace(this.hostnameAndPort, metadataEntity.preferred_network); + (_c = this.performanceClient) === null || _c === void 0 ? void 0 : _c.setPreQueueTime(exports.PerformanceEvents.AuthorityUpdateEndpointMetadata, this.correlationId); + return [4 /*yield*/, this.updateEndpointMetadata(metadataEntity)]; + case 2: + endpointSource = _d.sent(); + if (cloudDiscoverySource !== AuthorityMetadataSource.CACHE && endpointSource !== AuthorityMetadataSource.CACHE) { + // Reset the expiration time unless both values came from a successful cache lookup + metadataEntity.resetExpiresAt(); + metadataEntity.updateCanonicalAuthority(this.canonicalAuthority); + } + cacheKey = this.cacheManager.generateAuthorityMetadataCacheKey(metadataEntity.preferred_cache); + this.cacheManager.setAuthorityMetadata(cacheKey, metadataEntity); + this.metadata = metadataEntity; + return [2 /*return*/]; + } + }); + }); + }; + /** + * Update AuthorityMetadataEntity with new endpoints and return where the information came from + * @param metadataEntity + */ + Authority.prototype.updateEndpointMetadata = function (metadataEntity) { + var _a, _b, _c, _d, _e, _f; + return __awaiter(this, void 0, void 0, function () { + var metadata, harcodedMetadata; + return __generator(this, function (_g) { + switch (_g.label) { + case 0: + (_a = this.performanceClient) === null || _a === void 0 ? void 0 : _a.addQueueMeasurement(exports.PerformanceEvents.AuthorityUpdateEndpointMetadata, this.correlationId); + metadata = this.getEndpointMetadataFromConfig(); + if (metadata) { + metadataEntity.updateEndpointMetadata(metadata, false); + return [2 /*return*/, AuthorityMetadataSource.CONFIG]; + } + if (this.isAuthoritySameType(metadataEntity) && metadataEntity.endpointsFromNetwork && !metadataEntity.isExpired()) { + // No need to update + return [2 /*return*/, AuthorityMetadataSource.CACHE]; + } + (_b = this.performanceClient) === null || _b === void 0 ? void 0 : _b.setPreQueueTime(exports.PerformanceEvents.AuthorityGetEndpointMetadataFromNetwork, this.correlationId); + return [4 /*yield*/, this.getEndpointMetadataFromNetwork()]; + case 1: + metadata = _g.sent(); + if (!metadata) return [3 /*break*/, 4]; + if (!((_c = this.authorityOptions.azureRegionConfiguration) === null || _c === void 0 ? void 0 : _c.azureRegion)) return [3 /*break*/, 3]; + (_d = this.performanceClient) === null || _d === void 0 ? void 0 : _d.setPreQueueTime(exports.PerformanceEvents.AuthorityUpdateMetadataWithRegionalInformation, this.correlationId); + return [4 /*yield*/, this.updateMetadataWithRegionalInformation(metadata)]; + case 2: + metadata = _g.sent(); + _g.label = 3; + case 3: + metadataEntity.updateEndpointMetadata(metadata, true); + return [2 /*return*/, AuthorityMetadataSource.NETWORK]; + case 4: + harcodedMetadata = this.getEndpointMetadataFromHardcodedValues(); + if (!(harcodedMetadata && !this.authorityOptions.skipAuthorityMetadataCache)) return [3 /*break*/, 7]; + if (!((_e = this.authorityOptions.azureRegionConfiguration) === null || _e === void 0 ? void 0 : _e.azureRegion)) return [3 /*break*/, 6]; + (_f = this.performanceClient) === null || _f === void 0 ? void 0 : _f.setPreQueueTime(exports.PerformanceEvents.AuthorityUpdateMetadataWithRegionalInformation, this.correlationId); + return [4 /*yield*/, this.updateMetadataWithRegionalInformation(harcodedMetadata)]; + case 5: + harcodedMetadata = _g.sent(); + _g.label = 6; + case 6: + metadataEntity.updateEndpointMetadata(harcodedMetadata, false); + return [2 /*return*/, AuthorityMetadataSource.HARDCODED_VALUES]; + case 7: throw ClientAuthError.createUnableToGetOpenidConfigError(this.defaultOpenIdConfigurationEndpoint); + } + }); + }); + }; + /** + * Compares the number of url components after the domain to determine if the cached + * authority metadata can be used for the requested authority. Protects against same domain different + * authority such as login.microsoftonline.com/tenant and login.microsoftonline.com/tfp/tenant/policy + * @param metadataEntity + */ + Authority.prototype.isAuthoritySameType = function (metadataEntity) { + var cachedAuthorityUrl = new UrlString(metadataEntity.canonical_authority); + var cachedParts = cachedAuthorityUrl.getUrlComponents().PathSegments; + return cachedParts.length === this.canonicalAuthorityUrlComponents.PathSegments.length; + }; + /** + * Parse authorityMetadata config option + */ + Authority.prototype.getEndpointMetadataFromConfig = function () { + if (this.authorityOptions.authorityMetadata) { + try { + return JSON.parse(this.authorityOptions.authorityMetadata); + } + catch (e) { + throw ClientConfigurationError.createInvalidAuthorityMetadataError(); + } + } + return null; + }; + /** + * Gets OAuth endpoints from the given OpenID configuration endpoint. + * + * @param hasHardcodedMetadata boolean + */ + Authority.prototype.getEndpointMetadataFromNetwork = function () { + var _a; + return __awaiter(this, void 0, void 0, function () { + var options, response; + return __generator(this, function (_b) { + switch (_b.label) { + case 0: + (_a = this.performanceClient) === null || _a === void 0 ? void 0 : _a.addQueueMeasurement(exports.PerformanceEvents.AuthorityGetEndpointMetadataFromNetwork, this.correlationId); + options = {}; + _b.label = 1; + case 1: + _b.trys.push([1, 3, , 4]); + return [4 /*yield*/, this.networkInterface. + sendGetRequestAsync(this.defaultOpenIdConfigurationEndpoint, options)]; + case 2: + response = _b.sent(); + return [2 /*return*/, isOpenIdConfigResponse(response.body) ? response.body : null]; + case 3: + _b.sent(); + return [2 /*return*/, null]; + case 4: return [2 /*return*/]; + } + }); + }); + }; + /** + * Get OAuth endpoints for common authorities. + */ + Authority.prototype.getEndpointMetadataFromHardcodedValues = function () { + if (this.canonicalAuthority in EndpointMetadata) { + return EndpointMetadata[this.canonicalAuthority]; + } + return null; + }; + /** + * Update the retrieved metadata with regional information. + * User selected Azure region will be used if configured. + */ + Authority.prototype.updateMetadataWithRegionalInformation = function (metadata) { + var _a, _b, _c, _d; + return __awaiter(this, void 0, void 0, function () { + var userConfiguredAzureRegion, autodetectedRegionName; + return __generator(this, function (_e) { + switch (_e.label) { + case 0: + (_a = this.performanceClient) === null || _a === void 0 ? void 0 : _a.addQueueMeasurement(exports.PerformanceEvents.AuthorityUpdateMetadataWithRegionalInformation, this.correlationId); + userConfiguredAzureRegion = (_b = this.authorityOptions.azureRegionConfiguration) === null || _b === void 0 ? void 0 : _b.azureRegion; + if (!userConfiguredAzureRegion) return [3 /*break*/, 2]; + if (userConfiguredAzureRegion !== Constants.AZURE_REGION_AUTO_DISCOVER_FLAG) { + this.regionDiscoveryMetadata.region_outcome = RegionDiscoveryOutcomes.CONFIGURED_NO_AUTO_DETECTION; + this.regionDiscoveryMetadata.region_used = userConfiguredAzureRegion; + return [2 /*return*/, Authority.replaceWithRegionalInformation(metadata, userConfiguredAzureRegion)]; + } + (_c = this.performanceClient) === null || _c === void 0 ? void 0 : _c.setPreQueueTime(exports.PerformanceEvents.RegionDiscoveryDetectRegion, this.correlationId); + return [4 /*yield*/, this.regionDiscovery.detectRegion((_d = this.authorityOptions.azureRegionConfiguration) === null || _d === void 0 ? void 0 : _d.environmentRegion, this.regionDiscoveryMetadata)]; + case 1: + autodetectedRegionName = _e.sent(); + if (autodetectedRegionName) { + this.regionDiscoveryMetadata.region_outcome = RegionDiscoveryOutcomes.AUTO_DETECTION_REQUESTED_SUCCESSFUL; + this.regionDiscoveryMetadata.region_used = autodetectedRegionName; + return [2 /*return*/, Authority.replaceWithRegionalInformation(metadata, autodetectedRegionName)]; + } + this.regionDiscoveryMetadata.region_outcome = RegionDiscoveryOutcomes.AUTO_DETECTION_REQUESTED_FAILED; + _e.label = 2; + case 2: return [2 /*return*/, metadata]; + } + }); + }); + }; + /** + * Updates the AuthorityMetadataEntity with new aliases, preferred_network and preferred_cache + * and returns where the information was retrieved from + * @param metadataEntity + * @returns AuthorityMetadataSource + */ + Authority.prototype.updateCloudDiscoveryMetadata = function (metadataEntity) { + var _a, _b; + return __awaiter(this, void 0, void 0, function () { + var metadata, metadataEntityExpired, harcodedMetadata; + return __generator(this, function (_c) { + switch (_c.label) { + case 0: + (_a = this.performanceClient) === null || _a === void 0 ? void 0 : _a.addQueueMeasurement(exports.PerformanceEvents.AuthorityUpdateCloudDiscoveryMetadata, this.correlationId); + // attempt to read metadata from the config + this.logger.verbose("Attempting to get cloud discovery metadata in the config"); + this.logger.verbosePii("Known Authorities: " + (this.authorityOptions.knownAuthorities || Constants.NOT_APPLICABLE)); + this.logger.verbosePii("Authority Metadata: " + (this.authorityOptions.authorityMetadata || Constants.NOT_APPLICABLE)); + this.logger.verbosePii("Canonical Authority: " + (metadataEntity.canonical_authority || Constants.NOT_APPLICABLE)); + metadata = this.getCloudDiscoveryMetadataFromConfig(); + if (metadata) { + this.logger.verbose("Found cloud discovery metadata in the config."); + metadataEntity.updateCloudDiscoveryMetadata(metadata, false); + return [2 /*return*/, AuthorityMetadataSource.CONFIG]; + } + // If the cached metadata came from config but that config was not passed to this instance, we must go to the network + this.logger.verbose("Did not find cloud discovery metadata in the config... Attempting to get cloud discovery metadata from the cache."); + metadataEntityExpired = metadataEntity.isExpired(); + if (this.isAuthoritySameType(metadataEntity) && metadataEntity.aliasesFromNetwork && !metadataEntityExpired) { + this.logger.verbose("Found metadata in the cache."); + // No need to update + return [2 /*return*/, AuthorityMetadataSource.CACHE]; + } + else if (metadataEntityExpired) { + this.logger.verbose("The metadata entity is expired."); + } + this.logger.verbose("Did not find cloud discovery metadata in the cache... Attempting to get cloud discovery metadata from the network."); + (_b = this.performanceClient) === null || _b === void 0 ? void 0 : _b.setPreQueueTime(exports.PerformanceEvents.AuthorityGetCloudDiscoveryMetadataFromNetwork, this.correlationId); + return [4 /*yield*/, this.getCloudDiscoveryMetadataFromNetwork()]; + case 1: + metadata = _c.sent(); + if (metadata) { + this.logger.verbose("cloud discovery metadata was successfully returned from getCloudDiscoveryMetadataFromNetwork()"); + metadataEntity.updateCloudDiscoveryMetadata(metadata, true); + return [2 /*return*/, AuthorityMetadataSource.NETWORK]; + } + this.logger.verbose("Did not find cloud discovery metadata from the network... Attempting to get cloud discovery metadata from hardcoded values."); + harcodedMetadata = this.getCloudDiscoveryMetadataFromHarcodedValues(); + if (harcodedMetadata && !this.options.skipAuthorityMetadataCache) { + this.logger.verbose("Found cloud discovery metadata from hardcoded values."); + metadataEntity.updateCloudDiscoveryMetadata(harcodedMetadata, false); + return [2 /*return*/, AuthorityMetadataSource.HARDCODED_VALUES]; + } + // Metadata could not be obtained from the config, cache, network or hardcoded values + this.logger.error("Did not find cloud discovery metadata from hardcoded values... Metadata could not be obtained from config, cache, network or hardcoded values. Throwing Untrusted Authority Error."); + throw ClientConfigurationError.createUntrustedAuthorityError(); + } + }); + }); + }; + /** + * Parse cloudDiscoveryMetadata config or check knownAuthorities + */ + Authority.prototype.getCloudDiscoveryMetadataFromConfig = function () { + // CIAM does not support cloud discovery metadata + if (this.authorityType === exports.AuthorityType.Ciam) { + this.logger.verbose("CIAM authorities do not support cloud discovery metadata, generate the aliases from authority host."); + return Authority.createCloudDiscoveryMetadataFromHost(this.hostnameAndPort); + } + // Check if network response was provided in config + if (this.authorityOptions.cloudDiscoveryMetadata) { + this.logger.verbose("The cloud discovery metadata has been provided as a network response, in the config."); + try { + this.logger.verbose("Attempting to parse the cloud discovery metadata."); + var parsedResponse = JSON.parse(this.authorityOptions.cloudDiscoveryMetadata); + var metadata = Authority.getCloudDiscoveryMetadataFromNetworkResponse(parsedResponse.metadata, this.hostnameAndPort); + this.logger.verbose("Parsed the cloud discovery metadata."); + if (metadata) { + this.logger.verbose("There is returnable metadata attached to the parsed cloud discovery metadata."); + return metadata; + } + else { + this.logger.verbose("There is no metadata attached to the parsed cloud discovery metadata."); + } + } + catch (e) { + this.logger.verbose("Unable to parse the cloud discovery metadata. Throwing Invalid Cloud Discovery Metadata Error."); + throw ClientConfigurationError.createInvalidCloudDiscoveryMetadataError(); + } + } + // If cloudDiscoveryMetadata is empty or does not contain the host, check knownAuthorities + if (this.isInKnownAuthorities()) { + this.logger.verbose("The host is included in knownAuthorities. Creating new cloud discovery metadata from the host."); + return Authority.createCloudDiscoveryMetadataFromHost(this.hostnameAndPort); + } + return null; + }; + /** + * Called to get metadata from network if CloudDiscoveryMetadata was not populated by config + * + * @param hasHardcodedMetadata boolean + */ + Authority.prototype.getCloudDiscoveryMetadataFromNetwork = function () { + var _a; + return __awaiter(this, void 0, void 0, function () { + var instanceDiscoveryEndpoint, options, match, response, typedResponseBody, metadata, error_1, typedError; + return __generator(this, function (_b) { + switch (_b.label) { + case 0: + (_a = this.performanceClient) === null || _a === void 0 ? void 0 : _a.addQueueMeasurement(exports.PerformanceEvents.AuthorityGetCloudDiscoveryMetadataFromNetwork, this.correlationId); + instanceDiscoveryEndpoint = "" + Constants.AAD_INSTANCE_DISCOVERY_ENDPT + this.canonicalAuthority + "oauth2/v2.0/authorize"; + options = {}; + match = null; + _b.label = 1; + case 1: + _b.trys.push([1, 3, , 4]); + return [4 /*yield*/, this.networkInterface.sendGetRequestAsync(instanceDiscoveryEndpoint, options)]; + case 2: + response = _b.sent(); + typedResponseBody = void 0; + metadata = void 0; + if (isCloudInstanceDiscoveryResponse(response.body)) { + typedResponseBody = response.body; + metadata = typedResponseBody.metadata; + this.logger.verbosePii("tenant_discovery_endpoint is: " + typedResponseBody.tenant_discovery_endpoint); + } + else if (isCloudInstanceDiscoveryErrorResponse(response.body)) { + this.logger.warning("A CloudInstanceDiscoveryErrorResponse was returned. The cloud instance discovery network request's status code is: " + response.status); + typedResponseBody = response.body; + if (typedResponseBody.error === Constants.INVALID_INSTANCE) { + this.logger.error("The CloudInstanceDiscoveryErrorResponse error is invalid_instance."); + return [2 /*return*/, null]; + } + this.logger.warning("The CloudInstanceDiscoveryErrorResponse error is " + typedResponseBody.error); + this.logger.warning("The CloudInstanceDiscoveryErrorResponse error description is " + typedResponseBody.error_description); + this.logger.warning("Setting the value of the CloudInstanceDiscoveryMetadata (returned from the network) to []"); + metadata = []; + } + else { + this.logger.error("AAD did not return a CloudInstanceDiscoveryResponse or CloudInstanceDiscoveryErrorResponse"); + return [2 /*return*/, null]; + } + this.logger.verbose("Attempting to find a match between the developer's authority and the CloudInstanceDiscoveryMetadata returned from the network request."); + match = Authority.getCloudDiscoveryMetadataFromNetworkResponse(metadata, this.hostnameAndPort); + return [3 /*break*/, 4]; + case 3: + error_1 = _b.sent(); + if (error_1 instanceof AuthError) { + this.logger.error("There was a network error while attempting to get the cloud discovery instance metadata.\nError: " + error_1.errorCode + "\nError Description: " + error_1.errorMessage); + } + else { + typedError = error_1; + this.logger.error("A non-MSALJS error was thrown while attempting to get the cloud instance discovery metadata.\nError: " + typedError.name + "\nError Description: " + typedError.message); + } + return [2 /*return*/, null]; + case 4: + // Custom Domain scenario, host is trusted because Instance Discovery call succeeded + if (!match) { + this.logger.warning("The developer's authority was not found within the CloudInstanceDiscoveryMetadata returned from the network request."); + this.logger.verbose("Creating custom Authority for custom domain scenario."); + match = Authority.createCloudDiscoveryMetadataFromHost(this.hostnameAndPort); + } + return [2 /*return*/, match]; + } + }); + }); + }; + /** + * Get cloud discovery metadata for common authorities + */ + Authority.prototype.getCloudDiscoveryMetadataFromHarcodedValues = function () { + if (this.canonicalAuthority in InstanceDiscoveryMetadata) { + return InstanceDiscoveryMetadata[this.canonicalAuthority]; + } + return null; + }; + /** + * Helper function to determine if this host is included in the knownAuthorities config option + */ + Authority.prototype.isInKnownAuthorities = function () { + var _this = this; + var matches = this.authorityOptions.knownAuthorities.filter(function (authority) { + return UrlString.getDomainFromUrl(authority).toLowerCase() === _this.hostnameAndPort; + }); + return matches.length > 0; + }; + /** + * helper function to populate the authority based on azureCloudOptions + * @param authorityString + * @param azureCloudOptions + */ + Authority.generateAuthority = function (authorityString, azureCloudOptions) { + var authorityAzureCloudInstance; + if (azureCloudOptions && azureCloudOptions.azureCloudInstance !== exports.AzureCloudInstance.None) { + var tenant = azureCloudOptions.tenant ? azureCloudOptions.tenant : Constants.DEFAULT_COMMON_TENANT; + authorityAzureCloudInstance = azureCloudOptions.azureCloudInstance + "/" + tenant + "/"; + } + return authorityAzureCloudInstance ? authorityAzureCloudInstance : authorityString; + }; + /** + * Creates cloud discovery metadata object from a given host + * @param host + */ + Authority.createCloudDiscoveryMetadataFromHost = function (host) { + return { + preferred_network: host, + preferred_cache: host, + aliases: [host] + }; + }; + /** + * Searches instance discovery network response for the entry that contains the host in the aliases list + * @param response + * @param authority + */ + Authority.getCloudDiscoveryMetadataFromNetworkResponse = function (response, authority) { + for (var i = 0; i < response.length; i++) { + var metadata = response[i]; + if (metadata.aliases.indexOf(authority) > -1) { + return metadata; + } + } + return null; + }; + /** + * helper function to generate environment from authority object + */ + Authority.prototype.getPreferredCache = function () { + if (this.discoveryComplete()) { + return this.metadata.preferred_cache; + } + else { + throw ClientAuthError.createEndpointDiscoveryIncompleteError("Discovery incomplete."); + } + }; + /** + * Returns whether or not the provided host is an alias of this authority instance + * @param host + */ + Authority.prototype.isAlias = function (host) { + return this.metadata.aliases.indexOf(host) > -1; + }; + /** + * Checks whether the provided host is that of a public cloud authority + * + * @param authority string + * @returns bool + */ + Authority.isPublicCloudAuthority = function (host) { + return Constants.KNOWN_PUBLIC_CLOUDS.indexOf(host) >= 0; + }; + /** + * Rebuild the authority string with the region + * + * @param host string + * @param region string + */ + Authority.buildRegionalAuthorityString = function (host, region, queryString) { + // Create and validate a Url string object with the initial authority string + var authorityUrlInstance = new UrlString(host); + authorityUrlInstance.validateAsUri(); + var authorityUrlParts = authorityUrlInstance.getUrlComponents(); + var hostNameAndPort = region + "." + authorityUrlParts.HostNameAndPort; + if (this.isPublicCloudAuthority(authorityUrlParts.HostNameAndPort)) { + hostNameAndPort = region + "." + Constants.REGIONAL_AUTH_PUBLIC_CLOUD_SUFFIX; + } + // Include the query string portion of the url + var url = UrlString.constructAuthorityUriFromObject(__assign(__assign({}, authorityUrlInstance.getUrlComponents()), { HostNameAndPort: hostNameAndPort })).urlString; + // Add the query string if a query string was provided + if (queryString) + return url + "?" + queryString; + return url; + }; + /** + * Replace the endpoints in the metadata object with their regional equivalents. + * + * @param metadata OpenIdConfigResponse + * @param azureRegion string + */ + Authority.replaceWithRegionalInformation = function (metadata, azureRegion) { + metadata.authorization_endpoint = Authority.buildRegionalAuthorityString(metadata.authorization_endpoint, azureRegion); + // TODO: Enquire on whether we should leave the query string or remove it before releasing the feature + metadata.token_endpoint = Authority.buildRegionalAuthorityString(metadata.token_endpoint, azureRegion, Constants.REGIONAL_AUTH_NON_MSI_QUERY_STRING); + if (metadata.end_session_endpoint) { + metadata.end_session_endpoint = Authority.buildRegionalAuthorityString(metadata.end_session_endpoint, azureRegion); + } + return metadata; + }; + /** + * Transform CIAM_AUTHORIY as per the below rules: + * If no path segments found and it is a CIAM authority (hostname ends with .ciamlogin.com), then transform it + * + * NOTE: The transformation path should go away once STS supports CIAM with the format: `tenantIdorDomain.ciamlogin.com` + * `ciamlogin.com` can also change in the future and we should accommodate the same + * + * @param authority + */ + Authority.transformCIAMAuthority = function (authority) { + var ciamAuthority = authority.endsWith(Constants.FORWARD_SLASH) ? authority : "" + authority + Constants.FORWARD_SLASH; + var authorityUrl = new UrlString(authority); + var authorityUrlComponents = authorityUrl.getUrlComponents(); + // check if transformation is needed + if (authorityUrlComponents.PathSegments.length === 0 && (authorityUrlComponents.HostNameAndPort.endsWith(Constants.CIAM_AUTH_URL))) { + var tenantIdOrDomain = authorityUrlComponents.HostNameAndPort.split(".")[0]; + ciamAuthority = "" + ciamAuthority + tenantIdOrDomain + Constants.AAD_TENANT_DOMAIN_SUFFIX; + } + return ciamAuthority; + }; + // Reserved tenant domain names that will not be replaced with tenant id + Authority.reservedTenantDomains = (new Set([ + "{tenant}", + "{tenantid}", + AADAuthorityConstants.COMMON, + AADAuthorityConstants.CONSUMERS, + AADAuthorityConstants.ORGANIZATIONS + ])); + return Authority; +}()); + +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. + */ +var AuthorityFactory = /** @class */ (function () { + function AuthorityFactory() { + } + /** + * Create an authority object of the correct type based on the url + * Performs basic authority validation - checks to see if the authority is of a valid type (i.e. aad, b2c, adfs) + * + * Also performs endpoint discovery. + * + * @param authorityUri + * @param networkClient + * @param protocolMode + */ + AuthorityFactory.createDiscoveredInstance = function (authorityUri, networkClient, cacheManager, authorityOptions, logger, performanceClient, correlationId) { + return __awaiter(this, void 0, void 0, function () { + var authorityUriFinal, acquireTokenAuthority, e_1; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + performanceClient === null || performanceClient === void 0 ? void 0 : performanceClient.addQueueMeasurement(exports.PerformanceEvents.AuthorityFactoryCreateDiscoveredInstance, correlationId); + authorityUriFinal = Authority.transformCIAMAuthority(authorityUri); + acquireTokenAuthority = AuthorityFactory.createInstance(authorityUriFinal, networkClient, cacheManager, authorityOptions, logger, performanceClient, correlationId); + _a.label = 1; + case 1: + _a.trys.push([1, 3, , 4]); + performanceClient === null || performanceClient === void 0 ? void 0 : performanceClient.setPreQueueTime(exports.PerformanceEvents.AuthorityResolveEndpointsAsync, correlationId); + return [4 /*yield*/, acquireTokenAuthority.resolveEndpointsAsync()]; + case 2: + _a.sent(); + return [2 /*return*/, acquireTokenAuthority]; + case 3: + e_1 = _a.sent(); + throw ClientAuthError.createEndpointDiscoveryIncompleteError(e_1); + case 4: return [2 /*return*/]; + } + }); + }); + }; + /** + * Create an authority object of the correct type based on the url + * Performs basic authority validation - checks to see if the authority is of a valid type (i.e. aad, b2c, adfs) + * + * Does not perform endpoint discovery. + * + * @param authorityUrl + * @param networkInterface + * @param protocolMode + */ + AuthorityFactory.createInstance = function (authorityUrl, networkInterface, cacheManager, authorityOptions, logger, performanceClient, correlationId) { + // Throw error if authority url is empty + if (StringUtils.isEmpty(authorityUrl)) { + throw ClientConfigurationError.createUrlEmptyError(); + } + return new Authority(authorityUrl, networkInterface, cacheManager, authorityOptions, logger, performanceClient, correlationId); + }; + return AuthorityFactory; +}()); + +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. + */ +var ServerTelemetryEntity = /** @class */ (function () { + function ServerTelemetryEntity() { + this.failedRequests = []; + this.errors = []; + this.cacheHits = 0; + } + /** + * validates if a given cache entry is "Telemetry", parses + * @param key + * @param entity + */ + ServerTelemetryEntity.isServerTelemetryEntity = function (key, entity) { + var validateKey = key.indexOf(SERVER_TELEM_CONSTANTS.CACHE_KEY) === 0; + var validateEntity = true; + if (entity) { + validateEntity = + entity.hasOwnProperty("failedRequests") && + entity.hasOwnProperty("errors") && + entity.hasOwnProperty("cacheHits"); + } + return validateKey && validateEntity; + }; + return ServerTelemetryEntity; +}()); + +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. + */ +var ThrottlingEntity = /** @class */ (function () { + function ThrottlingEntity() { + } + /** + * validates if a given cache entry is "Throttling", parses + * @param key + * @param entity + */ + ThrottlingEntity.isThrottlingEntity = function (key, entity) { + var validateKey = false; + if (key) { + validateKey = key.indexOf(ThrottlingConstants.THROTTLING_PREFIX) === 0; + } + var validateEntity = true; + if (entity) { + validateEntity = entity.hasOwnProperty("throttleTime"); + } + return validateKey && validateEntity; + }; + return ThrottlingEntity; +}()); + +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. + */ +var StubbedNetworkModule = { + sendGetRequestAsync: function () { + var notImplErr = "Network interface - sendGetRequestAsync() has not been implemented for the Network interface."; + return Promise.reject(AuthError.createUnexpectedError(notImplErr)); + }, + sendPostRequestAsync: function () { + var notImplErr = "Network interface - sendPostRequestAsync() has not been implemented for the Network interface."; + return Promise.reject(AuthError.createUnexpectedError(notImplErr)); + } +}; + +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. + */ +/** + * ClientAuthErrorMessage class containing string constants used by error codes and messages. + */ +var JoseHeaderErrorMessage = { + missingKidError: { + code: "missing_kid_error", + desc: "The JOSE Header for the requested JWT, JWS or JWK object requires a keyId to be configured as the 'kid' header claim. No 'kid' value was provided." + }, + missingAlgError: { + code: "missing_alg_error", + desc: "The JOSE Header for the requested JWT, JWS or JWK object requires an algorithm to be specified as the 'alg' header claim. No 'alg' value was provided." + }, +}; +/** + * Error thrown when there is an error in the client code running on the browser. + */ +var JoseHeaderError = /** @class */ (function (_super) { + __extends(JoseHeaderError, _super); + function JoseHeaderError(errorCode, errorMessage) { + var _this = _super.call(this, errorCode, errorMessage) || this; + _this.name = "JoseHeaderError"; + Object.setPrototypeOf(_this, JoseHeaderError.prototype); + return _this; + } + /** + * Creates an error thrown when keyId isn't set on JOSE header. + */ + JoseHeaderError.createMissingKidError = function () { + return new JoseHeaderError(JoseHeaderErrorMessage.missingKidError.code, JoseHeaderErrorMessage.missingKidError.desc); + }; + /** + * Creates an error thrown when algorithm isn't set on JOSE header. + */ + JoseHeaderError.createMissingAlgError = function () { + return new JoseHeaderError(JoseHeaderErrorMessage.missingAlgError.code, JoseHeaderErrorMessage.missingAlgError.desc); + }; + return JoseHeaderError; +}(AuthError)); + +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. + */ +var JoseHeader = /** @class */ (function () { + function JoseHeader(options) { + this.typ = options.typ; + this.alg = options.alg; + this.kid = options.kid; + } + /** + * Builds SignedHttpRequest formatted JOSE Header from the + * JOSE Header options provided or previously set on the object and returns + * the stringified header object. + * Throws if keyId or algorithm aren't provided since they are required for Access Token Binding. + * @param shrHeaderOptions + * @returns + */ + JoseHeader.getShrHeaderString = function (shrHeaderOptions) { + // KeyID is required on the SHR header + if (!shrHeaderOptions.kid) { + throw JoseHeaderError.createMissingKidError(); + } + // Alg is required on the SHR header + if (!shrHeaderOptions.alg) { + throw JoseHeaderError.createMissingAlgError(); + } + var shrHeader = new JoseHeader({ + // Access Token PoP headers must have type pop, but the type header can be overriden for special cases + typ: shrHeaderOptions.typ || JsonTypes.Pop, + kid: shrHeaderOptions.kid, + alg: shrHeaderOptions.alg + }); + return JSON.stringify(shrHeader); + }; + return JoseHeader; +}()); + +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. + */ +/** + * This is a helper class that parses supported HTTP response authentication headers to extract and return + * header challenge values that can be used outside the basic authorization flows. + */ +var AuthenticationHeaderParser = /** @class */ (function () { + function AuthenticationHeaderParser(headers) { + this.headers = headers; + } + /** + * This method parses the SHR nonce value out of either the Authentication-Info or WWW-Authenticate authentication headers. + * @returns + */ + AuthenticationHeaderParser.prototype.getShrNonce = function () { + // Attempt to parse nonce from Authentiacation-Info + var authenticationInfo = this.headers[exports.HeaderNames.AuthenticationInfo]; + if (authenticationInfo) { + var authenticationInfoChallenges = this.parseChallenges(authenticationInfo); + if (authenticationInfoChallenges.nextnonce) { + return authenticationInfoChallenges.nextnonce; + } + throw ClientConfigurationError.createInvalidAuthenticationHeaderError(exports.HeaderNames.AuthenticationInfo, "nextnonce challenge is missing."); + } + // Attempt to parse nonce from WWW-Authenticate + var wwwAuthenticate = this.headers[exports.HeaderNames.WWWAuthenticate]; + if (wwwAuthenticate) { + var wwwAuthenticateChallenges = this.parseChallenges(wwwAuthenticate); + if (wwwAuthenticateChallenges.nonce) { + return wwwAuthenticateChallenges.nonce; + } + throw ClientConfigurationError.createInvalidAuthenticationHeaderError(exports.HeaderNames.WWWAuthenticate, "nonce challenge is missing."); + } + // If neither header is present, throw missing headers error + throw ClientConfigurationError.createMissingNonceAuthenticationHeadersError(); + }; + /** + * Parses an HTTP header's challenge set into a key/value map. + * @param header + * @returns + */ + AuthenticationHeaderParser.prototype.parseChallenges = function (header) { + var schemeSeparator = header.indexOf(" "); + var challenges = header.substr(schemeSeparator + 1).split(","); + var challengeMap = {}; + challenges.forEach(function (challenge) { + var _a = challenge.split("="), key = _a[0], value = _a[1]; + // Remove escaped quotation marks (', ") from challenge string to keep only the challenge value + challengeMap[key] = unescape(value.replace(/['"]+/g, Constants.EMPTY_STRING)); + }); + return challengeMap; + }; + return AuthenticationHeaderParser; +}()); + +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. + */ +var ServerTelemetryManager = /** @class */ (function () { + function ServerTelemetryManager(telemetryRequest, cacheManager) { + this.cacheOutcome = CacheOutcome.NO_CACHE_HIT; + this.cacheManager = cacheManager; + this.apiId = telemetryRequest.apiId; + this.correlationId = telemetryRequest.correlationId; + this.wrapperSKU = telemetryRequest.wrapperSKU || Constants.EMPTY_STRING; + this.wrapperVer = telemetryRequest.wrapperVer || Constants.EMPTY_STRING; + this.telemetryCacheKey = SERVER_TELEM_CONSTANTS.CACHE_KEY + Separators.CACHE_KEY_SEPARATOR + telemetryRequest.clientId; + } + /** + * API to add MSER Telemetry to request + */ + ServerTelemetryManager.prototype.generateCurrentRequestHeaderValue = function () { + var request = "" + this.apiId + SERVER_TELEM_CONSTANTS.VALUE_SEPARATOR + this.cacheOutcome; + var platformFields = [this.wrapperSKU, this.wrapperVer].join(SERVER_TELEM_CONSTANTS.VALUE_SEPARATOR); + var regionDiscoveryFields = this.getRegionDiscoveryFields(); + var requestWithRegionDiscoveryFields = [request, regionDiscoveryFields].join(SERVER_TELEM_CONSTANTS.VALUE_SEPARATOR); + return [SERVER_TELEM_CONSTANTS.SCHEMA_VERSION, requestWithRegionDiscoveryFields, platformFields].join(SERVER_TELEM_CONSTANTS.CATEGORY_SEPARATOR); + }; + /** + * API to add MSER Telemetry for the last failed request + */ + ServerTelemetryManager.prototype.generateLastRequestHeaderValue = function () { + var lastRequests = this.getLastRequests(); + var maxErrors = ServerTelemetryManager.maxErrorsToSend(lastRequests); + var failedRequests = lastRequests.failedRequests.slice(0, 2 * maxErrors).join(SERVER_TELEM_CONSTANTS.VALUE_SEPARATOR); + var errors = lastRequests.errors.slice(0, maxErrors).join(SERVER_TELEM_CONSTANTS.VALUE_SEPARATOR); + var errorCount = lastRequests.errors.length; + // Indicate whether this header contains all data or partial data + var overflow = maxErrors < errorCount ? SERVER_TELEM_CONSTANTS.OVERFLOW_TRUE : SERVER_TELEM_CONSTANTS.OVERFLOW_FALSE; + var platformFields = [errorCount, overflow].join(SERVER_TELEM_CONSTANTS.VALUE_SEPARATOR); + return [SERVER_TELEM_CONSTANTS.SCHEMA_VERSION, lastRequests.cacheHits, failedRequests, errors, platformFields].join(SERVER_TELEM_CONSTANTS.CATEGORY_SEPARATOR); + }; + /** + * API to cache token failures for MSER data capture + * @param error + */ + ServerTelemetryManager.prototype.cacheFailedRequest = function (error) { + var lastRequests = this.getLastRequests(); + if (lastRequests.errors.length >= SERVER_TELEM_CONSTANTS.MAX_CACHED_ERRORS) { + // Remove a cached error to make room, first in first out + lastRequests.failedRequests.shift(); // apiId + lastRequests.failedRequests.shift(); // correlationId + lastRequests.errors.shift(); + } + lastRequests.failedRequests.push(this.apiId, this.correlationId); + if (!StringUtils.isEmpty(error.subError)) { + lastRequests.errors.push(error.subError); + } + else if (!StringUtils.isEmpty(error.errorCode)) { + lastRequests.errors.push(error.errorCode); + } + else if (!!error && error.toString()) { + lastRequests.errors.push(error.toString()); + } + else { + lastRequests.errors.push(SERVER_TELEM_CONSTANTS.UNKNOWN_ERROR); + } + this.cacheManager.setServerTelemetry(this.telemetryCacheKey, lastRequests); + return; + }; + /** + * Update server telemetry cache entry by incrementing cache hit counter + */ + ServerTelemetryManager.prototype.incrementCacheHits = function () { + var lastRequests = this.getLastRequests(); + lastRequests.cacheHits += 1; + this.cacheManager.setServerTelemetry(this.telemetryCacheKey, lastRequests); + return lastRequests.cacheHits; + }; + /** + * Get the server telemetry entity from cache or initialize a new one + */ + ServerTelemetryManager.prototype.getLastRequests = function () { + var initialValue = new ServerTelemetryEntity(); + var lastRequests = this.cacheManager.getServerTelemetry(this.telemetryCacheKey); + return lastRequests || initialValue; + }; + /** + * Remove server telemetry cache entry + */ + ServerTelemetryManager.prototype.clearTelemetryCache = function () { + var lastRequests = this.getLastRequests(); + var numErrorsFlushed = ServerTelemetryManager.maxErrorsToSend(lastRequests); + var errorCount = lastRequests.errors.length; + if (numErrorsFlushed === errorCount) { + // All errors were sent on last request, clear Telemetry cache + this.cacheManager.removeItem(this.telemetryCacheKey); + } + else { + // Partial data was flushed to server, construct a new telemetry cache item with errors that were not flushed + var serverTelemEntity = new ServerTelemetryEntity(); + serverTelemEntity.failedRequests = lastRequests.failedRequests.slice(numErrorsFlushed * 2); // failedRequests contains 2 items for each error + serverTelemEntity.errors = lastRequests.errors.slice(numErrorsFlushed); + this.cacheManager.setServerTelemetry(this.telemetryCacheKey, serverTelemEntity); + } + }; + /** + * Returns the maximum number of errors that can be flushed to the server in the next network request + * @param serverTelemetryEntity + */ + ServerTelemetryManager.maxErrorsToSend = function (serverTelemetryEntity) { + var i; + var maxErrors = 0; + var dataSize = 0; + var errorCount = serverTelemetryEntity.errors.length; + for (i = 0; i < errorCount; i++) { + // failedRequests parameter contains pairs of apiId and correlationId, multiply index by 2 to preserve pairs + var apiId = serverTelemetryEntity.failedRequests[2 * i] || Constants.EMPTY_STRING; + var correlationId = serverTelemetryEntity.failedRequests[2 * i + 1] || Constants.EMPTY_STRING; + var errorCode = serverTelemetryEntity.errors[i] || Constants.EMPTY_STRING; + // Count number of characters that would be added to header, each character is 1 byte. Add 3 at the end to account for separators + dataSize += apiId.toString().length + correlationId.toString().length + errorCode.length + 3; + if (dataSize < SERVER_TELEM_CONSTANTS.MAX_LAST_HEADER_BYTES) { + // Adding this entry to the header would still keep header size below the limit + maxErrors += 1; + } + else { + break; + } + } + return maxErrors; + }; + /** + * Get the region discovery fields + * + * @returns string + */ + ServerTelemetryManager.prototype.getRegionDiscoveryFields = function () { + var regionDiscoveryFields = []; + regionDiscoveryFields.push(this.regionUsed || Constants.EMPTY_STRING); + regionDiscoveryFields.push(this.regionSource || Constants.EMPTY_STRING); + regionDiscoveryFields.push(this.regionOutcome || Constants.EMPTY_STRING); + return regionDiscoveryFields.join(","); + }; + /** + * Update the region discovery metadata + * + * @param regionDiscoveryMetadata + * @returns void + */ + ServerTelemetryManager.prototype.updateRegionDiscoveryMetadata = function (regionDiscoveryMetadata) { + this.regionUsed = regionDiscoveryMetadata.region_used; + this.regionSource = regionDiscoveryMetadata.region_source; + this.regionOutcome = regionDiscoveryMetadata.region_outcome; + }; + /** + * Set cache outcome + */ + ServerTelemetryManager.prototype.setCacheOutcome = function (cacheOutcome) { + this.cacheOutcome = cacheOutcome; + }; + return ServerTelemetryManager; +}()); + +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. + */ +var PerformanceClient = /** @class */ (function () { + /** + * Creates an instance of PerformanceClient, + * an abstract class containing core performance telemetry logic. + * + * @constructor + * @param {string} clientId Client ID of the application + * @param {string} authority Authority used by the application + * @param {Logger} logger Logger used by the application + * @param {string} libraryName Name of the library + * @param {string} libraryVersion Version of the library + */ + function PerformanceClient(clientId, authority, logger, libraryName, libraryVersion, applicationTelemetry) { + this.authority = authority; + this.libraryName = libraryName; + this.libraryVersion = libraryVersion; + this.applicationTelemetry = applicationTelemetry; + this.clientId = clientId; + this.logger = logger; + this.callbacks = new Map(); + this.eventsByCorrelationId = new Map(); + this.queueMeasurements = new Map(); + this.preQueueTimeByCorrelationId = new Map(); + } + /** + * Starts and returns an platform-specific implementation of IPerformanceMeasurement. + * Note: this function can be changed to abstract at the next major version bump. + * + * @param {string} measureName + * @param {string} correlationId + * @returns {IPerformanceMeasurement} + */ + /* eslint-disable-next-line @typescript-eslint/no-unused-vars */ + PerformanceClient.prototype.startPerformanceMeasurement = function (measureName, correlationId) { + return {}; + }; + /** + * Starts and returns an platform-specific implementation of IPerformanceMeasurement. + * Note: this incorrectly-named function will be removed at the next major version bump. + * + * @param {string} measureName + * @param {string} correlationId + * @returns {IPerformanceMeasurement} + */ + /* eslint-disable-next-line @typescript-eslint/no-unused-vars */ + PerformanceClient.prototype.startPerformanceMeasuremeant = function (measureName, correlationId) { + return {}; + }; + /** + * Get integral fields. + * Override to change the set. + */ + PerformanceClient.prototype.getIntFields = function () { + return IntFields; + }; + /** + * Gets map of pre-queue times by correlation Id + * + * @param {PerformanceEvents} eventName + * @param {string} correlationId + * @returns {number} + */ + PerformanceClient.prototype.getPreQueueTime = function (eventName, correlationId) { + var preQueueEvent = this.preQueueTimeByCorrelationId.get(correlationId); + if (!preQueueEvent) { + this.logger.trace("PerformanceClient.getPreQueueTime: no pre-queue times found for correlationId: " + correlationId + ", unable to add queue measurement"); + return; + } + else if (preQueueEvent.name !== eventName) { + this.logger.trace("PerformanceClient.getPreQueueTime: no pre-queue time found for " + eventName + ", unable to add queue measurement"); + return; + } + return preQueueEvent.time; + }; + /** + * Calculates the difference between current time and time when function was queued. + * Note: It is possible to have 0 as the queue time if the current time and the queued time was the same. + * + * @param {number} preQueueTime + * @param {number} currentTime + * @returns {number} + */ + PerformanceClient.prototype.calculateQueuedTime = function (preQueueTime, currentTime) { + if (preQueueTime < 1) { + this.logger.trace("PerformanceClient: preQueueTime should be a positive integer and not " + preQueueTime); + return 0; + } + if (currentTime < 1) { + this.logger.trace("PerformanceClient: currentTime should be a positive integer and not " + currentTime); + return 0; + } + if (currentTime < preQueueTime) { + this.logger.trace("PerformanceClient: currentTime is less than preQueueTime, check how time is being retrieved"); + return 0; + } + return currentTime - preQueueTime; + }; + /** + * Adds queue measurement time to QueueMeasurements array for given correlation ID. + * + * @param {PerformanceEvents} eventName + * @param {?string} correlationId + * @param {?number} queueTime + * @param {?boolean} manuallyCompleted - indicator for manually completed queue measurements + * @returns + */ + PerformanceClient.prototype.addQueueMeasurement = function (eventName, correlationId, queueTime, manuallyCompleted) { + if (!correlationId) { + this.logger.trace("PerformanceClient.addQueueMeasurement: correlationId not provided for " + eventName + ", cannot add queue measurement"); + return; + } + if (queueTime === 0) { + // Possible for there to be no queue time after calculation + this.logger.trace("PerformanceClient.addQueueMeasurement: queue time provided for " + eventName + " is " + queueTime); + } + else if (!queueTime) { + this.logger.trace("PerformanceClient.addQueueMeasurement: no queue time provided for " + eventName); + return; + } + var queueMeasurement = { eventName: eventName, queueTime: queueTime, manuallyCompleted: manuallyCompleted }; + // Adds to existing correlation Id if present in queueMeasurements + var existingMeasurements = this.queueMeasurements.get(correlationId); + if (existingMeasurements) { + existingMeasurements.push(queueMeasurement); + this.queueMeasurements.set(correlationId, existingMeasurements); + } + else { + // Sets new correlation Id if not present in queueMeasurements + this.logger.trace("PerformanceClient.addQueueMeasurement: adding correlationId " + correlationId + " to queue measurements"); + var measurementArray = [queueMeasurement]; + this.queueMeasurements.set(correlationId, measurementArray); + } + // Delete processed pre-queue event. + this.preQueueTimeByCorrelationId.delete(correlationId); + }; + /** + * Starts measuring performance for a given operation. Returns a function that should be used to end the measurement. + * + * @param {PerformanceEvents} measureName + * @param {?string} [correlationId] + * @returns {InProgressPerformanceEvent} + */ + PerformanceClient.prototype.startMeasurement = function (measureName, correlationId) { + var _this = this; + var _a, _b; + // Generate a placeholder correlation if the request does not provide one + var eventCorrelationId = correlationId || this.generateId(); + if (!correlationId) { + this.logger.info("PerformanceClient: No correlation id provided for " + measureName + ", generating", eventCorrelationId); + } + // Duplicate code to address spelling error will be removed at the next major version bump. + this.logger.trace("PerformanceClient: Performance measurement started for " + measureName, eventCorrelationId); + var performanceMeasurement = this.startPerformanceMeasuremeant(measureName, eventCorrelationId); + performanceMeasurement.startMeasurement(); + var inProgressEvent = { + eventId: this.generateId(), + status: exports.PerformanceEventStatus.InProgress, + authority: this.authority, + libraryName: this.libraryName, + libraryVersion: this.libraryVersion, + clientId: this.clientId, + name: measureName, + startTimeMs: Date.now(), + correlationId: eventCorrelationId, + appName: (_a = this.applicationTelemetry) === null || _a === void 0 ? void 0 : _a.appName, + appVersion: (_b = this.applicationTelemetry) === null || _b === void 0 ? void 0 : _b.appVersion, + }; + // Store in progress events so they can be discarded if not ended properly + this.cacheEventByCorrelationId(inProgressEvent); + // Return the event and functions the caller can use to properly end/flush the measurement + return { + endMeasurement: function (event) { + return _this.endMeasurement(__assign(__assign({}, inProgressEvent), event), performanceMeasurement); + }, + discardMeasurement: function () { + return _this.discardMeasurements(inProgressEvent.correlationId); + }, + addStaticFields: function (fields) { + return _this.addStaticFields(fields, inProgressEvent.correlationId); + }, + increment: function (counters) { + return _this.increment(counters, inProgressEvent.correlationId); + }, + measurement: performanceMeasurement, + event: inProgressEvent + }; + }; + /** + * Stops measuring the performance for an operation. Should only be called directly by PerformanceClient classes, + * as consumers should instead use the function returned by startMeasurement. + * Adds a new field named as "[event name]DurationMs" for sub-measurements, completes and emits an event + * otherwise. + * + * @param {PerformanceEvent} event + * @param {IPerformanceMeasurement} measurement + * @returns {(PerformanceEvent | null)} + */ + PerformanceClient.prototype.endMeasurement = function (event, measurement) { + var _this = this; + var _a, _b; + var rootEvent = this.eventsByCorrelationId.get(event.correlationId); + if (!rootEvent) { + this.logger.trace("PerformanceClient: Measurement not found for " + event.eventId, event.correlationId); + return null; + } + var isRoot = event.eventId === rootEvent.eventId; + var queueInfo = { + totalQueueTime: 0, + totalQueueCount: 0, + manuallyCompletedCount: 0 + }; + if (isRoot) { + queueInfo = this.getQueueInfo(event.correlationId); + this.discardCache(rootEvent.correlationId); + } + else { + (_a = rootEvent.incompleteSubMeasurements) === null || _a === void 0 ? void 0 : _a.delete(event.eventId); + } + measurement === null || measurement === void 0 ? void 0 : measurement.endMeasurement(); + var durationMs = measurement === null || measurement === void 0 ? void 0 : measurement.flushMeasurement(); + // null indicates no measurement was taken (e.g. needed performance APIs not present) + if (!durationMs) { + this.logger.trace("PerformanceClient: Performance measurement not taken", rootEvent.correlationId); + return null; + } + this.logger.trace("PerformanceClient: Performance measurement ended for " + event.name + ": " + durationMs + " ms", event.correlationId); + // Add sub-measurement attribute to root event. + if (!isRoot) { + rootEvent[event.name + "DurationMs"] = Math.floor(durationMs); + return __assign({}, rootEvent); + } + var finalEvent = __assign(__assign({}, rootEvent), event); + var incompleteSubsCount = 0; + // Incomplete sub-measurements are discarded. They are likely an instrumentation bug that should be fixed. + (_b = finalEvent.incompleteSubMeasurements) === null || _b === void 0 ? void 0 : _b.forEach(function (subMeasurement) { + _this.logger.trace("PerformanceClient: Incomplete submeasurement " + subMeasurement.name + " found for " + event.name, finalEvent.correlationId); + incompleteSubsCount++; + }); + finalEvent.incompleteSubMeasurements = undefined; + finalEvent = __assign(__assign({}, finalEvent), { durationMs: Math.round(durationMs), queuedTimeMs: queueInfo.totalQueueTime, queuedCount: queueInfo.totalQueueCount, queuedManuallyCompletedCount: queueInfo.manuallyCompletedCount, status: exports.PerformanceEventStatus.Completed, incompleteSubsCount: incompleteSubsCount }); + this.truncateIntegralFields(finalEvent, this.getIntFields()); + this.emitEvents([finalEvent], event.correlationId); + return finalEvent; + }; + /** + * Saves extra information to be emitted when the measurements are flushed + * @param fields + * @param correlationId + */ + PerformanceClient.prototype.addStaticFields = function (fields, correlationId) { + this.logger.trace("PerformanceClient: Updating static fields"); + var event = this.eventsByCorrelationId.get(correlationId); + if (event) { + this.eventsByCorrelationId.set(correlationId, __assign(__assign({}, event), fields)); + } + else { + this.logger.trace("PerformanceClient: Event not found for", correlationId); + } + }; + /** + * Increment counters to be emitted when the measurements are flushed + * @param counters {Counters} + * @param correlationId {string} correlation identifier + */ + PerformanceClient.prototype.increment = function (counters, correlationId) { + this.logger.trace("PerformanceClient: Updating counters"); + var event = this.eventsByCorrelationId.get(correlationId); + if (event) { + for (var counter in counters) { + if (!event.hasOwnProperty(counter)) { + event[counter] = 0; + } + event[counter] += counters[counter]; + } + } + else { + this.logger.trace("PerformanceClient: Event not found for", correlationId); + } + }; + /** + * Upserts event into event cache. + * First key is the correlation id, second key is the event id. + * Allows for events to be grouped by correlation id, + * and to easily allow for properties on them to be updated. + * + * @private + * @param {PerformanceEvent} event + */ + PerformanceClient.prototype.cacheEventByCorrelationId = function (event) { + var rootEvent = this.eventsByCorrelationId.get(event.correlationId); + if (rootEvent) { + this.logger.trace("PerformanceClient: Performance measurement for " + event.name + " added/updated", event.correlationId); + rootEvent.incompleteSubMeasurements = rootEvent.incompleteSubMeasurements || new Map(); + rootEvent.incompleteSubMeasurements.set(event.eventId, { name: event.name, startTimeMs: event.startTimeMs }); + } + else { + this.logger.trace("PerformanceClient: Performance measurement for " + event.name + " started", event.correlationId); + this.eventsByCorrelationId.set(event.correlationId, __assign({}, event)); + } + }; + PerformanceClient.prototype.getQueueInfo = function (correlationId) { + var queueMeasurementForCorrelationId = this.queueMeasurements.get(correlationId); + if (!queueMeasurementForCorrelationId) { + this.logger.trace("PerformanceClient: no queue measurements found for for correlationId: " + correlationId); + } + var totalQueueTime = 0; + var totalQueueCount = 0; + var manuallyCompletedCount = 0; + queueMeasurementForCorrelationId === null || queueMeasurementForCorrelationId === void 0 ? void 0 : queueMeasurementForCorrelationId.forEach(function (measurement) { + totalQueueTime += measurement.queueTime; + totalQueueCount++; + manuallyCompletedCount += measurement.manuallyCompleted ? 1 : 0; + }); + return { + totalQueueTime: totalQueueTime, + totalQueueCount: totalQueueCount, + manuallyCompletedCount: manuallyCompletedCount + }; + }; + /** + * Removes measurements for a given correlation id. + * + * @param {string} correlationId + */ + PerformanceClient.prototype.discardMeasurements = function (correlationId) { + this.logger.trace("PerformanceClient: Performance measurements discarded", correlationId); + this.eventsByCorrelationId.delete(correlationId); + }; + /** + * Removes cache for a given correlation id. + * + * @param {string} correlationId correlation identifier + */ + PerformanceClient.prototype.discardCache = function (correlationId) { + this.discardMeasurements(correlationId); + this.logger.trace("PerformanceClient: QueueMeasurements discarded", correlationId); + this.queueMeasurements.delete(correlationId); + this.logger.trace("PerformanceClient: Pre-queue times discarded", correlationId); + this.preQueueTimeByCorrelationId.delete(correlationId); + }; + /** + * Registers a callback function to receive performance events. + * + * @param {PerformanceCallbackFunction} callback + * @returns {string} + */ + PerformanceClient.prototype.addPerformanceCallback = function (callback) { + var callbackId = this.generateId(); + this.callbacks.set(callbackId, callback); + this.logger.verbose("PerformanceClient: Performance callback registered with id: " + callbackId); + return callbackId; + }; + /** + * Removes a callback registered with addPerformanceCallback. + * + * @param {string} callbackId + * @returns {boolean} + */ + PerformanceClient.prototype.removePerformanceCallback = function (callbackId) { + var result = this.callbacks.delete(callbackId); + if (result) { + this.logger.verbose("PerformanceClient: Performance callback " + callbackId + " removed."); + } + else { + this.logger.verbose("PerformanceClient: Performance callback " + callbackId + " not removed."); + } + return result; + }; + /** + * Emits events to all registered callbacks. + * + * @param {PerformanceEvent[]} events + * @param {?string} [correlationId] + */ + PerformanceClient.prototype.emitEvents = function (events, correlationId) { + var _this = this; + this.logger.verbose("PerformanceClient: Emitting performance events", correlationId); + this.callbacks.forEach(function (callback, callbackId) { + _this.logger.trace("PerformanceClient: Emitting event to callback " + callbackId, correlationId); + callback.apply(null, [events]); + }); + }; + /** + * Enforce truncation of integral fields in performance event. + * @param {PerformanceEvent} event performance event to update. + * @param {Set} intFields integral fields. + */ + PerformanceClient.prototype.truncateIntegralFields = function (event, intFields) { + intFields.forEach(function (key) { + if (key in event && typeof event[key] === "number") { + event[key] = Math.floor(event[key]); + } + }); + }; + return PerformanceClient; +}()); + +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. + */ +var StubPerformanceMeasurement = /** @class */ (function () { + function StubPerformanceMeasurement() { + } + /* eslint-disable-next-line @typescript-eslint/no-empty-function */ + StubPerformanceMeasurement.prototype.startMeasurement = function () { }; + /* eslint-disable-next-line @typescript-eslint/no-empty-function */ + StubPerformanceMeasurement.prototype.endMeasurement = function () { }; + StubPerformanceMeasurement.prototype.flushMeasurement = function () { + return null; + }; + return StubPerformanceMeasurement; +}()); +var StubPerformanceClient = /** @class */ (function (_super) { + __extends(StubPerformanceClient, _super); + function StubPerformanceClient() { + return _super !== null && _super.apply(this, arguments) || this; + } + StubPerformanceClient.prototype.generateId = function () { + return "callback-id"; + }; + StubPerformanceClient.prototype.startPerformanceMeasuremeant = function () { + return new StubPerformanceMeasurement(); + }; + StubPerformanceClient.prototype.startPerformanceMeasurement = function () { + return new StubPerformanceMeasurement(); + }; + /* eslint-disable-next-line @typescript-eslint/no-unused-vars */ + StubPerformanceClient.prototype.calculateQueuedTime = function (preQueueTime, currentTime) { + return 0; + }; + /* eslint-disable-next-line @typescript-eslint/no-unused-vars */ + StubPerformanceClient.prototype.addQueueMeasurement = function (eventName, correlationId, queueTime) { + return; + }; + /* eslint-disable-next-line @typescript-eslint/no-unused-vars */ + StubPerformanceClient.prototype.setPreQueueTime = function (eventName, correlationId) { + return; + }; + return StubPerformanceClient; +}(PerformanceClient)); + +exports.AccessTokenEntity = AccessTokenEntity; +exports.AccountEntity = AccountEntity; +exports.AppMetadataEntity = AppMetadataEntity; +exports.AuthError = AuthError; +exports.AuthErrorMessage = AuthErrorMessage; +exports.AuthToken = AuthToken; +exports.AuthenticationHeaderParser = AuthenticationHeaderParser; +exports.Authority = Authority; +exports.AuthorityFactory = AuthorityFactory; +exports.AuthorityMetadataEntity = AuthorityMetadataEntity; +exports.AuthorizationCodeClient = AuthorizationCodeClient; +exports.CacheManager = CacheManager; +exports.CacheRecord = CacheRecord; +exports.ClientAuthError = ClientAuthError; +exports.ClientAuthErrorMessage = ClientAuthErrorMessage; +exports.ClientConfigurationError = ClientConfigurationError; +exports.ClientConfigurationErrorMessage = ClientConfigurationErrorMessage; +exports.ClientCredentialClient = ClientCredentialClient; +exports.CodeChallengeMethodValues = CodeChallengeMethodValues; +exports.Constants = Constants; +exports.CredentialEntity = CredentialEntity; +exports.DEFAULT_CRYPTO_IMPLEMENTATION = DEFAULT_CRYPTO_IMPLEMENTATION; +exports.DEFAULT_SYSTEM_OPTIONS = DEFAULT_SYSTEM_OPTIONS; +exports.DefaultStorageClass = DefaultStorageClass; +exports.DeviceCodeClient = DeviceCodeClient; +exports.Errors = Errors; +exports.IdToken = AuthToken; +exports.IdTokenEntity = IdTokenEntity; +exports.IntFields = IntFields; +exports.InteractionRequiredAuthError = InteractionRequiredAuthError; +exports.InteractionRequiredAuthErrorMessage = InteractionRequiredAuthErrorMessage; +exports.JoseHeader = JoseHeader; +exports.Logger = Logger; +exports.NetworkManager = NetworkManager; +exports.OIDC_DEFAULT_SCOPES = OIDC_DEFAULT_SCOPES; +exports.ONE_DAY_IN_MS = ONE_DAY_IN_MS; +exports.OnBehalfOfClient = OnBehalfOfClient; +exports.PerformanceClient = PerformanceClient; +exports.PopTokenGenerator = PopTokenGenerator; +exports.PromptValue = PromptValue; +exports.ProtocolUtils = ProtocolUtils; +exports.RefreshTokenClient = RefreshTokenClient; +exports.RefreshTokenEntity = RefreshTokenEntity; +exports.ScopeSet = ScopeSet; +exports.ServerError = ServerError; +exports.ServerTelemetryEntity = ServerTelemetryEntity; +exports.ServerTelemetryManager = ServerTelemetryManager; +exports.SilentFlowClient = SilentFlowClient; +exports.StringUtils = StringUtils; +exports.StubPerformanceClient = StubPerformanceClient; +exports.StubbedNetworkModule = StubbedNetworkModule; +exports.THE_FAMILY_ID = THE_FAMILY_ID; +exports.ThrottlingConstants = ThrottlingConstants; +exports.ThrottlingEntity = ThrottlingEntity; +exports.ThrottlingUtils = ThrottlingUtils; +exports.TimeUtils = TimeUtils; +exports.TokenCacheContext = TokenCacheContext; +exports.UrlString = UrlString; +exports.UsernamePasswordClient = UsernamePasswordClient; +exports.buildClientInfo = buildClientInfo; +exports.buildClientInfoFromHomeAccountId = buildClientInfoFromHomeAccountId; +exports.version = version; +//# sourceMappingURL=index.cjs.js.map + + +/***/ }), + +/***/ 2884: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + + +if (process.env.NODE_ENV === 'production') { + module.exports = __nccwpck_require__(9802) +} else { + module.exports = __nccwpck_require__(5674) +} + + +/***/ }), + +/***/ 5674: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ value: true })); + +function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; } + +var msalCommon = __nccwpck_require__(5728); +var http = __nccwpck_require__(3685); +var http__default = _interopDefault(http); +var https = _interopDefault(__nccwpck_require__(5687)); +var uuid = __nccwpck_require__(5840); +var crypto = _interopDefault(__nccwpck_require__(6113)); +var jsonwebtoken = __nccwpck_require__(7486); + +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. + */ +/** + * http methods + */ +var HttpMethod; +(function (HttpMethod) { + HttpMethod["GET"] = "get"; + HttpMethod["POST"] = "post"; +})(HttpMethod || (HttpMethod = {})); +var HttpStatus; +(function (HttpStatus) { + HttpStatus[HttpStatus["SUCCESS_RANGE_START"] = 200] = "SUCCESS_RANGE_START"; + HttpStatus[HttpStatus["SUCCESS_RANGE_END"] = 299] = "SUCCESS_RANGE_END"; + HttpStatus[HttpStatus["REDIRECT"] = 302] = "REDIRECT"; + HttpStatus[HttpStatus["CLIENT_ERROR_RANGE_START"] = 400] = "CLIENT_ERROR_RANGE_START"; + HttpStatus[HttpStatus["CLIENT_ERROR_RANGE_END"] = 499] = "CLIENT_ERROR_RANGE_END"; + HttpStatus[HttpStatus["SERVER_ERROR_RANGE_START"] = 500] = "SERVER_ERROR_RANGE_START"; + HttpStatus[HttpStatus["SERVER_ERROR_RANGE_END"] = 599] = "SERVER_ERROR_RANGE_END"; +})(HttpStatus || (HttpStatus = {})); +var ProxyStatus; +(function (ProxyStatus) { + ProxyStatus[ProxyStatus["SUCCESS_RANGE_START"] = 200] = "SUCCESS_RANGE_START"; + ProxyStatus[ProxyStatus["SUCCESS_RANGE_END"] = 299] = "SUCCESS_RANGE_END"; + ProxyStatus[ProxyStatus["SERVER_ERROR"] = 500] = "SERVER_ERROR"; +})(ProxyStatus || (ProxyStatus = {})); +/** + * Constants used for region discovery + */ +const REGION_ENVIRONMENT_VARIABLE = "REGION_NAME"; +/** + * Constant used for PKCE + */ +const RANDOM_OCTET_SIZE = 32; +/** + * Constants used in PKCE + */ +const Hash = { + SHA256: "sha256" +}; +/** + * Constants for encoding schemes + */ +const CharSet = { + CV_CHARSET: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~" +}; +/** + * Constants + */ +const Constants = { + MSAL_SKU: "msal.js.node", + JWT_BEARER_ASSERTION_TYPE: "urn:ietf:params:oauth:client-assertion-type:jwt-bearer", + AUTHORIZATION_PENDING: "authorization_pending", + HTTP_PROTOCOL: "http://", + LOCALHOST: "localhost" +}; +/** + * API Codes for Telemetry purposes. + * Before adding a new code you must claim it in the MSAL Telemetry tracker as these number spaces are shared across all MSALs + * 0-99 Silent Flow + * 600-699 Device Code Flow + * 800-899 Auth Code Flow + */ +var ApiId; +(function (ApiId) { + ApiId[ApiId["acquireTokenSilent"] = 62] = "acquireTokenSilent"; + ApiId[ApiId["acquireTokenByUsernamePassword"] = 371] = "acquireTokenByUsernamePassword"; + ApiId[ApiId["acquireTokenByDeviceCode"] = 671] = "acquireTokenByDeviceCode"; + ApiId[ApiId["acquireTokenByClientCredential"] = 771] = "acquireTokenByClientCredential"; + ApiId[ApiId["acquireTokenByCode"] = 871] = "acquireTokenByCode"; + ApiId[ApiId["acquireTokenByRefreshToken"] = 872] = "acquireTokenByRefreshToken"; +})(ApiId || (ApiId = {})); +/** + * JWT constants + */ +const JwtConstants = { + ALGORITHM: "alg", + RSA_256: "RS256", + X5T: "x5t", + X5C: "x5c", + AUDIENCE: "aud", + EXPIRATION_TIME: "exp", + ISSUER: "iss", + SUBJECT: "sub", + NOT_BEFORE: "nbf", + JWT_ID: "jti" +}; +const LOOPBACK_SERVER_CONSTANTS = { + INTERVAL_MS: 100, + TIMEOUT_MS: 5000 +}; + +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. + */ +class NetworkUtils { + static getNetworkResponse(headers, body, statusCode) { + return { + headers: headers, + body: body, + status: statusCode + }; + } + /* + * Utility function that converts a URL object into an ordinary options object as expected by the + * http.request and https.request APIs. + * https://github.com/nodejs/node/blob/main/lib/internal/url.js#L1090 + */ + static urlToHttpOptions(url) { + const options = { + protocol: url.protocol, + hostname: url.hostname && url.hostname.startsWith("[") ? url.hostname.slice(1, -1) : url.hostname, + hash: url.hash, + search: url.search, + pathname: url.pathname, + path: `${url.pathname || ""}${url.search || ""}`, + href: url.href + }; + if (url.port !== "") { + options.port = Number(url.port); + } + if (url.username || url.password) { + options.auth = `${decodeURIComponent(url.username)}:${decodeURIComponent(url.password)}`; + } + return options; + } +} + +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. + */ +/** + * This class implements the API for network requests. + */ +class HttpClient { + constructor(proxyUrl, customAgentOptions) { + this.proxyUrl = proxyUrl || ""; + this.customAgentOptions = customAgentOptions || {}; + } + /** + * Http Get request + * @param url + * @param options + */ + async sendGetRequestAsync(url, options) { + if (this.proxyUrl) { + return networkRequestViaProxy(url, this.proxyUrl, HttpMethod.GET, options, this.customAgentOptions); + } else { + return networkRequestViaHttps(url, HttpMethod.GET, options, this.customAgentOptions); + } + } + /** + * Http Post request + * @param url + * @param options + */ + async sendPostRequestAsync(url, options, cancellationToken) { + if (this.proxyUrl) { + return networkRequestViaProxy(url, this.proxyUrl, HttpMethod.POST, options, this.customAgentOptions, cancellationToken); + } else { + return networkRequestViaHttps(url, HttpMethod.POST, options, this.customAgentOptions, cancellationToken); + } + } +} +const networkRequestViaProxy = (destinationUrlString, proxyUrlString, httpMethod, options, agentOptions, timeout) => { + const destinationUrl = new URL(destinationUrlString); + const proxyUrl = new URL(proxyUrlString); + // "method: connect" must be used to establish a connection to the proxy + const headers = (options == null ? void 0 : options.headers) || {}; + const tunnelRequestOptions = { + host: proxyUrl.hostname, + port: proxyUrl.port, + method: "CONNECT", + path: destinationUrl.hostname, + headers: headers + }; + if (timeout) { + tunnelRequestOptions.timeout = timeout; + } + if (agentOptions && Object.keys(agentOptions).length) { + tunnelRequestOptions.agent = new http__default.Agent(agentOptions); + } + // compose a request string for the socket + let postRequestStringContent = ""; + if (httpMethod === HttpMethod.POST) { + const body = (options == null ? void 0 : options.body) || ""; + postRequestStringContent = "Content-Type: application/x-www-form-urlencoded\r\n" + `Content-Length: ${body.length}\r\n` + `\r\n${body}`; + } + const outgoingRequestString = `${httpMethod.toUpperCase()} ${destinationUrl.href} HTTP/1.1\r\n` + `Host: ${destinationUrl.host}\r\n` + "Connection: close\r\n" + postRequestStringContent + "\r\n"; + return new Promise((resolve, reject) => { + const request = http__default.request(tunnelRequestOptions); + if (tunnelRequestOptions.timeout) { + request.on("timeout", () => { + request.destroy(); + reject(new Error("Request time out")); + }); + } + request.end(); + // establish connection to the proxy + request.on("connect", (response, socket) => { + const proxyStatusCode = (response == null ? void 0 : response.statusCode) || ProxyStatus.SERVER_ERROR; + if (proxyStatusCode < ProxyStatus.SUCCESS_RANGE_START || proxyStatusCode > ProxyStatus.SUCCESS_RANGE_END) { + request.destroy(); + socket.destroy(); + reject(new Error(`Error connecting to proxy. Http status code: ${response.statusCode}. Http status message: ${(response == null ? void 0 : response.statusMessage) || "Unknown"}`)); + } + if (tunnelRequestOptions.timeout) { + socket.setTimeout(tunnelRequestOptions.timeout); + socket.on("timeout", () => { + request.destroy(); + socket.destroy(); + reject(new Error("Request time out")); + }); + } + // make a request over an HTTP tunnel + socket.write(outgoingRequestString); + const data = []; + socket.on("data", chunk => { + data.push(chunk); + }); + socket.on("end", () => { + // combine all received buffer streams into one buffer, and then into a string + const dataString = Buffer.concat([...data]).toString(); + // separate each line into it's own entry in an arry + const dataStringArray = dataString.split("\r\n"); + // the first entry will contain the statusCode and statusMessage + const httpStatusCode = parseInt(dataStringArray[0].split(" ")[1]); + // remove "HTTP/1.1" and the status code to get the status message + const statusMessage = dataStringArray[0].split(" ").slice(2).join(" "); + // the last entry will contain the body + const body = dataStringArray[dataStringArray.length - 1]; + // everything in between the first and last entries are the headers + const headersArray = dataStringArray.slice(1, dataStringArray.length - 2); + // build an object out of all the headers + const entries = new Map(); + headersArray.forEach(header => { + /** + * the header might look like "Content-Length: 1531", but that is just a string + * it needs to be converted to a key/value pair + * split the string at the first instance of ":" + * there may be more than one ":" if the value of the header is supposed to be a JSON object + */ + const headerKeyValue = header.split(new RegExp(/:\s(.*)/s)); + const headerKey = headerKeyValue[0]; + let headerValue = headerKeyValue[1]; + // check if the value of the header is supposed to be a JSON object + try { + const object = JSON.parse(headerValue); + // if it is, then convert it from a string to a JSON object + if (object && typeof object === "object") { + headerValue = object; + } + } catch (e) { + // otherwise, leave it as a string + } + entries.set(headerKey, headerValue); + }); + const headers = Object.fromEntries(entries); + const parsedHeaders = headers; + const networkResponse = NetworkUtils.getNetworkResponse(parsedHeaders, parseBody(httpStatusCode, statusMessage, parsedHeaders, body), httpStatusCode); + if ((httpStatusCode < HttpStatus.SUCCESS_RANGE_START || httpStatusCode > HttpStatus.SUCCESS_RANGE_END) && + // do not destroy the request for the device code flow + networkResponse.body["error"] !== Constants.AUTHORIZATION_PENDING) { + request.destroy(); + } + resolve(networkResponse); + }); + socket.on("error", chunk => { + request.destroy(); + socket.destroy(); + reject(new Error(chunk.toString())); + }); + }); + request.on("error", chunk => { + request.destroy(); + reject(new Error(chunk.toString())); + }); + }); +}; +const networkRequestViaHttps = (urlString, httpMethod, options, agentOptions, timeout) => { + const isPostRequest = httpMethod === HttpMethod.POST; + const body = (options == null ? void 0 : options.body) || ""; + const url = new URL(urlString); + const headers = (options == null ? void 0 : options.headers) || {}; + const customOptions = { + method: httpMethod, + headers: headers, + ...NetworkUtils.urlToHttpOptions(url) + }; + if (timeout) { + customOptions.timeout = timeout; + } + if (agentOptions && Object.keys(agentOptions).length) { + customOptions.agent = new https.Agent(agentOptions); + } + if (isPostRequest) { + // needed for post request to work + customOptions.headers = { + ...customOptions.headers, + "Content-Length": body.length + }; + } + return new Promise((resolve, reject) => { + const request = https.request(customOptions); + if (timeout) { + request.on("timeout", () => { + request.destroy(); + reject(new Error("Request time out")); + }); + } + if (isPostRequest) { + request.write(body); + } + request.end(); + request.on("response", response => { + const headers = response.headers; + const statusCode = response.statusCode; + const statusMessage = response.statusMessage; + const data = []; + response.on("data", chunk => { + data.push(chunk); + }); + response.on("end", () => { + // combine all received buffer streams into one buffer, and then into a string + const body = Buffer.concat([...data]).toString(); + const parsedHeaders = headers; + const networkResponse = NetworkUtils.getNetworkResponse(parsedHeaders, parseBody(statusCode, statusMessage, parsedHeaders, body), statusCode); + if ((statusCode < HttpStatus.SUCCESS_RANGE_START || statusCode > HttpStatus.SUCCESS_RANGE_END) && + // do not destroy the request for the device code flow + networkResponse.body["error"] !== Constants.AUTHORIZATION_PENDING) { + request.destroy(); + } + resolve(networkResponse); + }); + }); + request.on("error", chunk => { + request.destroy(); + reject(new Error(chunk.toString())); + }); + }); +}; +/** + * Check if extra parsing is needed on the repsonse from the server + * @param statusCode {number} the status code of the response from the server + * @param statusMessage {string | undefined} the status message of the response from the server + * @param headers {Record} the headers of the response from the server + * @param body {string} the body from the response of the server + * @returns {Object} JSON parsed body or error object + */ +const parseBody = (statusCode, statusMessage, headers, body) => { + /* + * Informational responses (100 – 199) + * Successful responses (200 – 299) + * Redirection messages (300 – 399) + * Client error responses (400 – 499) + * Server error responses (500 – 599) + */ + let parsedBody; + try { + parsedBody = JSON.parse(body); + } catch (error) { + let errorType; + let errorDescriptionHelper; + if (statusCode >= HttpStatus.CLIENT_ERROR_RANGE_START && statusCode <= HttpStatus.CLIENT_ERROR_RANGE_END) { + errorType = "client_error"; + errorDescriptionHelper = "A client"; + } else if (statusCode >= HttpStatus.SERVER_ERROR_RANGE_START && statusCode <= HttpStatus.SERVER_ERROR_RANGE_END) { + errorType = "server_error"; + errorDescriptionHelper = "A server"; + } else { + errorType = "unknown_error"; + errorDescriptionHelper = "An unknown"; + } + parsedBody = { + error: errorType, + error_description: `${errorDescriptionHelper} error occured.\nHttp status code: ${statusCode}\nHttp status message: ${statusMessage || "Unknown"}\nHeaders: ${JSON.stringify(headers)}` + }; + } + return parsedBody; +}; + +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. + */ +const DEFAULT_AUTH_OPTIONS = { + clientId: msalCommon.Constants.EMPTY_STRING, + authority: msalCommon.Constants.DEFAULT_AUTHORITY, + clientSecret: msalCommon.Constants.EMPTY_STRING, + clientAssertion: msalCommon.Constants.EMPTY_STRING, + clientCertificate: { + thumbprint: msalCommon.Constants.EMPTY_STRING, + privateKey: msalCommon.Constants.EMPTY_STRING, + x5c: msalCommon.Constants.EMPTY_STRING + }, + knownAuthorities: [], + cloudDiscoveryMetadata: msalCommon.Constants.EMPTY_STRING, + authorityMetadata: msalCommon.Constants.EMPTY_STRING, + clientCapabilities: [], + protocolMode: msalCommon.ProtocolMode.AAD, + azureCloudOptions: { + azureCloudInstance: msalCommon.AzureCloudInstance.None, + tenant: msalCommon.Constants.EMPTY_STRING + }, + skipAuthorityMetadataCache: false +}; +const DEFAULT_CACHE_OPTIONS = { + claimsBasedCachingEnabled: true +}; +const DEFAULT_LOGGER_OPTIONS = { + loggerCallback: () => { + // allow users to not set logger call back + }, + piiLoggingEnabled: false, + logLevel: msalCommon.LogLevel.Info +}; +const DEFAULT_SYSTEM_OPTIONS = { + loggerOptions: DEFAULT_LOGGER_OPTIONS, + networkClient: /*#__PURE__*/new HttpClient(), + proxyUrl: msalCommon.Constants.EMPTY_STRING, + customAgentOptions: {} +}; +const DEFAULT_TELEMETRY_OPTIONS = { + application: { + appName: msalCommon.Constants.EMPTY_STRING, + appVersion: msalCommon.Constants.EMPTY_STRING + } +}; +/** + * Sets the default options when not explicitly configured from app developer + * + * @param auth - Authentication options + * @param cache - Cache options + * @param system - System options + * @param telemetry - Telemetry options + * + * @returns Configuration + * @public + */ +function buildAppConfiguration({ + auth, + broker, + cache, + system, + telemetry +}) { + const systemOptions = { + ...DEFAULT_SYSTEM_OPTIONS, + networkClient: new HttpClient(system == null ? void 0 : system.proxyUrl, system == null ? void 0 : system.customAgentOptions), + loggerOptions: (system == null ? void 0 : system.loggerOptions) || DEFAULT_LOGGER_OPTIONS + }; + return { + auth: { + ...DEFAULT_AUTH_OPTIONS, + ...auth + }, + broker: { + ...broker + }, + cache: { + ...DEFAULT_CACHE_OPTIONS, + ...cache + }, + system: { + ...systemOptions, + ...system + }, + telemetry: { + ...DEFAULT_TELEMETRY_OPTIONS, + ...telemetry + } + }; +} + +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. + */ +class GuidGenerator { + /** + * + * RFC4122: The version 4 UUID is meant for generating UUIDs from truly-random or pseudo-random numbers. + * uuidv4 generates guids from cryprtographically-string random + */ + generateGuid() { + return uuid.v4(); + } + /** + * verifies if a string is GUID + * @param guid + */ + isGuid(guid) { + const regexGuid = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i; + return regexGuid.test(guid); + } +} + +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. + */ +class EncodingUtils { + /** + * 'utf8': Multibyte encoded Unicode characters. Many web pages and other document formats use UTF-8. + * 'base64': Base64 encoding. + * + * @param str text + */ + static base64Encode(str, encoding) { + return Buffer.from(str, encoding).toString("base64"); + } + /** + * encode a URL + * @param str + */ + static base64EncodeUrl(str, encoding) { + return EncodingUtils.base64Encode(str, encoding).replace(/=/g, msalCommon.Constants.EMPTY_STRING).replace(/\+/g, "-").replace(/\//g, "_"); + } + /** + * 'utf8': Multibyte encoded Unicode characters. Many web pages and other document formats use UTF-8. + * 'base64': Base64 encoding. + * + * @param base64Str Base64 encoded text + */ + static base64Decode(base64Str) { + return Buffer.from(base64Str, "base64").toString("utf8"); + } + /** + * @param base64Str Base64 encoded Url + */ + static base64DecodeUrl(base64Str) { + let str = base64Str.replace(/-/g, "+").replace(/_/g, "/"); + while (str.length % 4) { + str += "="; + } + return EncodingUtils.base64Decode(str); + } +} + +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. + */ +class HashUtils { + /** + * generate 'SHA256' hash + * @param buffer + */ + sha256(buffer) { + return crypto.createHash(Hash.SHA256).update(buffer).digest(); + } +} + +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. + */ +/** + * https://tools.ietf.org/html/rfc7636#page-8 + */ +class PkceGenerator { + constructor() { + this.hashUtils = new HashUtils(); + } + /** + * generates the codeVerfier and the challenge from the codeVerfier + * reference: https://tools.ietf.org/html/rfc7636#section-4.1 and https://tools.ietf.org/html/rfc7636#section-4.2 + */ + async generatePkceCodes() { + const verifier = this.generateCodeVerifier(); + const challenge = this.generateCodeChallengeFromVerifier(verifier); + return { + verifier, + challenge + }; + } + /** + * generates the codeVerfier; reference: https://tools.ietf.org/html/rfc7636#section-4.1 + */ + generateCodeVerifier() { + const charArr = []; + const maxNumber = 256 - 256 % CharSet.CV_CHARSET.length; + while (charArr.length <= RANDOM_OCTET_SIZE) { + const byte = crypto.randomBytes(1)[0]; + if (byte >= maxNumber) { + /* + * Ignore this number to maintain randomness. + * Including it would result in an unequal distribution of characters after doing the modulo + */ + continue; + } + const index = byte % CharSet.CV_CHARSET.length; + charArr.push(CharSet.CV_CHARSET[index]); + } + const verifier = charArr.join(msalCommon.Constants.EMPTY_STRING); + return EncodingUtils.base64EncodeUrl(verifier); + } + /** + * generate the challenge from the codeVerfier; reference: https://tools.ietf.org/html/rfc7636#section-4.2 + * @param codeVerifier + */ + generateCodeChallengeFromVerifier(codeVerifier) { + return EncodingUtils.base64EncodeUrl(this.hashUtils.sha256(codeVerifier).toString("base64"), "base64"); + } +} + +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. + */ +/** + * This class implements MSAL node's crypto interface, which allows it to perform base64 encoding and decoding, generating cryptographically random GUIDs and + * implementing Proof Key for Code Exchange specs for the OAuth Authorization Code Flow using PKCE (rfc here: https://tools.ietf.org/html/rfc7636). + * @public + */ +class CryptoProvider { + constructor() { + // Browser crypto needs to be validated first before any other classes can be set. + this.pkceGenerator = new PkceGenerator(); + this.guidGenerator = new GuidGenerator(); + this.hashUtils = new HashUtils(); + } + /** + * Creates a new random GUID - used to populate state and nonce. + * @returns string (GUID) + */ + createNewGuid() { + return this.guidGenerator.generateGuid(); + } + /** + * Encodes input string to base64. + * @param input - string to be encoded + */ + base64Encode(input) { + return EncodingUtils.base64Encode(input); + } + /** + * Decodes input string from base64. + * @param input - string to be decoded + */ + base64Decode(input) { + return EncodingUtils.base64Decode(input); + } + /** + * Generates PKCE codes used in Authorization Code Flow. + */ + generatePkceCodes() { + return this.pkceGenerator.generatePkceCodes(); + } + /** + * Generates a keypair, stores it and returns a thumbprint - not yet implemented for node + */ + getPublicKeyThumbprint() { + throw new Error("Method not implemented."); + } + /** + * Removes cryptographic keypair from key store matching the keyId passed in + * @param kid + */ + removeTokenBindingKey() { + throw new Error("Method not implemented."); + } + /** + * Removes all cryptographic keys from Keystore + */ + clearKeystore() { + throw new Error("Method not implemented."); + } + /** + * Signs the given object as a jwt payload with private key retrieved by given kid - currently not implemented for node + */ + signJwt() { + throw new Error("Method not implemented."); + } + /** + * Returns the SHA-256 hash of an input string + */ + async hashString(plainText) { + return EncodingUtils.base64EncodeUrl(this.hashUtils.sha256(plainText).toString("base64"), "base64"); + } +} + +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. + */ +/** + * This class deserializes cache entities read from the file into in memory object types defined internally + */ +class Deserializer { + /** + * Parse the JSON blob in memory and deserialize the content + * @param cachedJson + */ + static deserializeJSONBlob(jsonFile) { + const deserializedCache = msalCommon.StringUtils.isEmpty(jsonFile) ? {} : JSON.parse(jsonFile); + return deserializedCache; + } + /** + * Deserializes accounts to AccountEntity objects + * @param accounts + */ + static deserializeAccounts(accounts) { + const accountObjects = {}; + if (accounts) { + Object.keys(accounts).map(function (key) { + const serializedAcc = accounts[key]; + const mappedAcc = { + homeAccountId: serializedAcc.home_account_id, + environment: serializedAcc.environment, + realm: serializedAcc.realm, + localAccountId: serializedAcc.local_account_id, + username: serializedAcc.username, + authorityType: serializedAcc.authority_type, + name: serializedAcc.name, + clientInfo: serializedAcc.client_info, + lastModificationTime: serializedAcc.last_modification_time, + lastModificationApp: serializedAcc.last_modification_app + }; + const account = new msalCommon.AccountEntity(); + msalCommon.CacheManager.toObject(account, mappedAcc); + accountObjects[key] = account; + }); + } + return accountObjects; + } + /** + * Deserializes id tokens to IdTokenEntity objects + * @param idTokens + */ + static deserializeIdTokens(idTokens) { + const idObjects = {}; + if (idTokens) { + Object.keys(idTokens).map(function (key) { + const serializedIdT = idTokens[key]; + const mappedIdT = { + homeAccountId: serializedIdT.home_account_id, + environment: serializedIdT.environment, + credentialType: serializedIdT.credential_type, + clientId: serializedIdT.client_id, + secret: serializedIdT.secret, + realm: serializedIdT.realm + }; + const idToken = new msalCommon.IdTokenEntity(); + msalCommon.CacheManager.toObject(idToken, mappedIdT); + idObjects[key] = idToken; + }); + } + return idObjects; + } + /** + * Deserializes access tokens to AccessTokenEntity objects + * @param accessTokens + */ + static deserializeAccessTokens(accessTokens) { + const atObjects = {}; + if (accessTokens) { + Object.keys(accessTokens).map(function (key) { + const serializedAT = accessTokens[key]; + const mappedAT = { + homeAccountId: serializedAT.home_account_id, + environment: serializedAT.environment, + credentialType: serializedAT.credential_type, + clientId: serializedAT.client_id, + secret: serializedAT.secret, + realm: serializedAT.realm, + target: serializedAT.target, + cachedAt: serializedAT.cached_at, + expiresOn: serializedAT.expires_on, + extendedExpiresOn: serializedAT.extended_expires_on, + refreshOn: serializedAT.refresh_on, + keyId: serializedAT.key_id, + tokenType: serializedAT.token_type, + requestedClaims: serializedAT.requestedClaims, + requestedClaimsHash: serializedAT.requestedClaimsHash, + userAssertionHash: serializedAT.userAssertionHash + }; + const accessToken = new msalCommon.AccessTokenEntity(); + msalCommon.CacheManager.toObject(accessToken, mappedAT); + atObjects[key] = accessToken; + }); + } + return atObjects; + } + /** + * Deserializes refresh tokens to RefreshTokenEntity objects + * @param refreshTokens + */ + static deserializeRefreshTokens(refreshTokens) { + const rtObjects = {}; + if (refreshTokens) { + Object.keys(refreshTokens).map(function (key) { + const serializedRT = refreshTokens[key]; + const mappedRT = { + homeAccountId: serializedRT.home_account_id, + environment: serializedRT.environment, + credentialType: serializedRT.credential_type, + clientId: serializedRT.client_id, + secret: serializedRT.secret, + familyId: serializedRT.family_id, + target: serializedRT.target, + realm: serializedRT.realm + }; + const refreshToken = new msalCommon.RefreshTokenEntity(); + msalCommon.CacheManager.toObject(refreshToken, mappedRT); + rtObjects[key] = refreshToken; + }); + } + return rtObjects; + } + /** + * Deserializes appMetadata to AppMetaData objects + * @param appMetadata + */ + static deserializeAppMetadata(appMetadata) { + const appMetadataObjects = {}; + if (appMetadata) { + Object.keys(appMetadata).map(function (key) { + const serializedAmdt = appMetadata[key]; + const mappedAmd = { + clientId: serializedAmdt.client_id, + environment: serializedAmdt.environment, + familyId: serializedAmdt.family_id + }; + const amd = new msalCommon.AppMetadataEntity(); + msalCommon.CacheManager.toObject(amd, mappedAmd); + appMetadataObjects[key] = amd; + }); + } + return appMetadataObjects; + } + /** + * Deserialize an inMemory Cache + * @param jsonCache + */ + static deserializeAllCache(jsonCache) { + return { + accounts: jsonCache.Account ? this.deserializeAccounts(jsonCache.Account) : {}, + idTokens: jsonCache.IdToken ? this.deserializeIdTokens(jsonCache.IdToken) : {}, + accessTokens: jsonCache.AccessToken ? this.deserializeAccessTokens(jsonCache.AccessToken) : {}, + refreshTokens: jsonCache.RefreshToken ? this.deserializeRefreshTokens(jsonCache.RefreshToken) : {}, + appMetadata: jsonCache.AppMetadata ? this.deserializeAppMetadata(jsonCache.AppMetadata) : {} + }; + } +} + +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. + */ +class Serializer { + /** + * serialize the JSON blob + * @param data + */ + static serializeJSONBlob(data) { + return JSON.stringify(data); + } + /** + * Serialize Accounts + * @param accCache + */ + static serializeAccounts(accCache) { + const accounts = {}; + Object.keys(accCache).map(function (key) { + const accountEntity = accCache[key]; + accounts[key] = { + home_account_id: accountEntity.homeAccountId, + environment: accountEntity.environment, + realm: accountEntity.realm, + local_account_id: accountEntity.localAccountId, + username: accountEntity.username, + authority_type: accountEntity.authorityType, + name: accountEntity.name, + client_info: accountEntity.clientInfo, + last_modification_time: accountEntity.lastModificationTime, + last_modification_app: accountEntity.lastModificationApp + }; + }); + return accounts; + } + /** + * Serialize IdTokens + * @param idTCache + */ + static serializeIdTokens(idTCache) { + const idTokens = {}; + Object.keys(idTCache).map(function (key) { + const idTEntity = idTCache[key]; + idTokens[key] = { + home_account_id: idTEntity.homeAccountId, + environment: idTEntity.environment, + credential_type: idTEntity.credentialType, + client_id: idTEntity.clientId, + secret: idTEntity.secret, + realm: idTEntity.realm + }; + }); + return idTokens; + } + /** + * Serializes AccessTokens + * @param atCache + */ + static serializeAccessTokens(atCache) { + const accessTokens = {}; + Object.keys(atCache).map(function (key) { + const atEntity = atCache[key]; + accessTokens[key] = { + home_account_id: atEntity.homeAccountId, + environment: atEntity.environment, + credential_type: atEntity.credentialType, + client_id: atEntity.clientId, + secret: atEntity.secret, + realm: atEntity.realm, + target: atEntity.target, + cached_at: atEntity.cachedAt, + expires_on: atEntity.expiresOn, + extended_expires_on: atEntity.extendedExpiresOn, + refresh_on: atEntity.refreshOn, + key_id: atEntity.keyId, + token_type: atEntity.tokenType, + requestedClaims: atEntity.requestedClaims, + requestedClaimsHash: atEntity.requestedClaimsHash, + userAssertionHash: atEntity.userAssertionHash + }; + }); + return accessTokens; + } + /** + * Serialize refreshTokens + * @param rtCache + */ + static serializeRefreshTokens(rtCache) { + const refreshTokens = {}; + Object.keys(rtCache).map(function (key) { + const rtEntity = rtCache[key]; + refreshTokens[key] = { + home_account_id: rtEntity.homeAccountId, + environment: rtEntity.environment, + credential_type: rtEntity.credentialType, + client_id: rtEntity.clientId, + secret: rtEntity.secret, + family_id: rtEntity.familyId, + target: rtEntity.target, + realm: rtEntity.realm + }; + }); + return refreshTokens; + } + /** + * Serialize amdtCache + * @param amdtCache + */ + static serializeAppMetadata(amdtCache) { + const appMetadata = {}; + Object.keys(amdtCache).map(function (key) { + const amdtEntity = amdtCache[key]; + appMetadata[key] = { + client_id: amdtEntity.clientId, + environment: amdtEntity.environment, + family_id: amdtEntity.familyId + }; + }); + return appMetadata; + } + /** + * Serialize the cache + * @param jsonContent + */ + static serializeAllCache(inMemCache) { + return { + Account: this.serializeAccounts(inMemCache.accounts), + IdToken: this.serializeIdTokens(inMemCache.idTokens), + AccessToken: this.serializeAccessTokens(inMemCache.accessTokens), + RefreshToken: this.serializeRefreshTokens(inMemCache.refreshTokens), + AppMetadata: this.serializeAppMetadata(inMemCache.appMetadata) + }; + } +} + +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. + */ +/** + * This class implements Storage for node, reading cache from user specified storage location or an extension library + * @public + */ +class NodeStorage extends msalCommon.CacheManager { + constructor(logger, clientId, cryptoImpl) { + super(clientId, cryptoImpl, logger); + this.cache = {}; + this.changeEmitters = []; + this.logger = logger; + } + /** + * Queue up callbacks + * @param func - a callback function for cache change indication + */ + registerChangeEmitter(func) { + this.changeEmitters.push(func); + } + /** + * Invoke the callback when cache changes + */ + emitChange() { + this.changeEmitters.forEach(func => func.call(null)); + } + /** + * Converts cacheKVStore to InMemoryCache + * @param cache - key value store + */ + cacheToInMemoryCache(cache) { + const inMemoryCache = { + accounts: {}, + idTokens: {}, + accessTokens: {}, + refreshTokens: {}, + appMetadata: {} + }; + for (const key in cache) { + if (cache[key] instanceof msalCommon.AccountEntity) { + inMemoryCache.accounts[key] = cache[key]; + } else if (cache[key] instanceof msalCommon.IdTokenEntity) { + inMemoryCache.idTokens[key] = cache[key]; + } else if (cache[key] instanceof msalCommon.AccessTokenEntity) { + inMemoryCache.accessTokens[key] = cache[key]; + } else if (cache[key] instanceof msalCommon.RefreshTokenEntity) { + inMemoryCache.refreshTokens[key] = cache[key]; + } else if (cache[key] instanceof msalCommon.AppMetadataEntity) { + inMemoryCache.appMetadata[key] = cache[key]; + } else { + continue; + } + } + return inMemoryCache; + } + /** + * converts inMemoryCache to CacheKVStore + * @param inMemoryCache - kvstore map for inmemory + */ + inMemoryCacheToCache(inMemoryCache) { + // convert in memory cache to a flat Key-Value map + let cache = this.getCache(); + cache = { + ...cache, + ...inMemoryCache.accounts, + ...inMemoryCache.idTokens, + ...inMemoryCache.accessTokens, + ...inMemoryCache.refreshTokens, + ...inMemoryCache.appMetadata + }; + // convert in memory cache to a flat Key-Value map + return cache; + } + /** + * gets the current in memory cache for the client + */ + getInMemoryCache() { + this.logger.trace("Getting in-memory cache"); + // convert the cache key value store to inMemoryCache + const inMemoryCache = this.cacheToInMemoryCache(this.getCache()); + return inMemoryCache; + } + /** + * sets the current in memory cache for the client + * @param inMemoryCache - key value map in memory + */ + setInMemoryCache(inMemoryCache) { + this.logger.trace("Setting in-memory cache"); + // convert and append the inMemoryCache to cacheKVStore + const cache = this.inMemoryCacheToCache(inMemoryCache); + this.setCache(cache); + this.emitChange(); + } + /** + * get the current cache key-value store + */ + getCache() { + this.logger.trace("Getting cache key-value store"); + return this.cache; + } + /** + * sets the current cache (key value store) + * @param cacheMap - key value map + */ + setCache(cache) { + this.logger.trace("Setting cache key value store"); + this.cache = cache; + // mark change in cache + this.emitChange(); + } + /** + * Gets cache item with given key. + * @param key - lookup key for the cache entry + */ + getItem(key) { + this.logger.tracePii(`Item key: ${key}`); + // read cache + const cache = this.getCache(); + return cache[key]; + } + /** + * Gets cache item with given key-value + * @param key - lookup key for the cache entry + * @param value - value of the cache entry + */ + setItem(key, value) { + this.logger.tracePii(`Item key: ${key}`); + // read cache + const cache = this.getCache(); + cache[key] = value; + // write to cache + this.setCache(cache); + } + getAccountKeys() { + const inMemoryCache = this.getInMemoryCache(); + const accountKeys = Object.keys(inMemoryCache.accounts); + return accountKeys; + } + getTokenKeys() { + const inMemoryCache = this.getInMemoryCache(); + const tokenKeys = { + idToken: Object.keys(inMemoryCache.idTokens), + accessToken: Object.keys(inMemoryCache.accessTokens), + refreshToken: Object.keys(inMemoryCache.refreshTokens) + }; + return tokenKeys; + } + /** + * fetch the account entity + * @param accountKey - lookup key to fetch cache type AccountEntity + */ + getAccount(accountKey) { + const account = this.getItem(accountKey); + if (msalCommon.AccountEntity.isAccountEntity(account)) { + return account; + } + return null; + } + /** + * set account entity + * @param account - cache value to be set of type AccountEntity + */ + setAccount(account) { + const accountKey = account.generateAccountKey(); + this.setItem(accountKey, account); + } + /** + * fetch the idToken credential + * @param idTokenKey - lookup key to fetch cache type IdTokenEntity + */ + getIdTokenCredential(idTokenKey) { + const idToken = this.getItem(idTokenKey); + if (msalCommon.IdTokenEntity.isIdTokenEntity(idToken)) { + return idToken; + } + return null; + } + /** + * set idToken credential + * @param idToken - cache value to be set of type IdTokenEntity + */ + setIdTokenCredential(idToken) { + const idTokenKey = idToken.generateCredentialKey(); + this.setItem(idTokenKey, idToken); + } + /** + * fetch the accessToken credential + * @param accessTokenKey - lookup key to fetch cache type AccessTokenEntity + */ + getAccessTokenCredential(accessTokenKey) { + const accessToken = this.getItem(accessTokenKey); + if (msalCommon.AccessTokenEntity.isAccessTokenEntity(accessToken)) { + return accessToken; + } + return null; + } + /** + * set accessToken credential + * @param accessToken - cache value to be set of type AccessTokenEntity + */ + setAccessTokenCredential(accessToken) { + const accessTokenKey = accessToken.generateCredentialKey(); + this.setItem(accessTokenKey, accessToken); + } + /** + * fetch the refreshToken credential + * @param refreshTokenKey - lookup key to fetch cache type RefreshTokenEntity + */ + getRefreshTokenCredential(refreshTokenKey) { + const refreshToken = this.getItem(refreshTokenKey); + if (msalCommon.RefreshTokenEntity.isRefreshTokenEntity(refreshToken)) { + return refreshToken; + } + return null; + } + /** + * set refreshToken credential + * @param refreshToken - cache value to be set of type RefreshTokenEntity + */ + setRefreshTokenCredential(refreshToken) { + const refreshTokenKey = refreshToken.generateCredentialKey(); + this.setItem(refreshTokenKey, refreshToken); + } + /** + * fetch appMetadata entity from the platform cache + * @param appMetadataKey - lookup key to fetch cache type AppMetadataEntity + */ + getAppMetadata(appMetadataKey) { + const appMetadata = this.getItem(appMetadataKey); + if (msalCommon.AppMetadataEntity.isAppMetadataEntity(appMetadataKey, appMetadata)) { + return appMetadata; + } + return null; + } + /** + * set appMetadata entity to the platform cache + * @param appMetadata - cache value to be set of type AppMetadataEntity + */ + setAppMetadata(appMetadata) { + const appMetadataKey = appMetadata.generateAppMetadataKey(); + this.setItem(appMetadataKey, appMetadata); + } + /** + * fetch server telemetry entity from the platform cache + * @param serverTelemetrykey - lookup key to fetch cache type ServerTelemetryEntity + */ + getServerTelemetry(serverTelemetrykey) { + const serverTelemetryEntity = this.getItem(serverTelemetrykey); + if (serverTelemetryEntity && msalCommon.ServerTelemetryEntity.isServerTelemetryEntity(serverTelemetrykey, serverTelemetryEntity)) { + return serverTelemetryEntity; + } + return null; + } + /** + * set server telemetry entity to the platform cache + * @param serverTelemetryKey - lookup key to fetch cache type ServerTelemetryEntity + * @param serverTelemetry - cache value to be set of type ServerTelemetryEntity + */ + setServerTelemetry(serverTelemetryKey, serverTelemetry) { + this.setItem(serverTelemetryKey, serverTelemetry); + } + /** + * fetch authority metadata entity from the platform cache + * @param key - lookup key to fetch cache type AuthorityMetadataEntity + */ + getAuthorityMetadata(key) { + const authorityMetadataEntity = this.getItem(key); + if (authorityMetadataEntity && msalCommon.AuthorityMetadataEntity.isAuthorityMetadataEntity(key, authorityMetadataEntity)) { + return authorityMetadataEntity; + } + return null; + } + /** + * Get all authority metadata keys + */ + getAuthorityMetadataKeys() { + return this.getKeys().filter(key => { + return this.isAuthorityMetadata(key); + }); + } + /** + * set authority metadata entity to the platform cache + * @param key - lookup key to fetch cache type AuthorityMetadataEntity + * @param metadata - cache value to be set of type AuthorityMetadataEntity + */ + setAuthorityMetadata(key, metadata) { + this.setItem(key, metadata); + } + /** + * fetch throttling entity from the platform cache + * @param throttlingCacheKey - lookup key to fetch cache type ThrottlingEntity + */ + getThrottlingCache(throttlingCacheKey) { + const throttlingCache = this.getItem(throttlingCacheKey); + if (throttlingCache && msalCommon.ThrottlingEntity.isThrottlingEntity(throttlingCacheKey, throttlingCache)) { + return throttlingCache; + } + return null; + } + /** + * set throttling entity to the platform cache + * @param throttlingCacheKey - lookup key to fetch cache type ThrottlingEntity + * @param throttlingCache - cache value to be set of type ThrottlingEntity + */ + setThrottlingCache(throttlingCacheKey, throttlingCache) { + this.setItem(throttlingCacheKey, throttlingCache); + } + /** + * Removes the cache item from memory with the given key. + * @param key - lookup key to remove a cache entity + * @param inMemory - key value map of the cache + */ + removeItem(key) { + this.logger.tracePii(`Item key: ${key}`); + // read inMemoryCache + let result = false; + const cache = this.getCache(); + if (!!cache[key]) { + delete cache[key]; + result = true; + } + // write to the cache after removal + if (result) { + this.setCache(cache); + this.emitChange(); + } + return result; + } + /** + * Checks whether key is in cache. + * @param key - look up key for a cache entity + */ + containsKey(key) { + return this.getKeys().includes(key); + } + /** + * Gets all keys in window. + */ + getKeys() { + this.logger.trace("Retrieving all cache keys"); + // read cache + const cache = this.getCache(); + return [...Object.keys(cache)]; + } + /** + * Clears all cache entries created by MSAL (except tokens). + */ + async clear() { + this.logger.trace("Clearing cache entries created by MSAL"); + // read inMemoryCache + const cacheKeys = this.getKeys(); + // delete each element + cacheKeys.forEach(key => { + this.removeItem(key); + }); + this.emitChange(); + } + /** + * Initialize in memory cache from an exisiting cache vault + * @param cache - blob formatted cache (JSON) + */ + static generateInMemoryCache(cache) { + return Deserializer.deserializeAllCache(Deserializer.deserializeJSONBlob(cache)); + } + /** + * retrieves the final JSON + * @param inMemoryCache - itemised cache read from the JSON + */ + static generateJsonCache(inMemoryCache) { + return Serializer.serializeAllCache(inMemoryCache); + } + /** + * Updates a credential's cache key if the current cache key is outdated + */ + updateCredentialCacheKey(currentCacheKey, credential) { + const updatedCacheKey = credential.generateCredentialKey(); + if (currentCacheKey !== updatedCacheKey) { + const cacheItem = this.getItem(currentCacheKey); + if (cacheItem) { + this.removeItem(currentCacheKey); + this.setItem(updatedCacheKey, cacheItem); + this.logger.verbose(`Updated an outdated ${credential.credentialType} cache key`); + return updatedCacheKey; + } else { + this.logger.error(`Attempted to update an outdated ${credential.credentialType} cache key but no item matching the outdated key was found in storage`); + } + } + return currentCacheKey; + } +} + +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. + */ +const defaultSerializedCache = { + Account: {}, + IdToken: {}, + AccessToken: {}, + RefreshToken: {}, + AppMetadata: {} +}; +/** + * In-memory token cache manager + * @public + */ +class TokenCache { + constructor(storage, logger, cachePlugin) { + this.cacheHasChanged = false; + this.storage = storage; + this.storage.registerChangeEmitter(this.handleChangeEvent.bind(this)); + if (cachePlugin) { + this.persistence = cachePlugin; + } + this.logger = logger; + } + /** + * Set to true if cache state has changed since last time serialize or writeToPersistence was called + */ + hasChanged() { + return this.cacheHasChanged; + } + /** + * Serializes in memory cache to JSON + */ + serialize() { + this.logger.trace("Serializing in-memory cache"); + let finalState = Serializer.serializeAllCache(this.storage.getInMemoryCache()); + // if cacheSnapshot not null or empty, merge + if (!msalCommon.StringUtils.isEmpty(this.cacheSnapshot)) { + this.logger.trace("Reading cache snapshot from disk"); + finalState = this.mergeState(JSON.parse(this.cacheSnapshot), finalState); + } else { + this.logger.trace("No cache snapshot to merge"); + } + this.cacheHasChanged = false; + return JSON.stringify(finalState); + } + /** + * Deserializes JSON to in-memory cache. JSON should be in MSAL cache schema format + * @param cache - blob formatted cache + */ + deserialize(cache) { + this.logger.trace("Deserializing JSON to in-memory cache"); + this.cacheSnapshot = cache; + if (!msalCommon.StringUtils.isEmpty(this.cacheSnapshot)) { + this.logger.trace("Reading cache snapshot from disk"); + const deserializedCache = Deserializer.deserializeAllCache(this.overlayDefaults(JSON.parse(this.cacheSnapshot))); + this.storage.setInMemoryCache(deserializedCache); + } else { + this.logger.trace("No cache snapshot to deserialize"); + } + } + /** + * Fetches the cache key-value map + */ + getKVStore() { + return this.storage.getCache(); + } + /** + * API that retrieves all accounts currently in cache to the user + */ + async getAllAccounts() { + this.logger.trace("getAllAccounts called"); + let cacheContext; + try { + if (this.persistence) { + cacheContext = new msalCommon.TokenCacheContext(this, false); + await this.persistence.beforeCacheAccess(cacheContext); + } + return this.storage.getAllAccounts(); + } finally { + if (this.persistence && cacheContext) { + await this.persistence.afterCacheAccess(cacheContext); + } + } + } + /** + * Returns the signed in account matching homeAccountId. + * (the account object is created at the time of successful login) + * or null when no matching account is found + * @param homeAccountId - unique identifier for an account (uid.utid) + */ + async getAccountByHomeId(homeAccountId) { + const allAccounts = await this.getAllAccounts(); + if (!msalCommon.StringUtils.isEmpty(homeAccountId) && allAccounts && allAccounts.length) { + return allAccounts.filter(accountObj => accountObj.homeAccountId === homeAccountId)[0] || null; + } else { + return null; + } + } + /** + * Returns the signed in account matching localAccountId. + * (the account object is created at the time of successful login) + * or null when no matching account is found + * @param localAccountId - unique identifier of an account (sub/obj when homeAccountId cannot be populated) + */ + async getAccountByLocalId(localAccountId) { + const allAccounts = await this.getAllAccounts(); + if (!msalCommon.StringUtils.isEmpty(localAccountId) && allAccounts && allAccounts.length) { + return allAccounts.filter(accountObj => accountObj.localAccountId === localAccountId)[0] || null; + } else { + return null; + } + } + /** + * API to remove a specific account and the relevant data from cache + * @param account - AccountInfo passed by the user + */ + async removeAccount(account) { + this.logger.trace("removeAccount called"); + let cacheContext; + try { + if (this.persistence) { + cacheContext = new msalCommon.TokenCacheContext(this, true); + await this.persistence.beforeCacheAccess(cacheContext); + } + await this.storage.removeAccount(msalCommon.AccountEntity.generateAccountCacheKey(account)); + } finally { + if (this.persistence && cacheContext) { + await this.persistence.afterCacheAccess(cacheContext); + } + } + } + /** + * Called when the cache has changed state. + */ + handleChangeEvent() { + this.cacheHasChanged = true; + } + /** + * Merge in memory cache with the cache snapshot. + * @param oldState - cache before changes + * @param currentState - current cache state in the library + */ + mergeState(oldState, currentState) { + this.logger.trace("Merging in-memory cache with cache snapshot"); + const stateAfterRemoval = this.mergeRemovals(oldState, currentState); + return this.mergeUpdates(stateAfterRemoval, currentState); + } + /** + * Deep update of oldState based on newState values + * @param oldState - cache before changes + * @param newState - updated cache + */ + mergeUpdates(oldState, newState) { + Object.keys(newState).forEach(newKey => { + const newValue = newState[newKey]; + // if oldState does not contain value but newValue does, add it + if (!oldState.hasOwnProperty(newKey)) { + if (newValue !== null) { + oldState[newKey] = newValue; + } + } else { + // both oldState and newState contain the key, do deep update + const newValueNotNull = newValue !== null; + const newValueIsObject = typeof newValue === "object"; + const newValueIsNotArray = !Array.isArray(newValue); + const oldStateNotUndefinedOrNull = typeof oldState[newKey] !== "undefined" && oldState[newKey] !== null; + if (newValueNotNull && newValueIsObject && newValueIsNotArray && oldStateNotUndefinedOrNull) { + this.mergeUpdates(oldState[newKey], newValue); + } else { + oldState[newKey] = newValue; + } + } + }); + return oldState; + } + /** + * Removes entities in oldState that the were removed from newState. If there are any unknown values in root of + * oldState that are not recognized, they are left untouched. + * @param oldState - cache before changes + * @param newState - updated cache + */ + mergeRemovals(oldState, newState) { + this.logger.trace("Remove updated entries in cache"); + const accounts = oldState.Account ? this.mergeRemovalsDict(oldState.Account, newState.Account) : oldState.Account; + const accessTokens = oldState.AccessToken ? this.mergeRemovalsDict(oldState.AccessToken, newState.AccessToken) : oldState.AccessToken; + const refreshTokens = oldState.RefreshToken ? this.mergeRemovalsDict(oldState.RefreshToken, newState.RefreshToken) : oldState.RefreshToken; + const idTokens = oldState.IdToken ? this.mergeRemovalsDict(oldState.IdToken, newState.IdToken) : oldState.IdToken; + const appMetadata = oldState.AppMetadata ? this.mergeRemovalsDict(oldState.AppMetadata, newState.AppMetadata) : oldState.AppMetadata; + return { + ...oldState, + Account: accounts, + AccessToken: accessTokens, + RefreshToken: refreshTokens, + IdToken: idTokens, + AppMetadata: appMetadata + }; + } + /** + * Helper to merge new cache with the old one + * @param oldState - cache before changes + * @param newState - updated cache + */ + mergeRemovalsDict(oldState, newState) { + const finalState = { + ...oldState + }; + Object.keys(oldState).forEach(oldKey => { + if (!newState || !newState.hasOwnProperty(oldKey)) { + delete finalState[oldKey]; + } + }); + return finalState; + } + /** + * Helper to overlay as a part of cache merge + * @param passedInCache - cache read from the blob + */ + overlayDefaults(passedInCache) { + this.logger.trace("Overlaying input cache with the default cache"); + return { + Account: { + ...defaultSerializedCache.Account, + ...passedInCache.Account + }, + IdToken: { + ...defaultSerializedCache.IdToken, + ...passedInCache.IdToken + }, + AccessToken: { + ...defaultSerializedCache.AccessToken, + ...passedInCache.AccessToken + }, + RefreshToken: { + ...defaultSerializedCache.RefreshToken, + ...passedInCache.RefreshToken + }, + AppMetadata: { + ...defaultSerializedCache.AppMetadata, + ...passedInCache.AppMetadata + } + }; + } +} + +/* eslint-disable header/header */ +const name = "@azure/msal-node"; +const version = "1.18.1"; + +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. + */ +/** + * NodeAuthErrorMessage class containing string constants used by error codes and messages. + */ +const NodeAuthErrorMessage = { + invalidLoopbackAddressType: { + code: "invalid_loopback_server_address_type", + desc: "Loopback server address is not type string. This is unexpected." + }, + unableToLoadRedirectUri: { + code: "unable_to_load_redirectUrl", + desc: "Loopback server callback was invoked without a url. This is unexpected." + }, + noAuthCodeInResponse: { + code: "no_auth_code_in_response", + desc: "No auth code found in the server response. Please check your network trace to determine what happened." + }, + noLoopbackServerExists: { + code: "no_loopback_server_exists", + desc: "No loopback server exists yet." + }, + loopbackServerAlreadyExists: { + code: "loopback_server_already_exists", + desc: "Loopback server already exists. Cannot create another." + }, + loopbackServerTimeout: { + code: "loopback_server_timeout", + desc: "Timed out waiting for auth code listener to be registered." + }, + stateNotFoundError: { + code: "state_not_found", + desc: "State not found. Please verify that the request originated from msal." + } +}; +class NodeAuthError extends msalCommon.AuthError { + constructor(errorCode, errorMessage) { + super(errorCode, errorMessage); + this.name = "NodeAuthError"; + } + /** + * Creates an error thrown if loopback server address is of type string. + */ + static createInvalidLoopbackAddressTypeError() { + return new NodeAuthError(NodeAuthErrorMessage.invalidLoopbackAddressType.code, `${NodeAuthErrorMessage.invalidLoopbackAddressType.desc}`); + } + /** + * Creates an error thrown if the loopback server is unable to get a url. + */ + static createUnableToLoadRedirectUrlError() { + return new NodeAuthError(NodeAuthErrorMessage.unableToLoadRedirectUri.code, `${NodeAuthErrorMessage.unableToLoadRedirectUri.desc}`); + } + /** + * Creates an error thrown if the server response does not contain an auth code. + */ + static createNoAuthCodeInResponseError() { + return new NodeAuthError(NodeAuthErrorMessage.noAuthCodeInResponse.code, `${NodeAuthErrorMessage.noAuthCodeInResponse.desc}`); + } + /** + * Creates an error thrown if the loopback server has not been spun up yet. + */ + static createNoLoopbackServerExistsError() { + return new NodeAuthError(NodeAuthErrorMessage.noLoopbackServerExists.code, `${NodeAuthErrorMessage.noLoopbackServerExists.desc}`); + } + /** + * Creates an error thrown if a loopback server already exists when attempting to create another one. + */ + static createLoopbackServerAlreadyExistsError() { + return new NodeAuthError(NodeAuthErrorMessage.loopbackServerAlreadyExists.code, `${NodeAuthErrorMessage.loopbackServerAlreadyExists.desc}`); + } + /** + * Creates an error thrown if the loopback server times out registering the auth code listener. + */ + static createLoopbackServerTimeoutError() { + return new NodeAuthError(NodeAuthErrorMessage.loopbackServerTimeout.code, `${NodeAuthErrorMessage.loopbackServerTimeout.desc}`); + } + /** + * Creates an error thrown when the state is not present. + */ + static createStateNotFoundError() { + return new NodeAuthError(NodeAuthErrorMessage.stateNotFoundError.code, NodeAuthErrorMessage.stateNotFoundError.desc); + } +} + +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. + */ +/** + * Base abstract class for all ClientApplications - public and confidential + * @public + */ +class ClientApplication { + /** + * Constructor for the ClientApplication + */ + constructor(configuration) { + this.config = buildAppConfiguration(configuration); + this.cryptoProvider = new CryptoProvider(); + this.logger = new msalCommon.Logger(this.config.system.loggerOptions, name, version); + this.storage = new NodeStorage(this.logger, this.config.auth.clientId, this.cryptoProvider); + this.tokenCache = new TokenCache(this.storage, this.logger, this.config.cache.cachePlugin); + } + /** + * Creates the URL of the authorization request, letting the user input credentials and consent to the + * application. The URL targets the /authorize endpoint of the authority configured in the + * application object. + * + * Once the user inputs their credentials and consents, the authority will send a response to the redirect URI + * sent in the request and should contain an authorization code, which can then be used to acquire tokens via + * `acquireTokenByCode(AuthorizationCodeRequest)`. + */ + async getAuthCodeUrl(request) { + this.logger.info("getAuthCodeUrl called", request.correlationId); + const validRequest = { + ...request, + ...(await this.initializeBaseRequest(request)), + responseMode: request.responseMode || msalCommon.ResponseMode.QUERY, + authenticationScheme: msalCommon.AuthenticationScheme.BEARER + }; + const authClientConfig = await this.buildOauthClientConfiguration(validRequest.authority, validRequest.correlationId, undefined, undefined, request.azureCloudOptions); + const authorizationCodeClient = new msalCommon.AuthorizationCodeClient(authClientConfig); + this.logger.verbose("Auth code client created", validRequest.correlationId); + return authorizationCodeClient.getAuthCodeUrl(validRequest); + } + /** + * Acquires a token by exchanging the Authorization Code received from the first step of OAuth2.0 + * Authorization Code flow. + * + * `getAuthCodeUrl(AuthorizationCodeUrlRequest)` can be used to create the URL for the first step of OAuth2.0 + * Authorization Code flow. Ensure that values for redirectUri and scopes in AuthorizationCodeUrlRequest and + * AuthorizationCodeRequest are the same. + */ + async acquireTokenByCode(request, authCodePayLoad) { + this.logger.info("acquireTokenByCode called"); + if (request.state && authCodePayLoad) { + this.logger.info("acquireTokenByCode - validating state"); + this.validateState(request.state, authCodePayLoad.state || ""); + // eslint-disable-next-line no-param-reassign + authCodePayLoad = { + ...authCodePayLoad, + state: "" + }; + } + const validRequest = { + ...request, + ...(await this.initializeBaseRequest(request)), + authenticationScheme: msalCommon.AuthenticationScheme.BEARER + }; + const serverTelemetryManager = this.initializeServerTelemetryManager(ApiId.acquireTokenByCode, validRequest.correlationId); + try { + const authClientConfig = await this.buildOauthClientConfiguration(validRequest.authority, validRequest.correlationId, serverTelemetryManager, undefined, request.azureCloudOptions); + const authorizationCodeClient = new msalCommon.AuthorizationCodeClient(authClientConfig); + this.logger.verbose("Auth code client created", validRequest.correlationId); + return authorizationCodeClient.acquireToken(validRequest, authCodePayLoad); + } catch (e) { + if (e instanceof msalCommon.AuthError) { + e.setCorrelationId(validRequest.correlationId); + } + serverTelemetryManager.cacheFailedRequest(e); + throw e; + } + } + /** + * Acquires a token by exchanging the refresh token provided for a new set of tokens. + * + * This API is provided only for scenarios where you would like to migrate from ADAL to MSAL. Otherwise, it is + * recommended that you use `acquireTokenSilent()` for silent scenarios. When using `acquireTokenSilent()`, MSAL will + * handle the caching and refreshing of tokens automatically. + */ + async acquireTokenByRefreshToken(request) { + this.logger.info("acquireTokenByRefreshToken called", request.correlationId); + const validRequest = { + ...request, + ...(await this.initializeBaseRequest(request)), + authenticationScheme: msalCommon.AuthenticationScheme.BEARER + }; + const serverTelemetryManager = this.initializeServerTelemetryManager(ApiId.acquireTokenByRefreshToken, validRequest.correlationId); + try { + const refreshTokenClientConfig = await this.buildOauthClientConfiguration(validRequest.authority, validRequest.correlationId, serverTelemetryManager, undefined, request.azureCloudOptions); + const refreshTokenClient = new msalCommon.RefreshTokenClient(refreshTokenClientConfig); + this.logger.verbose("Refresh token client created", validRequest.correlationId); + return refreshTokenClient.acquireToken(validRequest); + } catch (e) { + if (e instanceof msalCommon.AuthError) { + e.setCorrelationId(validRequest.correlationId); + } + serverTelemetryManager.cacheFailedRequest(e); + throw e; + } + } + /** + * Acquires a token silently when a user specifies the account the token is requested for. + * + * This API expects the user to provide an account object and looks into the cache to retrieve the token if present. + * There is also an optional "forceRefresh" boolean the user can send to bypass the cache for access_token and id_token. + * In case the refresh_token is expired or not found, an error is thrown + * and the guidance is for the user to call any interactive token acquisition API (eg: `acquireTokenByCode()`). + */ + async acquireTokenSilent(request) { + const validRequest = { + ...request, + ...(await this.initializeBaseRequest(request)), + forceRefresh: request.forceRefresh || false + }; + const serverTelemetryManager = this.initializeServerTelemetryManager(ApiId.acquireTokenSilent, validRequest.correlationId, validRequest.forceRefresh); + try { + const silentFlowClientConfig = await this.buildOauthClientConfiguration(validRequest.authority, validRequest.correlationId, serverTelemetryManager, undefined, request.azureCloudOptions); + const silentFlowClient = new msalCommon.SilentFlowClient(silentFlowClientConfig); + this.logger.verbose("Silent flow client created", validRequest.correlationId); + return silentFlowClient.acquireToken(validRequest); + } catch (e) { + if (e instanceof msalCommon.AuthError) { + e.setCorrelationId(validRequest.correlationId); + } + serverTelemetryManager.cacheFailedRequest(e); + throw e; + } + } + /** + * Acquires tokens with password grant by exchanging client applications username and password for credentials + * + * The latest OAuth 2.0 Security Best Current Practice disallows the password grant entirely. + * More details on this recommendation at https://tools.ietf.org/html/draft-ietf-oauth-security-topics-13#section-3.4 + * Microsoft's documentation and recommendations are at: + * https://docs.microsoft.com/en-us/azure/active-directory/develop/msal-authentication-flows#usernamepassword + * + * @param request - UsenamePasswordRequest + */ + async acquireTokenByUsernamePassword(request) { + this.logger.info("acquireTokenByUsernamePassword called", request.correlationId); + const validRequest = { + ...request, + ...(await this.initializeBaseRequest(request)) + }; + const serverTelemetryManager = this.initializeServerTelemetryManager(ApiId.acquireTokenByUsernamePassword, validRequest.correlationId); + try { + const usernamePasswordClientConfig = await this.buildOauthClientConfiguration(validRequest.authority, validRequest.correlationId, serverTelemetryManager, undefined, request.azureCloudOptions); + const usernamePasswordClient = new msalCommon.UsernamePasswordClient(usernamePasswordClientConfig); + this.logger.verbose("Username password client created", validRequest.correlationId); + return usernamePasswordClient.acquireToken(validRequest); + } catch (e) { + if (e instanceof msalCommon.AuthError) { + e.setCorrelationId(validRequest.correlationId); + } + serverTelemetryManager.cacheFailedRequest(e); + throw e; + } + } + /** + * Gets the token cache for the application. + */ + getTokenCache() { + this.logger.info("getTokenCache called"); + return this.tokenCache; + } + /** + * Validates OIDC state by comparing the user cached state with the state received from the server. + * + * This API is provided for scenarios where you would use OAuth2.0 state parameter to mitigate against + * CSRF attacks. + * For more information about state, visit https://datatracker.ietf.org/doc/html/rfc6819#section-3.6. + * @param state + * @param cachedState + */ + validateState(state, cachedState) { + if (!state) { + throw NodeAuthError.createStateNotFoundError(); + } + if (state !== cachedState) { + throw msalCommon.ClientAuthError.createStateMismatchError(); + } + } + /** + * Returns the logger instance + */ + getLogger() { + return this.logger; + } + /** + * Replaces the default logger set in configurations with new Logger with new configurations + * @param logger - Logger instance + */ + setLogger(logger) { + this.logger = logger; + } + /** + * Builds the common configuration to be passed to the common component based on the platform configurarion + * @param authority - user passed authority in configuration + * @param serverTelemetryManager - initializes servertelemetry if passed + */ + async buildOauthClientConfiguration(authority, requestCorrelationId, serverTelemetryManager, azureRegionConfiguration, azureCloudOptions) { + this.logger.verbose("buildOauthClientConfiguration called", requestCorrelationId); + // precedence - azureCloudInstance + tenant >> authority and request >> config + const userAzureCloudOptions = azureCloudOptions ? azureCloudOptions : this.config.auth.azureCloudOptions; + // using null assertion operator as we ensure that all config values have default values in buildConfiguration() + this.logger.verbose(`building oauth client configuration with the authority: ${authority}`, requestCorrelationId); + const discoveredAuthority = await this.createAuthority(authority, azureRegionConfiguration, requestCorrelationId, userAzureCloudOptions); + serverTelemetryManager == null ? void 0 : serverTelemetryManager.updateRegionDiscoveryMetadata(discoveredAuthority.regionDiscoveryMetadata); + const clientConfiguration = { + authOptions: { + clientId: this.config.auth.clientId, + authority: discoveredAuthority, + clientCapabilities: this.config.auth.clientCapabilities + }, + loggerOptions: { + logLevel: this.config.system.loggerOptions.logLevel, + loggerCallback: this.config.system.loggerOptions.loggerCallback, + piiLoggingEnabled: this.config.system.loggerOptions.piiLoggingEnabled, + correlationId: requestCorrelationId + }, + cacheOptions: { + claimsBasedCachingEnabled: this.config.cache.claimsBasedCachingEnabled + }, + cryptoInterface: this.cryptoProvider, + networkInterface: this.config.system.networkClient, + storageInterface: this.storage, + serverTelemetryManager: serverTelemetryManager, + clientCredentials: { + clientSecret: this.clientSecret, + clientAssertion: this.clientAssertion ? this.getClientAssertion(discoveredAuthority) : undefined + }, + libraryInfo: { + sku: Constants.MSAL_SKU, + version: version, + cpu: process.arch || msalCommon.Constants.EMPTY_STRING, + os: process.platform || msalCommon.Constants.EMPTY_STRING + }, + telemetry: this.config.telemetry, + persistencePlugin: this.config.cache.cachePlugin, + serializableCache: this.tokenCache + }; + return clientConfiguration; + } + getClientAssertion(authority) { + return { + assertion: this.clientAssertion.getJwt(this.cryptoProvider, this.config.auth.clientId, authority.tokenEndpoint), + assertionType: Constants.JWT_BEARER_ASSERTION_TYPE + }; + } + /** + * Generates a request with the default scopes & generates a correlationId. + * @param authRequest - BaseAuthRequest for initialization + */ + async initializeBaseRequest(authRequest) { + this.logger.verbose("initializeRequestScopes called", authRequest.correlationId); + // Default authenticationScheme to Bearer, log that POP isn't supported yet + if (authRequest.authenticationScheme && authRequest.authenticationScheme === msalCommon.AuthenticationScheme.POP) { + this.logger.verbose("Authentication Scheme 'pop' is not supported yet, setting Authentication Scheme to 'Bearer' for request", authRequest.correlationId); + } + authRequest.authenticationScheme = msalCommon.AuthenticationScheme.BEARER; + // Set requested claims hash if claims-based caching is enabled and claims were requested + if (this.config.cache.claimsBasedCachingEnabled && authRequest.claims && + // Checks for empty stringified object "{}" which doesn't qualify as requested claims + !msalCommon.StringUtils.isEmptyObj(authRequest.claims)) { + authRequest.requestedClaimsHash = await this.cryptoProvider.hashString(authRequest.claims); + } + return { + ...authRequest, + scopes: [...(authRequest && authRequest.scopes || []), ...msalCommon.OIDC_DEFAULT_SCOPES], + correlationId: authRequest && authRequest.correlationId || this.cryptoProvider.createNewGuid(), + authority: authRequest.authority || this.config.auth.authority + }; + } + /** + * Initializes the server telemetry payload + * @param apiId - Id for a specific request + * @param correlationId - GUID + * @param forceRefresh - boolean to indicate network call + */ + initializeServerTelemetryManager(apiId, correlationId, forceRefresh) { + const telemetryPayload = { + clientId: this.config.auth.clientId, + correlationId: correlationId, + apiId: apiId, + forceRefresh: forceRefresh || false + }; + return new msalCommon.ServerTelemetryManager(telemetryPayload, this.storage); + } + /** + * Create authority instance. If authority not passed in request, default to authority set on the application + * object. If no authority set in application object, then default to common authority. + * @param authorityString - authority from user configuration + */ + async createAuthority(authorityString, azureRegionConfiguration, requestCorrelationId, azureCloudOptions) { + this.logger.verbose("createAuthority called", requestCorrelationId); + // build authority string based on auth params - azureCloudInstance is prioritized if provided + const authorityUrl = msalCommon.Authority.generateAuthority(authorityString, azureCloudOptions); + const authorityOptions = { + protocolMode: this.config.auth.protocolMode, + knownAuthorities: this.config.auth.knownAuthorities, + cloudDiscoveryMetadata: this.config.auth.cloudDiscoveryMetadata, + authorityMetadata: this.config.auth.authorityMetadata, + azureRegionConfiguration, + skipAuthorityMetadataCache: this.config.auth.skipAuthorityMetadataCache + }; + return await msalCommon.AuthorityFactory.createDiscoveredInstance(authorityUrl, this.config.system.networkClient, this.storage, authorityOptions, this.logger); + } + /** + * Clear the cache + */ + clearCache() { + this.storage.clear(); + } +} + +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. + */ +class LoopbackClient { + /** + * Spins up a loopback server which returns the server response when the localhost redirectUri is hit + * @param successTemplate + * @param errorTemplate + * @returns + */ + async listenForAuthCode(successTemplate, errorTemplate) { + if (!!this.server) { + throw NodeAuthError.createLoopbackServerAlreadyExistsError(); + } + const authCodeListener = new Promise((resolve, reject) => { + this.server = http.createServer(async (req, res) => { + const url = req.url; + if (!url) { + res.end(errorTemplate || "Error occurred loading redirectUrl"); + reject(NodeAuthError.createUnableToLoadRedirectUrlError()); + return; + } else if (url === msalCommon.Constants.FORWARD_SLASH) { + res.end(successTemplate || "Auth code was successfully acquired. You can close this window now."); + return; + } + const authCodeResponse = msalCommon.UrlString.getDeserializedQueryString(url); + if (authCodeResponse.code) { + const redirectUri = await this.getRedirectUri(); + res.writeHead(HttpStatus.REDIRECT, { + location: redirectUri + }); // Prevent auth code from being saved in the browser history + res.end(); + } + resolve(authCodeResponse); + }); + this.server.listen(0); // Listen on any available port + }); + // Wait for server to be listening + await new Promise(resolve => { + let ticks = 0; + const id = setInterval(() => { + if (LOOPBACK_SERVER_CONSTANTS.TIMEOUT_MS / LOOPBACK_SERVER_CONSTANTS.INTERVAL_MS < ticks) { + throw NodeAuthError.createLoopbackServerTimeoutError(); + } + if (this.server.listening) { + clearInterval(id); + resolve(); + } + ticks++; + }, LOOPBACK_SERVER_CONSTANTS.INTERVAL_MS); + }); + return authCodeListener; + } + /** + * Get the port that the loopback server is running on + * @returns + */ + getRedirectUri() { + if (!this.server) { + throw NodeAuthError.createNoLoopbackServerExistsError(); + } + const address = this.server.address(); + if (!address || typeof address === "string" || !address.port) { + this.closeServer(); + throw NodeAuthError.createInvalidLoopbackAddressTypeError(); + } + const port = address && address.port; + return `${Constants.HTTP_PROTOCOL}${Constants.LOCALHOST}:${port}`; + } + /** + * Close the loopback server + */ + closeServer() { + if (!!this.server) { + this.server.close(); + } + } +} + +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. + */ +/** + * This class is to be used to acquire tokens for public client applications (desktop, mobile). Public client applications + * are not trusted to safely store application secrets, and therefore can only request tokens in the name of an user. + * @public + */ +class PublicClientApplication extends ClientApplication { + /** + * Important attributes in the Configuration object for auth are: + * - clientID: the application ID of your application. You can obtain one by registering your application with our Application registration portal. + * - authority: the authority URL for your application. + * + * AAD authorities are of the form https://login.microsoftonline.com/\{Enter_the_Tenant_Info_Here\}. + * - If your application supports Accounts in one organizational directory, replace "Enter_the_Tenant_Info_Here" value with the Tenant Id or Tenant name (for example, contoso.microsoft.com). + * - If your application supports Accounts in any organizational directory, replace "Enter_the_Tenant_Info_Here" value with organizations. + * - If your application supports Accounts in any organizational directory and personal Microsoft accounts, replace "Enter_the_Tenant_Info_Here" value with common. + * - To restrict support to Personal Microsoft accounts only, replace "Enter_the_Tenant_Info_Here" value with consumers. + * + * Azure B2C authorities are of the form https://\{instance\}/\{tenant\}/\{policy\}. Each policy is considered + * its own authority. You will have to set the all of the knownAuthorities at the time of the client application + * construction. + * + * ADFS authorities are of the form https://\{instance\}/adfs. + */ + constructor(configuration) { + super(configuration); + if (this.config.broker.nativeBrokerPlugin) { + if (this.config.broker.nativeBrokerPlugin.isBrokerAvailable) { + this.nativeBrokerPlugin = this.config.broker.nativeBrokerPlugin; + this.nativeBrokerPlugin.setLogger(this.config.system.loggerOptions); + } else { + this.logger.warning("NativeBroker implementation was provided but the broker is unavailable."); + } + } + } + /** + * Acquires a token from the authority using OAuth2.0 device code flow. + * This flow is designed for devices that do not have access to a browser or have input constraints. + * The authorization server issues a DeviceCode object with a verification code, an end-user code, + * and the end-user verification URI. The DeviceCode object is provided through a callback, and the end-user should be + * instructed to use another device to navigate to the verification URI to input credentials. + * Since the client cannot receive incoming requests, it polls the authorization server repeatedly + * until the end-user completes input of credentials. + */ + async acquireTokenByDeviceCode(request) { + this.logger.info("acquireTokenByDeviceCode called", request.correlationId); + const validRequest = Object.assign(request, await this.initializeBaseRequest(request)); + const serverTelemetryManager = this.initializeServerTelemetryManager(ApiId.acquireTokenByDeviceCode, validRequest.correlationId); + try { + const deviceCodeConfig = await this.buildOauthClientConfiguration(validRequest.authority, validRequest.correlationId, serverTelemetryManager, undefined, request.azureCloudOptions); + const deviceCodeClient = new msalCommon.DeviceCodeClient(deviceCodeConfig); + this.logger.verbose("Device code client created", validRequest.correlationId); + return deviceCodeClient.acquireToken(validRequest); + } catch (e) { + if (e instanceof msalCommon.AuthError) { + e.setCorrelationId(validRequest.correlationId); + } + serverTelemetryManager.cacheFailedRequest(e); + throw e; + } + } + /** + * Acquires a token interactively via the browser by requesting an authorization code then exchanging it for a token. + */ + async acquireTokenInteractive(request) { + const correlationId = request.correlationId || this.cryptoProvider.createNewGuid(); + this.logger.trace("acquireTokenInteractive called", correlationId); + const { + openBrowser, + successTemplate, + errorTemplate, + windowHandle, + loopbackClient: customLoopbackClient, + ...remainingProperties + } = request; + if (this.nativeBrokerPlugin) { + var _remainingProperties$; + const brokerRequest = { + ...remainingProperties, + clientId: this.config.auth.clientId, + scopes: request.scopes || msalCommon.OIDC_DEFAULT_SCOPES, + redirectUri: `${Constants.HTTP_PROTOCOL}${Constants.LOCALHOST}`, + authority: request.authority || this.config.auth.authority, + correlationId: correlationId, + extraParameters: { + ...remainingProperties.extraQueryParameters, + ...remainingProperties.tokenQueryParameters + }, + accountId: (_remainingProperties$ = remainingProperties.account) == null ? void 0 : _remainingProperties$.nativeAccountId + }; + return this.nativeBrokerPlugin.acquireTokenInteractive(brokerRequest, windowHandle); + } + const { + verifier, + challenge + } = await this.cryptoProvider.generatePkceCodes(); + const loopbackClient = customLoopbackClient || new LoopbackClient(); + const authCodeListener = loopbackClient.listenForAuthCode(successTemplate, errorTemplate); + const redirectUri = loopbackClient.getRedirectUri(); + const validRequest = { + ...remainingProperties, + correlationId: correlationId, + scopes: request.scopes || msalCommon.OIDC_DEFAULT_SCOPES, + redirectUri: redirectUri, + responseMode: msalCommon.ResponseMode.QUERY, + codeChallenge: challenge, + codeChallengeMethod: msalCommon.CodeChallengeMethodValues.S256 + }; + const authCodeUrl = await this.getAuthCodeUrl(validRequest); + await openBrowser(authCodeUrl); + const authCodeResponse = await authCodeListener.finally(() => { + loopbackClient.closeServer(); + }); + if (authCodeResponse.error) { + throw new msalCommon.ServerError(authCodeResponse.error, authCodeResponse.error_description, authCodeResponse.suberror); + } else if (!authCodeResponse.code) { + throw NodeAuthError.createNoAuthCodeInResponseError(); + } + const clientInfo = authCodeResponse.client_info; + const tokenRequest = { + code: authCodeResponse.code, + codeVerifier: verifier, + clientInfo: clientInfo || msalCommon.Constants.EMPTY_STRING, + ...validRequest + }; + return this.acquireTokenByCode(tokenRequest); + } + /** + * Returns a token retrieved either from the cache or by exchanging the refresh token for a fresh access token. If brokering is enabled the token request will be serviced by the broker. + * @param request + * @returns + */ + async acquireTokenSilent(request) { + const correlationId = request.correlationId || this.cryptoProvider.createNewGuid(); + this.logger.trace("acquireTokenSilent called", correlationId); + if (this.nativeBrokerPlugin) { + const brokerRequest = { + ...request, + clientId: this.config.auth.clientId, + scopes: request.scopes || msalCommon.OIDC_DEFAULT_SCOPES, + redirectUri: `${Constants.HTTP_PROTOCOL}${Constants.LOCALHOST}`, + authority: request.authority || this.config.auth.authority, + correlationId: correlationId, + extraParameters: request.tokenQueryParameters, + accountId: request.account.nativeAccountId, + forceRefresh: request.forceRefresh || false + }; + return this.nativeBrokerPlugin.acquireTokenSilent(brokerRequest); + } + return super.acquireTokenSilent(request); + } + /** + * Removes cache artifacts associated with the given account + * @param request + * @returns + */ + async signOut(request) { + if (this.nativeBrokerPlugin && request.account.nativeAccountId) { + const signoutRequest = { + clientId: this.config.auth.clientId, + accountId: request.account.nativeAccountId, + correlationId: request.correlationId || this.cryptoProvider.createNewGuid() + }; + await this.nativeBrokerPlugin.signOut(signoutRequest); + } + await this.getTokenCache().removeAccount(request.account); + } + /** + * Returns all cached accounts for this application. If brokering is enabled this request will be serviced by the broker. + * @returns + */ + async getAllAccounts() { + if (this.nativeBrokerPlugin) { + const correlationId = this.cryptoProvider.createNewGuid(); + return this.nativeBrokerPlugin.getAllAccounts(this.config.auth.clientId, correlationId); + } + return this.getTokenCache().getAllAccounts(); + } +} + +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. + */ +/** + * Client assertion of type jwt-bearer used in confidential client flows + * @public + */ +class ClientAssertion { + /** + * Initialize the ClientAssertion class from the clientAssertion passed by the user + * @param assertion - refer https://tools.ietf.org/html/rfc7521 + */ + static fromAssertion(assertion) { + const clientAssertion = new ClientAssertion(); + clientAssertion.jwt = assertion; + return clientAssertion; + } + /** + * Initialize the ClientAssertion class from the certificate passed by the user + * @param thumbprint - identifier of a certificate + * @param privateKey - secret key + * @param publicCertificate - electronic document provided to prove the ownership of the public key + */ + static fromCertificate(thumbprint, privateKey, publicCertificate) { + const clientAssertion = new ClientAssertion(); + clientAssertion.privateKey = privateKey; + clientAssertion.thumbprint = thumbprint; + if (publicCertificate) { + clientAssertion.publicCertificate = this.parseCertificate(publicCertificate); + } + return clientAssertion; + } + /** + * Update JWT for certificate based clientAssertion, if passed by the user, uses it as is + * @param cryptoProvider - library's crypto helper + * @param issuer - iss claim + * @param jwtAudience - aud claim + */ + getJwt(cryptoProvider, issuer, jwtAudience) { + // if assertion was created from certificate, check if jwt is expired and create new one. + if (this.privateKey && this.thumbprint) { + if (this.jwt && !this.isExpired() && issuer === this.issuer && jwtAudience === this.jwtAudience) { + return this.jwt; + } + return this.createJwt(cryptoProvider, issuer, jwtAudience); + } + /* + * if assertion was created by caller, then we just append it. It is up to the caller to + * ensure that it contains necessary claims and that it is not expired. + */ + if (this.jwt) { + return this.jwt; + } + throw msalCommon.ClientAuthError.createInvalidAssertionError(); + } + /** + * JWT format and required claims specified: https://tools.ietf.org/html/rfc7523#section-3 + */ + createJwt(cryptoProvider, issuer, jwtAudience) { + this.issuer = issuer; + this.jwtAudience = jwtAudience; + const issuedAt = msalCommon.TimeUtils.nowSeconds(); + this.expirationTime = issuedAt + 600; + const header = { + alg: JwtConstants.RSA_256, + x5t: EncodingUtils.base64EncodeUrl(this.thumbprint, "hex") + }; + if (this.publicCertificate) { + Object.assign(header, { + x5c: this.publicCertificate + }); + } + const payload = { + [JwtConstants.AUDIENCE]: this.jwtAudience, + [JwtConstants.EXPIRATION_TIME]: this.expirationTime, + [JwtConstants.ISSUER]: this.issuer, + [JwtConstants.SUBJECT]: this.issuer, + [JwtConstants.NOT_BEFORE]: issuedAt, + [JwtConstants.JWT_ID]: cryptoProvider.createNewGuid() + }; + this.jwt = jsonwebtoken.sign(payload, this.privateKey, { + header + }); + return this.jwt; + } + /** + * Utility API to check expiration + */ + isExpired() { + return this.expirationTime < msalCommon.TimeUtils.nowSeconds(); + } + /** + * Extracts the raw certs from a given certificate string and returns them in an array. + * @param publicCertificate - electronic document provided to prove the ownership of the public key + */ + static parseCertificate(publicCertificate) { + /** + * This is regex to identify the certs in a given certificate string. + * We want to look for the contents between the BEGIN and END certificate strings, without the associated newlines. + * The information in parens "(.+?)" is the capture group to represent the cert we want isolated. + * "." means any string character, "+" means match 1 or more times, and "?" means the shortest match. + * The "g" at the end of the regex means search the string globally, and the "s" enables the "." to match newlines. + */ + const regexToFindCerts = /-----BEGIN CERTIFICATE-----\r*\n(.+?)\r*\n-----END CERTIFICATE-----/gs; + const certs = []; + let matches; + while ((matches = regexToFindCerts.exec(publicCertificate)) !== null) { + // matches[1] represents the first parens capture group in the regex. + certs.push(matches[1].replace(/\r*\n/g, msalCommon.Constants.EMPTY_STRING)); + } + return certs; + } +} + +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. + */ +/** + * This class is to be used to acquire tokens for confidential client applications (webApp, webAPI). Confidential client applications + * will configure application secrets, client certificates/assertions as applicable + * @public + */ +class ConfidentialClientApplication extends ClientApplication { + /** + * Constructor for the ConfidentialClientApplication + * + * Required attributes in the Configuration object are: + * - clientID: the application ID of your application. You can obtain one by registering your application with our application registration portal + * - authority: the authority URL for your application. + * - client credential: Must set either client secret, certificate, or assertion for confidential clients. You can obtain a client secret from the application registration portal. + * + * In Azure AD, authority is a URL indicating of the form https://login.microsoftonline.com/\{Enter_the_Tenant_Info_Here\}. + * If your application supports Accounts in one organizational directory, replace "Enter_the_Tenant_Info_Here" value with the Tenant Id or Tenant name (for example, contoso.microsoft.com). + * If your application supports Accounts in any organizational directory, replace "Enter_the_Tenant_Info_Here" value with organizations. + * If your application supports Accounts in any organizational directory and personal Microsoft accounts, replace "Enter_the_Tenant_Info_Here" value with common. + * To restrict support to Personal Microsoft accounts only, replace "Enter_the_Tenant_Info_Here" value with consumers. + * + * In Azure B2C, authority is of the form https://\{instance\}/tfp/\{tenant\}/\{policyName\}/ + * Full B2C functionality will be available in this library in future versions. + * + * @param Configuration - configuration object for the MSAL ConfidentialClientApplication instance + */ + constructor(configuration) { + super(configuration); + this.setClientCredential(this.config); + this.appTokenProvider = undefined; + } + /** + * This extensibility point only works for the client_credential flow, i.e. acquireTokenByClientCredential and + * is meant for Azure SDK to enhance Managed Identity support. + * + * @param IAppTokenProvider - Extensibility interface, which allows the app developer to return a token from a custom source. + */ + SetAppTokenProvider(provider) { + this.appTokenProvider = provider; + } + /** + * Acquires tokens from the authority for the application (not for an end user). + */ + async acquireTokenByClientCredential(request) { + this.logger.info("acquireTokenByClientCredential called", request.correlationId); + // If there is a client assertion present in the request, it overrides the one present in the client configuration + let clientAssertion; + if (request.clientAssertion) { + clientAssertion = { + assertion: request.clientAssertion, + assertionType: Constants.JWT_BEARER_ASSERTION_TYPE + }; + } + const baseRequest = await this.initializeBaseRequest(request); + // valid base request should not contain oidc scopes in this grant type + const validBaseRequest = { + ...baseRequest, + scopes: baseRequest.scopes.filter(scope => !msalCommon.OIDC_DEFAULT_SCOPES.includes(scope)) + }; + const validRequest = { + ...request, + ...validBaseRequest, + clientAssertion + }; + const azureRegionConfiguration = { + azureRegion: validRequest.azureRegion, + environmentRegion: process.env[REGION_ENVIRONMENT_VARIABLE] + }; + const serverTelemetryManager = this.initializeServerTelemetryManager(ApiId.acquireTokenByClientCredential, validRequest.correlationId, validRequest.skipCache); + try { + const clientCredentialConfig = await this.buildOauthClientConfiguration(validRequest.authority, validRequest.correlationId, serverTelemetryManager, azureRegionConfiguration, request.azureCloudOptions); + const clientCredentialClient = new msalCommon.ClientCredentialClient(clientCredentialConfig, this.appTokenProvider); + this.logger.verbose("Client credential client created", validRequest.correlationId); + return clientCredentialClient.acquireToken(validRequest); + } catch (e) { + if (e instanceof msalCommon.AuthError) { + e.setCorrelationId(validRequest.correlationId); + } + serverTelemetryManager.cacheFailedRequest(e); + throw e; + } + } + /** + * Acquires tokens from the authority for the application. + * + * Used in scenarios where the current app is a middle-tier service which was called with a token + * representing an end user. The current app can use the token (oboAssertion) to request another + * token to access downstream web API, on behalf of that user. + * + * The current middle-tier app has no user interaction to obtain consent. + * See how to gain consent upfront for your middle-tier app from this article. + * https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-on-behalf-of-flow#gaining-consent-for-the-middle-tier-application + */ + async acquireTokenOnBehalfOf(request) { + this.logger.info("acquireTokenOnBehalfOf called", request.correlationId); + const validRequest = { + ...request, + ...(await this.initializeBaseRequest(request)) + }; + try { + const onBehalfOfConfig = await this.buildOauthClientConfiguration(validRequest.authority, validRequest.correlationId, undefined, undefined, request.azureCloudOptions); + const oboClient = new msalCommon.OnBehalfOfClient(onBehalfOfConfig); + this.logger.verbose("On behalf of client created", validRequest.correlationId); + return oboClient.acquireToken(validRequest); + } catch (e) { + if (e instanceof msalCommon.AuthError) { + e.setCorrelationId(validRequest.correlationId); + } + throw e; + } + } + setClientCredential(configuration) { + const clientSecretNotEmpty = !msalCommon.StringUtils.isEmpty(configuration.auth.clientSecret); + const clientAssertionNotEmpty = !msalCommon.StringUtils.isEmpty(configuration.auth.clientAssertion); + const certificate = configuration.auth.clientCertificate || { + thumbprint: msalCommon.Constants.EMPTY_STRING, + privateKey: msalCommon.Constants.EMPTY_STRING + }; + const certificateNotEmpty = !msalCommon.StringUtils.isEmpty(certificate.thumbprint) || !msalCommon.StringUtils.isEmpty(certificate.privateKey); + /* + * If app developer configures this callback, they don't need a credential + * i.e. AzureSDK can get token from Managed Identity without a cert / secret + */ + if (this.appTokenProvider) { + return; + } + // Check that at most one credential is set on the application + if (clientSecretNotEmpty && clientAssertionNotEmpty || clientAssertionNotEmpty && certificateNotEmpty || clientSecretNotEmpty && certificateNotEmpty) { + throw msalCommon.ClientAuthError.createInvalidCredentialError(); + } + if (configuration.auth.clientSecret) { + this.clientSecret = configuration.auth.clientSecret; + return; + } + if (configuration.auth.clientAssertion) { + this.clientAssertion = ClientAssertion.fromAssertion(configuration.auth.clientAssertion); + return; + } + if (!certificateNotEmpty) { + throw msalCommon.ClientAuthError.createInvalidCredentialError(); + } else { + var _configuration$auth$c; + this.clientAssertion = ClientAssertion.fromCertificate(certificate.thumbprint, certificate.privateKey, (_configuration$auth$c = configuration.auth.clientCertificate) == null ? void 0 : _configuration$auth$c.x5c); + } + } +} + +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. + */ +class DistributedCachePlugin { + constructor(client, partitionManager) { + this.client = client; + this.partitionManager = partitionManager; + } + async beforeCacheAccess(cacheContext) { + const partitionKey = await this.partitionManager.getKey(); + const cacheData = await this.client.get(partitionKey); + cacheContext.tokenCache.deserialize(cacheData); + } + async afterCacheAccess(cacheContext) { + if (cacheContext.cacheHasChanged) { + const kvStore = cacheContext.tokenCache.getKVStore(); + const accountEntities = Object.values(kvStore).filter(value => msalCommon.AccountEntity.isAccountEntity(value)); + if (accountEntities.length > 0) { + const accountEntity = accountEntities[0]; + const partitionKey = await this.partitionManager.extractKey(accountEntity); + await this.client.set(partitionKey, cacheContext.tokenCache.serialize()); + } + } + } +} + +Object.defineProperty(exports, "AuthError", ({ + enumerable: true, + get: function () { + return msalCommon.AuthError; + } +})); +Object.defineProperty(exports, "AuthErrorMessage", ({ + enumerable: true, + get: function () { + return msalCommon.AuthErrorMessage; + } +})); +Object.defineProperty(exports, "AzureCloudInstance", ({ + enumerable: true, + get: function () { + return msalCommon.AzureCloudInstance; + } +})); +Object.defineProperty(exports, "ClientAuthError", ({ + enumerable: true, + get: function () { + return msalCommon.ClientAuthError; + } +})); +Object.defineProperty(exports, "ClientAuthErrorMessage", ({ + enumerable: true, + get: function () { + return msalCommon.ClientAuthErrorMessage; + } +})); +Object.defineProperty(exports, "ClientConfigurationError", ({ + enumerable: true, + get: function () { + return msalCommon.ClientConfigurationError; + } +})); +Object.defineProperty(exports, "ClientConfigurationErrorMessage", ({ + enumerable: true, + get: function () { + return msalCommon.ClientConfigurationErrorMessage; + } +})); +Object.defineProperty(exports, "InteractionRequiredAuthError", ({ + enumerable: true, + get: function () { + return msalCommon.InteractionRequiredAuthError; + } +})); +Object.defineProperty(exports, "InteractionRequiredAuthErrorMessage", ({ + enumerable: true, + get: function () { + return msalCommon.InteractionRequiredAuthErrorMessage; + } +})); +Object.defineProperty(exports, "LogLevel", ({ + enumerable: true, + get: function () { + return msalCommon.LogLevel; + } +})); +Object.defineProperty(exports, "Logger", ({ + enumerable: true, + get: function () { + return msalCommon.Logger; + } +})); +Object.defineProperty(exports, "PromptValue", ({ + enumerable: true, + get: function () { + return msalCommon.PromptValue; + } +})); +Object.defineProperty(exports, "ProtocolMode", ({ + enumerable: true, + get: function () { + return msalCommon.ProtocolMode; + } +})); +Object.defineProperty(exports, "ResponseMode", ({ + enumerable: true, + get: function () { + return msalCommon.ResponseMode; + } +})); +Object.defineProperty(exports, "ServerError", ({ + enumerable: true, + get: function () { + return msalCommon.ServerError; + } +})); +Object.defineProperty(exports, "TokenCacheContext", ({ + enumerable: true, + get: function () { + return msalCommon.TokenCacheContext; + } +})); +exports.ClientApplication = ClientApplication; +exports.ClientAssertion = ClientAssertion; +exports.ConfidentialClientApplication = ConfidentialClientApplication; +exports.CryptoProvider = CryptoProvider; +exports.DistributedCachePlugin = DistributedCachePlugin; +exports.NodeStorage = NodeStorage; +exports.PublicClientApplication = PublicClientApplication; +exports.TokenCache = TokenCache; +exports.buildAppConfiguration = buildAppConfiguration; +exports.version = version; +//# sourceMappingURL=msal-node.cjs.development.js.map + + +/***/ }), + +/***/ 9802: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; +function e(e){return e&&"object"==typeof e&&"default"in e?e.default:e}Object.defineProperty(exports, "__esModule", ({value:!0}));var t,r,n,i=__nccwpck_require__(5728),o=__nccwpck_require__(3685),s=e(o),a=e(__nccwpck_require__(5687)),c=__nccwpck_require__(5840),l=e(__nccwpck_require__(6113)),h=__nccwpck_require__(7486);!function(e){e.GET="get",e.POST="post"}(t||(t={})),function(e){e[e.SUCCESS_RANGE_START=200]="SUCCESS_RANGE_START",e[e.SUCCESS_RANGE_END=299]="SUCCESS_RANGE_END",e[e.REDIRECT=302]="REDIRECT",e[e.CLIENT_ERROR_RANGE_START=400]="CLIENT_ERROR_RANGE_START",e[e.CLIENT_ERROR_RANGE_END=499]="CLIENT_ERROR_RANGE_END",e[e.SERVER_ERROR_RANGE_START=500]="SERVER_ERROR_RANGE_START",e[e.SERVER_ERROR_RANGE_END=599]="SERVER_ERROR_RANGE_END"}(r||(r={})),function(e){e[e.SUCCESS_RANGE_START=200]="SUCCESS_RANGE_START",e[e.SUCCESS_RANGE_END=299]="SUCCESS_RANGE_END",e[e.SERVER_ERROR=500]="SERVER_ERROR"}(n||(n={}));const u="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~";var d;!function(e){e[e.acquireTokenSilent=62]="acquireTokenSilent",e[e.acquireTokenByUsernamePassword=371]="acquireTokenByUsernamePassword",e[e.acquireTokenByDeviceCode=671]="acquireTokenByDeviceCode",e[e.acquireTokenByClientCredential=771]="acquireTokenByClientCredential",e[e.acquireTokenByCode=871]="acquireTokenByCode",e[e.acquireTokenByRefreshToken=872]="acquireTokenByRefreshToken"}(d||(d={}));class g{static getNetworkResponse(e,t,r){return{headers:e,body:t,status:r}}static urlToHttpOptions(e){const t={protocol:e.protocol,hostname:e.hostname&&e.hostname.startsWith("[")?e.hostname.slice(1,-1):e.hostname,hash:e.hash,search:e.search,pathname:e.pathname,path:`${e.pathname||""}${e.search||""}`,href:e.href};return""!==e.port&&(t.port=Number(e.port)),(e.username||e.password)&&(t.auth=`${decodeURIComponent(e.username)}:${decodeURIComponent(e.password)}`),t}}class p{constructor(e,t){this.proxyUrl=e||"",this.customAgentOptions=t||{}}async sendGetRequestAsync(e,r){return this.proxyUrl?y(e,this.proxyUrl,t.GET,r,this.customAgentOptions):m(e,t.GET,r,this.customAgentOptions)}async sendPostRequestAsync(e,r,n){return this.proxyUrl?y(e,this.proxyUrl,t.POST,r,this.customAgentOptions,n):m(e,t.POST,r,this.customAgentOptions,n)}}const y=(e,i,o,a,c,l)=>{const h=new URL(e),u=new URL(i),d={host:u.hostname,port:u.port,method:"CONNECT",path:h.hostname,headers:(null==a?void 0:a.headers)||{}};l&&(d.timeout=l),c&&Object.keys(c).length&&(d.agent=new s.Agent(c));let p="";if(o===t.POST){const e=(null==a?void 0:a.body)||"";p=`Content-Type: application/x-www-form-urlencoded\r\nContent-Length: ${e.length}\r\n\r\n`+e}const y=`${o.toUpperCase()} ${h.href} HTTP/1.1\r\nHost: ${h.host}\r\nConnection: close\r\n`+p+"\r\n";return new Promise((e,t)=>{const i=s.request(d);d.timeout&&i.on("timeout",()=>{i.destroy(),t(new Error("Request time out"))}),i.end(),i.on("connect",(o,s)=>{const a=(null==o?void 0:o.statusCode)||n.SERVER_ERROR;(an.SUCCESS_RANGE_END)&&(i.destroy(),s.destroy(),t(new Error(`Error connecting to proxy. Http status code: ${o.statusCode}. Http status message: ${(null==o?void 0:o.statusMessage)||"Unknown"}`))),d.timeout&&(s.setTimeout(d.timeout),s.on("timeout",()=>{i.destroy(),s.destroy(),t(new Error("Request time out"))})),s.write(y);const c=[];s.on("data",e=>{c.push(e)}),s.on("end",()=>{const t=Buffer.concat([...c]).toString().split("\r\n"),n=parseInt(t[0].split(" ")[1]),o=t[0].split(" ").slice(2).join(" "),s=t[t.length-1],a=t.slice(1,t.length-2),l=new Map;a.forEach(e=>{const t=e.split(new RegExp(/:\s(.*)/s)),r=t[0];let n=t[1];try{const e=JSON.parse(n);e&&"object"==typeof e&&(n=e)}catch(e){}l.set(r,n)});const h=Object.fromEntries(l),u=g.getNetworkResponse(h,C(n,o,h,s),n);(nr.SUCCESS_RANGE_END)&&"authorization_pending"!==u.body.error&&i.destroy(),e(u)}),s.on("error",e=>{i.destroy(),s.destroy(),t(new Error(e.toString()))})}),i.on("error",e=>{i.destroy(),t(new Error(e.toString()))})})},m=(e,n,i,o,s)=>{const c=n===t.POST,l=(null==i?void 0:i.body)||"",h=new URL(e),u={method:n,headers:(null==i?void 0:i.headers)||{},...g.urlToHttpOptions(h)};return s&&(u.timeout=s),o&&Object.keys(o).length&&(u.agent=new a.Agent(o)),c&&(u.headers={...u.headers,"Content-Length":l.length}),new Promise((e,t)=>{const n=a.request(u);s&&n.on("timeout",()=>{n.destroy(),t(new Error("Request time out"))}),c&&n.write(l),n.end(),n.on("response",t=>{const i=t.headers,o=t.statusCode,s=t.statusMessage,a=[];t.on("data",e=>{a.push(e)}),t.on("end",()=>{const t=Buffer.concat([...a]).toString(),c=g.getNetworkResponse(i,C(o,s,i,t),o);(or.SUCCESS_RANGE_END)&&"authorization_pending"!==c.body.error&&n.destroy(),e(c)})}),n.on("error",e=>{n.destroy(),t(new Error(e.toString()))})})},C=(e,t,n,i)=>{let o;try{o=JSON.parse(i)}catch(i){let s,a;e>=r.CLIENT_ERROR_RANGE_START&&e<=r.CLIENT_ERROR_RANGE_END?(s="client_error",a="A client"):e>=r.SERVER_ERROR_RANGE_START&&e<=r.SERVER_ERROR_RANGE_END?(s="server_error",a="A server"):(s="unknown_error",a="An unknown"),o={error:s,error_description:`${a} error occured.\nHttp status code: ${e}\nHttp status message: ${t||"Unknown"}\nHeaders: ${JSON.stringify(n)}`}}return o},f={clientId:i.Constants.EMPTY_STRING,authority:i.Constants.DEFAULT_AUTHORITY,clientSecret:i.Constants.EMPTY_STRING,clientAssertion:i.Constants.EMPTY_STRING,clientCertificate:{thumbprint:i.Constants.EMPTY_STRING,privateKey:i.Constants.EMPTY_STRING,x5c:i.Constants.EMPTY_STRING},knownAuthorities:[],cloudDiscoveryMetadata:i.Constants.EMPTY_STRING,authorityMetadata:i.Constants.EMPTY_STRING,clientCapabilities:[],protocolMode:i.ProtocolMode.AAD,azureCloudOptions:{azureCloudInstance:i.AzureCloudInstance.None,tenant:i.Constants.EMPTY_STRING},skipAuthorityMetadataCache:!1},T={claimsBasedCachingEnabled:!0},A={loggerCallback:()=>{},piiLoggingEnabled:!1,logLevel:i.LogLevel.Info},E={loggerOptions:A,networkClient:new p,proxyUrl:i.Constants.EMPTY_STRING,customAgentOptions:{}},k={application:{appName:i.Constants.EMPTY_STRING,appVersion:i.Constants.EMPTY_STRING}};function R({auth:e,broker:t,cache:r,system:n,telemetry:i}){const o={...E,networkClient:new p(null==n?void 0:n.proxyUrl,null==n?void 0:n.customAgentOptions),loggerOptions:(null==n?void 0:n.loggerOptions)||A};return{auth:{...f,...e},broker:{...t},cache:{...T,...r},system:{...o,...n},telemetry:{...k,...i}}}class I{generateGuid(){return c.v4()}isGuid(e){return/^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(e)}}class v{static base64Encode(e,t){return Buffer.from(e,t).toString("base64")}static base64EncodeUrl(e,t){return v.base64Encode(e,t).replace(/=/g,i.Constants.EMPTY_STRING).replace(/\+/g,"-").replace(/\//g,"_")}static base64Decode(e){return Buffer.from(e,"base64").toString("utf8")}static base64DecodeUrl(e){let t=e.replace(/-/g,"+").replace(/_/g,"/");for(;t.length%4;)t+="=";return v.base64Decode(t)}}class S{sha256(e){return l.createHash("sha256").update(e).digest()}}class w{constructor(){this.hashUtils=new S}async generatePkceCodes(){const e=this.generateCodeVerifier();return{verifier:e,challenge:this.generateCodeChallengeFromVerifier(e)}}generateCodeVerifier(){const e=[],t=256-256%u.length;for(;e.length<=32;){const r=l.randomBytes(1)[0];r>=t||e.push(u[r%u.length])}const r=e.join(i.Constants.EMPTY_STRING);return v.base64EncodeUrl(r)}generateCodeChallengeFromVerifier(e){return v.base64EncodeUrl(this.hashUtils.sha256(e).toString("base64"),"base64")}}class _{constructor(){this.pkceGenerator=new w,this.guidGenerator=new I,this.hashUtils=new S}createNewGuid(){return this.guidGenerator.generateGuid()}base64Encode(e){return v.base64Encode(e)}base64Decode(e){return v.base64Decode(e)}generatePkceCodes(){return this.pkceGenerator.generatePkceCodes()}getPublicKeyThumbprint(){throw new Error("Method not implemented.")}removeTokenBindingKey(){throw new Error("Method not implemented.")}clearKeystore(){throw new Error("Method not implemented.")}signJwt(){throw new Error("Method not implemented.")}async hashString(e){return v.base64EncodeUrl(this.hashUtils.sha256(e).toString("base64"),"base64")}}class b{static deserializeJSONBlob(e){return i.StringUtils.isEmpty(e)?{}:JSON.parse(e)}static deserializeAccounts(e){const t={};return e&&Object.keys(e).map((function(r){const n=e[r],o={homeAccountId:n.home_account_id,environment:n.environment,realm:n.realm,localAccountId:n.local_account_id,username:n.username,authorityType:n.authority_type,name:n.name,clientInfo:n.client_info,lastModificationTime:n.last_modification_time,lastModificationApp:n.last_modification_app},s=new i.AccountEntity;i.CacheManager.toObject(s,o),t[r]=s})),t}static deserializeIdTokens(e){const t={};return e&&Object.keys(e).map((function(r){const n=e[r],o={homeAccountId:n.home_account_id,environment:n.environment,credentialType:n.credential_type,clientId:n.client_id,secret:n.secret,realm:n.realm},s=new i.IdTokenEntity;i.CacheManager.toObject(s,o),t[r]=s})),t}static deserializeAccessTokens(e){const t={};return e&&Object.keys(e).map((function(r){const n=e[r],o={homeAccountId:n.home_account_id,environment:n.environment,credentialType:n.credential_type,clientId:n.client_id,secret:n.secret,realm:n.realm,target:n.target,cachedAt:n.cached_at,expiresOn:n.expires_on,extendedExpiresOn:n.extended_expires_on,refreshOn:n.refresh_on,keyId:n.key_id,tokenType:n.token_type,requestedClaims:n.requestedClaims,requestedClaimsHash:n.requestedClaimsHash,userAssertionHash:n.userAssertionHash},s=new i.AccessTokenEntity;i.CacheManager.toObject(s,o),t[r]=s})),t}static deserializeRefreshTokens(e){const t={};return e&&Object.keys(e).map((function(r){const n=e[r],o={homeAccountId:n.home_account_id,environment:n.environment,credentialType:n.credential_type,clientId:n.client_id,secret:n.secret,familyId:n.family_id,target:n.target,realm:n.realm},s=new i.RefreshTokenEntity;i.CacheManager.toObject(s,o),t[r]=s})),t}static deserializeAppMetadata(e){const t={};return e&&Object.keys(e).map((function(r){const n=e[r],o={clientId:n.client_id,environment:n.environment,familyId:n.family_id},s=new i.AppMetadataEntity;i.CacheManager.toObject(s,o),t[r]=s})),t}static deserializeAllCache(e){return{accounts:e.Account?this.deserializeAccounts(e.Account):{},idTokens:e.IdToken?this.deserializeIdTokens(e.IdToken):{},accessTokens:e.AccessToken?this.deserializeAccessTokens(e.AccessToken):{},refreshTokens:e.RefreshToken?this.deserializeRefreshTokens(e.RefreshToken):{},appMetadata:e.AppMetadata?this.deserializeAppMetadata(e.AppMetadata):{}}}}class O{static serializeJSONBlob(e){return JSON.stringify(e)}static serializeAccounts(e){const t={};return Object.keys(e).map((function(r){const n=e[r];t[r]={home_account_id:n.homeAccountId,environment:n.environment,realm:n.realm,local_account_id:n.localAccountId,username:n.username,authority_type:n.authorityType,name:n.name,client_info:n.clientInfo,last_modification_time:n.lastModificationTime,last_modification_app:n.lastModificationApp}})),t}static serializeIdTokens(e){const t={};return Object.keys(e).map((function(r){const n=e[r];t[r]={home_account_id:n.homeAccountId,environment:n.environment,credential_type:n.credentialType,client_id:n.clientId,secret:n.secret,realm:n.realm}})),t}static serializeAccessTokens(e){const t={};return Object.keys(e).map((function(r){const n=e[r];t[r]={home_account_id:n.homeAccountId,environment:n.environment,credential_type:n.credentialType,client_id:n.clientId,secret:n.secret,realm:n.realm,target:n.target,cached_at:n.cachedAt,expires_on:n.expiresOn,extended_expires_on:n.extendedExpiresOn,refresh_on:n.refreshOn,key_id:n.keyId,token_type:n.tokenType,requestedClaims:n.requestedClaims,requestedClaimsHash:n.requestedClaimsHash,userAssertionHash:n.userAssertionHash}})),t}static serializeRefreshTokens(e){const t={};return Object.keys(e).map((function(r){const n=e[r];t[r]={home_account_id:n.homeAccountId,environment:n.environment,credential_type:n.credentialType,client_id:n.clientId,secret:n.secret,family_id:n.familyId,target:n.target,realm:n.realm}})),t}static serializeAppMetadata(e){const t={};return Object.keys(e).map((function(r){const n=e[r];t[r]={client_id:n.clientId,environment:n.environment,family_id:n.familyId}})),t}static serializeAllCache(e){return{Account:this.serializeAccounts(e.accounts),IdToken:this.serializeIdTokens(e.idTokens),AccessToken:this.serializeAccessTokens(e.accessTokens),RefreshToken:this.serializeRefreshTokens(e.refreshTokens),AppMetadata:this.serializeAppMetadata(e.appMetadata)}}}class M extends i.CacheManager{constructor(e,t,r){super(t,r,e),this.cache={},this.changeEmitters=[],this.logger=e}registerChangeEmitter(e){this.changeEmitters.push(e)}emitChange(){this.changeEmitters.forEach(e=>e.call(null))}cacheToInMemoryCache(e){const t={accounts:{},idTokens:{},accessTokens:{},refreshTokens:{},appMetadata:{}};for(const r in e)if(e[r]instanceof i.AccountEntity)t.accounts[r]=e[r];else if(e[r]instanceof i.IdTokenEntity)t.idTokens[r]=e[r];else if(e[r]instanceof i.AccessTokenEntity)t.accessTokens[r]=e[r];else if(e[r]instanceof i.RefreshTokenEntity)t.refreshTokens[r]=e[r];else{if(!(e[r]instanceof i.AppMetadataEntity))continue;t.appMetadata[r]=e[r]}return t}inMemoryCacheToCache(e){let t=this.getCache();return t={...t,...e.accounts,...e.idTokens,...e.accessTokens,...e.refreshTokens,...e.appMetadata},t}getInMemoryCache(){return this.logger.trace("Getting in-memory cache"),this.cacheToInMemoryCache(this.getCache())}setInMemoryCache(e){this.logger.trace("Setting in-memory cache");const t=this.inMemoryCacheToCache(e);this.setCache(t),this.emitChange()}getCache(){return this.logger.trace("Getting cache key-value store"),this.cache}setCache(e){this.logger.trace("Setting cache key value store"),this.cache=e,this.emitChange()}getItem(e){return this.logger.tracePii("Item key: "+e),this.getCache()[e]}setItem(e,t){this.logger.tracePii("Item key: "+e);const r=this.getCache();r[e]=t,this.setCache(r)}getAccountKeys(){const e=this.getInMemoryCache();return Object.keys(e.accounts)}getTokenKeys(){const e=this.getInMemoryCache();return{idToken:Object.keys(e.idTokens),accessToken:Object.keys(e.accessTokens),refreshToken:Object.keys(e.refreshTokens)}}getAccount(e){const t=this.getItem(e);return i.AccountEntity.isAccountEntity(t)?t:null}setAccount(e){const t=e.generateAccountKey();this.setItem(t,e)}getIdTokenCredential(e){const t=this.getItem(e);return i.IdTokenEntity.isIdTokenEntity(t)?t:null}setIdTokenCredential(e){const t=e.generateCredentialKey();this.setItem(t,e)}getAccessTokenCredential(e){const t=this.getItem(e);return i.AccessTokenEntity.isAccessTokenEntity(t)?t:null}setAccessTokenCredential(e){const t=e.generateCredentialKey();this.setItem(t,e)}getRefreshTokenCredential(e){const t=this.getItem(e);return i.RefreshTokenEntity.isRefreshTokenEntity(t)?t:null}setRefreshTokenCredential(e){const t=e.generateCredentialKey();this.setItem(t,e)}getAppMetadata(e){const t=this.getItem(e);return i.AppMetadataEntity.isAppMetadataEntity(e,t)?t:null}setAppMetadata(e){const t=e.generateAppMetadataKey();this.setItem(t,e)}getServerTelemetry(e){const t=this.getItem(e);return t&&i.ServerTelemetryEntity.isServerTelemetryEntity(e,t)?t:null}setServerTelemetry(e,t){this.setItem(e,t)}getAuthorityMetadata(e){const t=this.getItem(e);return t&&i.AuthorityMetadataEntity.isAuthorityMetadataEntity(e,t)?t:null}getAuthorityMetadataKeys(){return this.getKeys().filter(e=>this.isAuthorityMetadata(e))}setAuthorityMetadata(e,t){this.setItem(e,t)}getThrottlingCache(e){const t=this.getItem(e);return t&&i.ThrottlingEntity.isThrottlingEntity(e,t)?t:null}setThrottlingCache(e,t){this.setItem(e,t)}removeItem(e){this.logger.tracePii("Item key: "+e);let t=!1;const r=this.getCache();return r[e]&&(delete r[e],t=!0),t&&(this.setCache(r),this.emitChange()),t}containsKey(e){return this.getKeys().includes(e)}getKeys(){this.logger.trace("Retrieving all cache keys");const e=this.getCache();return[...Object.keys(e)]}async clear(){this.logger.trace("Clearing cache entries created by MSAL"),this.getKeys().forEach(e=>{this.removeItem(e)}),this.emitChange()}static generateInMemoryCache(e){return b.deserializeAllCache(b.deserializeJSONBlob(e))}static generateJsonCache(e){return O.serializeAllCache(e)}updateCredentialCacheKey(e,t){const r=t.generateCredentialKey();if(e!==r){const n=this.getItem(e);if(n)return this.removeItem(e),this.setItem(r,n),this.logger.verbose(`Updated an outdated ${t.credentialType} cache key`),r;this.logger.error(`Attempted to update an outdated ${t.credentialType} cache key but no item matching the outdated key was found in storage`)}return e}}const P={},N={},q={},U={},x={};class z{constructor(e,t,r){this.cacheHasChanged=!1,this.storage=e,this.storage.registerChangeEmitter(this.handleChangeEvent.bind(this)),r&&(this.persistence=r),this.logger=t}hasChanged(){return this.cacheHasChanged}serialize(){this.logger.trace("Serializing in-memory cache");let e=O.serializeAllCache(this.storage.getInMemoryCache());return i.StringUtils.isEmpty(this.cacheSnapshot)?this.logger.trace("No cache snapshot to merge"):(this.logger.trace("Reading cache snapshot from disk"),e=this.mergeState(JSON.parse(this.cacheSnapshot),e)),this.cacheHasChanged=!1,JSON.stringify(e)}deserialize(e){if(this.logger.trace("Deserializing JSON to in-memory cache"),this.cacheSnapshot=e,i.StringUtils.isEmpty(this.cacheSnapshot))this.logger.trace("No cache snapshot to deserialize");else{this.logger.trace("Reading cache snapshot from disk");const e=b.deserializeAllCache(this.overlayDefaults(JSON.parse(this.cacheSnapshot)));this.storage.setInMemoryCache(e)}}getKVStore(){return this.storage.getCache()}async getAllAccounts(){let e;this.logger.trace("getAllAccounts called");try{return this.persistence&&(e=new i.TokenCacheContext(this,!1),await this.persistence.beforeCacheAccess(e)),this.storage.getAllAccounts()}finally{this.persistence&&e&&await this.persistence.afterCacheAccess(e)}}async getAccountByHomeId(e){const t=await this.getAllAccounts();return!i.StringUtils.isEmpty(e)&&t&&t.length&&t.filter(t=>t.homeAccountId===e)[0]||null}async getAccountByLocalId(e){const t=await this.getAllAccounts();return!i.StringUtils.isEmpty(e)&&t&&t.length&&t.filter(t=>t.localAccountId===e)[0]||null}async removeAccount(e){let t;this.logger.trace("removeAccount called");try{this.persistence&&(t=new i.TokenCacheContext(this,!0),await this.persistence.beforeCacheAccess(t)),await this.storage.removeAccount(i.AccountEntity.generateAccountCacheKey(e))}finally{this.persistence&&t&&await this.persistence.afterCacheAccess(t)}}handleChangeEvent(){this.cacheHasChanged=!0}mergeState(e,t){this.logger.trace("Merging in-memory cache with cache snapshot");const r=this.mergeRemovals(e,t);return this.mergeUpdates(r,t)}mergeUpdates(e,t){return Object.keys(t).forEach(r=>{const n=t[r];if(e.hasOwnProperty(r)){const t=null!==n,i="object"==typeof n,o=!Array.isArray(n),s=null!=e[r];t&&i&&o&&s?this.mergeUpdates(e[r],n):e[r]=n}else null!==n&&(e[r]=n)}),e}mergeRemovals(e,t){this.logger.trace("Remove updated entries in cache");const r=e.Account?this.mergeRemovalsDict(e.Account,t.Account):e.Account,n=e.AccessToken?this.mergeRemovalsDict(e.AccessToken,t.AccessToken):e.AccessToken,i=e.RefreshToken?this.mergeRemovalsDict(e.RefreshToken,t.RefreshToken):e.RefreshToken,o=e.IdToken?this.mergeRemovalsDict(e.IdToken,t.IdToken):e.IdToken,s=e.AppMetadata?this.mergeRemovalsDict(e.AppMetadata,t.AppMetadata):e.AppMetadata;return{...e,Account:r,AccessToken:n,RefreshToken:i,IdToken:o,AppMetadata:s}}mergeRemovalsDict(e,t){const r={...e};return Object.keys(e).forEach(e=>{t&&t.hasOwnProperty(e)||delete r[e]}),r}overlayDefaults(e){return this.logger.trace("Overlaying input cache with the default cache"),{Account:{...P,...e.Account},IdToken:{...N,...e.IdToken},AccessToken:{...q,...e.AccessToken},RefreshToken:{...U,...e.RefreshToken},AppMetadata:{...x,...e.AppMetadata}}}}class B extends i.AuthError{constructor(e,t){super(e,t),this.name="NodeAuthError"}static createInvalidLoopbackAddressTypeError(){return new B("invalid_loopback_server_address_type","Loopback server address is not type string. This is unexpected.")}static createUnableToLoadRedirectUrlError(){return new B("unable_to_load_redirectUrl","Loopback server callback was invoked without a url. This is unexpected.")}static createNoAuthCodeInResponseError(){return new B("no_auth_code_in_response","No auth code found in the server response. Please check your network trace to determine what happened.")}static createNoLoopbackServerExistsError(){return new B("no_loopback_server_exists","No loopback server exists yet.")}static createLoopbackServerAlreadyExistsError(){return new B("loopback_server_already_exists","Loopback server already exists. Cannot create another.")}static createLoopbackServerTimeoutError(){return new B("loopback_server_timeout","Timed out waiting for auth code listener to be registered.")}static createStateNotFoundError(){return new B("state_not_found","State not found. Please verify that the request originated from msal.")}}class G{constructor(e){this.config=R(e),this.cryptoProvider=new _,this.logger=new i.Logger(this.config.system.loggerOptions,"@azure/msal-node","1.18.1"),this.storage=new M(this.logger,this.config.auth.clientId,this.cryptoProvider),this.tokenCache=new z(this.storage,this.logger,this.config.cache.cachePlugin)}async getAuthCodeUrl(e){this.logger.info("getAuthCodeUrl called",e.correlationId);const t={...e,...await this.initializeBaseRequest(e),responseMode:e.responseMode||i.ResponseMode.QUERY,authenticationScheme:i.AuthenticationScheme.BEARER},r=await this.buildOauthClientConfiguration(t.authority,t.correlationId,void 0,void 0,e.azureCloudOptions),n=new i.AuthorizationCodeClient(r);return this.logger.verbose("Auth code client created",t.correlationId),n.getAuthCodeUrl(t)}async acquireTokenByCode(e,t){this.logger.info("acquireTokenByCode called"),e.state&&t&&(this.logger.info("acquireTokenByCode - validating state"),this.validateState(e.state,t.state||""),t={...t,state:""});const r={...e,...await this.initializeBaseRequest(e),authenticationScheme:i.AuthenticationScheme.BEARER},n=this.initializeServerTelemetryManager(d.acquireTokenByCode,r.correlationId);try{const o=await this.buildOauthClientConfiguration(r.authority,r.correlationId,n,void 0,e.azureCloudOptions),s=new i.AuthorizationCodeClient(o);return this.logger.verbose("Auth code client created",r.correlationId),s.acquireToken(r,t)}catch(e){throw e instanceof i.AuthError&&e.setCorrelationId(r.correlationId),n.cacheFailedRequest(e),e}}async acquireTokenByRefreshToken(e){this.logger.info("acquireTokenByRefreshToken called",e.correlationId);const t={...e,...await this.initializeBaseRequest(e),authenticationScheme:i.AuthenticationScheme.BEARER},r=this.initializeServerTelemetryManager(d.acquireTokenByRefreshToken,t.correlationId);try{const n=await this.buildOauthClientConfiguration(t.authority,t.correlationId,r,void 0,e.azureCloudOptions),o=new i.RefreshTokenClient(n);return this.logger.verbose("Refresh token client created",t.correlationId),o.acquireToken(t)}catch(e){throw e instanceof i.AuthError&&e.setCorrelationId(t.correlationId),r.cacheFailedRequest(e),e}}async acquireTokenSilent(e){const t={...e,...await this.initializeBaseRequest(e),forceRefresh:e.forceRefresh||!1},r=this.initializeServerTelemetryManager(d.acquireTokenSilent,t.correlationId,t.forceRefresh);try{const n=await this.buildOauthClientConfiguration(t.authority,t.correlationId,r,void 0,e.azureCloudOptions),o=new i.SilentFlowClient(n);return this.logger.verbose("Silent flow client created",t.correlationId),o.acquireToken(t)}catch(e){throw e instanceof i.AuthError&&e.setCorrelationId(t.correlationId),r.cacheFailedRequest(e),e}}async acquireTokenByUsernamePassword(e){this.logger.info("acquireTokenByUsernamePassword called",e.correlationId);const t={...e,...await this.initializeBaseRequest(e)},r=this.initializeServerTelemetryManager(d.acquireTokenByUsernamePassword,t.correlationId);try{const n=await this.buildOauthClientConfiguration(t.authority,t.correlationId,r,void 0,e.azureCloudOptions),o=new i.UsernamePasswordClient(n);return this.logger.verbose("Username password client created",t.correlationId),o.acquireToken(t)}catch(e){throw e instanceof i.AuthError&&e.setCorrelationId(t.correlationId),r.cacheFailedRequest(e),e}}getTokenCache(){return this.logger.info("getTokenCache called"),this.tokenCache}validateState(e,t){if(!e)throw B.createStateNotFoundError();if(e!==t)throw i.ClientAuthError.createStateMismatchError()}getLogger(){return this.logger}setLogger(e){this.logger=e}async buildOauthClientConfiguration(e,t,r,n,o){this.logger.verbose("buildOauthClientConfiguration called",t);const s=o||this.config.auth.azureCloudOptions;this.logger.verbose("building oauth client configuration with the authority: "+e,t);const a=await this.createAuthority(e,n,t,s);return null==r||r.updateRegionDiscoveryMetadata(a.regionDiscoveryMetadata),{authOptions:{clientId:this.config.auth.clientId,authority:a,clientCapabilities:this.config.auth.clientCapabilities},loggerOptions:{logLevel:this.config.system.loggerOptions.logLevel,loggerCallback:this.config.system.loggerOptions.loggerCallback,piiLoggingEnabled:this.config.system.loggerOptions.piiLoggingEnabled,correlationId:t},cacheOptions:{claimsBasedCachingEnabled:this.config.cache.claimsBasedCachingEnabled},cryptoInterface:this.cryptoProvider,networkInterface:this.config.system.networkClient,storageInterface:this.storage,serverTelemetryManager:r,clientCredentials:{clientSecret:this.clientSecret,clientAssertion:this.clientAssertion?this.getClientAssertion(a):void 0},libraryInfo:{sku:"msal.js.node",version:"1.18.1",cpu:process.arch||i.Constants.EMPTY_STRING,os:process.platform||i.Constants.EMPTY_STRING},telemetry:this.config.telemetry,persistencePlugin:this.config.cache.cachePlugin,serializableCache:this.tokenCache}}getClientAssertion(e){return{assertion:this.clientAssertion.getJwt(this.cryptoProvider,this.config.auth.clientId,e.tokenEndpoint),assertionType:"urn:ietf:params:oauth:client-assertion-type:jwt-bearer"}}async initializeBaseRequest(e){return this.logger.verbose("initializeRequestScopes called",e.correlationId),e.authenticationScheme&&e.authenticationScheme===i.AuthenticationScheme.POP&&this.logger.verbose("Authentication Scheme 'pop' is not supported yet, setting Authentication Scheme to 'Bearer' for request",e.correlationId),e.authenticationScheme=i.AuthenticationScheme.BEARER,this.config.cache.claimsBasedCachingEnabled&&e.claims&&!i.StringUtils.isEmptyObj(e.claims)&&(e.requestedClaimsHash=await this.cryptoProvider.hashString(e.claims)),{...e,scopes:[...e&&e.scopes||[],...i.OIDC_DEFAULT_SCOPES],correlationId:e&&e.correlationId||this.cryptoProvider.createNewGuid(),authority:e.authority||this.config.auth.authority}}initializeServerTelemetryManager(e,t,r){return new i.ServerTelemetryManager({clientId:this.config.auth.clientId,correlationId:t,apiId:e,forceRefresh:r||!1},this.storage)}async createAuthority(e,t,r,n){this.logger.verbose("createAuthority called",r);const o=i.Authority.generateAuthority(e,n),s={protocolMode:this.config.auth.protocolMode,knownAuthorities:this.config.auth.knownAuthorities,cloudDiscoveryMetadata:this.config.auth.cloudDiscoveryMetadata,authorityMetadata:this.config.auth.authorityMetadata,azureRegionConfiguration:t,skipAuthorityMetadataCache:this.config.auth.skipAuthorityMetadataCache};return await i.AuthorityFactory.createDiscoveredInstance(o,this.config.system.networkClient,this.storage,s,this.logger)}clearCache(){this.storage.clear()}}class j{async listenForAuthCode(e,t){if(this.server)throw B.createLoopbackServerAlreadyExistsError();const n=new Promise((n,s)=>{this.server=o.createServer(async(o,a)=>{const c=o.url;if(!c)return a.end(t||"Error occurred loading redirectUrl"),void s(B.createUnableToLoadRedirectUrlError());if(c===i.Constants.FORWARD_SLASH)return void a.end(e||"Auth code was successfully acquired. You can close this window now.");const l=i.UrlString.getDeserializedQueryString(c);if(l.code){const e=await this.getRedirectUri();a.writeHead(r.REDIRECT,{location:e}),a.end()}n(l)}),this.server.listen(0)});return await new Promise(e=>{let t=0;const r=setInterval(()=>{if(50!i.OIDC_DEFAULT_SCOPES.includes(e))},o={...e,...n,clientAssertion:t},s={azureRegion:o.azureRegion,environmentRegion:process.env.REGION_NAME},a=this.initializeServerTelemetryManager(d.acquireTokenByClientCredential,o.correlationId,o.skipCache);try{const t=await this.buildOauthClientConfiguration(o.authority,o.correlationId,a,s,e.azureCloudOptions),r=new i.ClientCredentialClient(t,this.appTokenProvider);return this.logger.verbose("Client credential client created",o.correlationId),r.acquireToken(o)}catch(e){throw e instanceof i.AuthError&&e.setCorrelationId(o.correlationId),a.cacheFailedRequest(e),e}}async acquireTokenOnBehalfOf(e){this.logger.info("acquireTokenOnBehalfOf called",e.correlationId);const t={...e,...await this.initializeBaseRequest(e)};try{const r=await this.buildOauthClientConfiguration(t.authority,t.correlationId,void 0,void 0,e.azureCloudOptions),n=new i.OnBehalfOfClient(r);return this.logger.verbose("On behalf of client created",t.correlationId),n.acquireToken(t)}catch(e){throw e instanceof i.AuthError&&e.setCorrelationId(t.correlationId),e}}setClientCredential(e){const t=!i.StringUtils.isEmpty(e.auth.clientSecret),r=!i.StringUtils.isEmpty(e.auth.clientAssertion),n=e.auth.clientCertificate||{thumbprint:i.Constants.EMPTY_STRING,privateKey:i.Constants.EMPTY_STRING},o=!i.StringUtils.isEmpty(n.thumbprint)||!i.StringUtils.isEmpty(n.privateKey);if(!this.appTokenProvider){if(t&&r||r&&o||t&&o)throw i.ClientAuthError.createInvalidCredentialError();if(e.auth.clientSecret)this.clientSecret=e.auth.clientSecret;else if(e.auth.clientAssertion)this.clientAssertion=D.fromAssertion(e.auth.clientAssertion);else{if(!o)throw i.ClientAuthError.createInvalidCredentialError();var s;this.clientAssertion=D.fromCertificate(n.thumbprint,n.privateKey,null==(s=e.auth.clientCertificate)?void 0:s.x5c)}}}},exports.CryptoProvider=_,exports.DistributedCachePlugin=class{constructor(e,t){this.client=e,this.partitionManager=t}async beforeCacheAccess(e){const t=await this.partitionManager.getKey(),r=await this.client.get(t);e.tokenCache.deserialize(r)}async afterCacheAccess(e){if(e.cacheHasChanged){const t=e.tokenCache.getKVStore(),r=Object.values(t).filter(e=>i.AccountEntity.isAccountEntity(e));if(r.length>0){const t=r[0],n=await this.partitionManager.extractKey(t);await this.client.set(n,e.tokenCache.serialize())}}}},exports.NodeStorage=M,exports.PublicClientApplication=class extends G{constructor(e){super(e),this.config.broker.nativeBrokerPlugin&&(this.config.broker.nativeBrokerPlugin.isBrokerAvailable?(this.nativeBrokerPlugin=this.config.broker.nativeBrokerPlugin,this.nativeBrokerPlugin.setLogger(this.config.system.loggerOptions)):this.logger.warning("NativeBroker implementation was provided but the broker is unavailable."))}async acquireTokenByDeviceCode(e){this.logger.info("acquireTokenByDeviceCode called",e.correlationId);const t=Object.assign(e,await this.initializeBaseRequest(e)),r=this.initializeServerTelemetryManager(d.acquireTokenByDeviceCode,t.correlationId);try{const n=await this.buildOauthClientConfiguration(t.authority,t.correlationId,r,void 0,e.azureCloudOptions),o=new i.DeviceCodeClient(n);return this.logger.verbose("Device code client created",t.correlationId),o.acquireToken(t)}catch(e){throw e instanceof i.AuthError&&e.setCorrelationId(t.correlationId),r.cacheFailedRequest(e),e}}async acquireTokenInteractive(e){const t=e.correlationId||this.cryptoProvider.createNewGuid();this.logger.trace("acquireTokenInteractive called",t);const{openBrowser:r,successTemplate:n,errorTemplate:o,windowHandle:s,loopbackClient:a,...c}=e;if(this.nativeBrokerPlugin){var l;const r={...c,clientId:this.config.auth.clientId,scopes:e.scopes||i.OIDC_DEFAULT_SCOPES,redirectUri:"http://localhost",authority:e.authority||this.config.auth.authority,correlationId:t,extraParameters:{...c.extraQueryParameters,...c.tokenQueryParameters},accountId:null==(l=c.account)?void 0:l.nativeAccountId};return this.nativeBrokerPlugin.acquireTokenInteractive(r,s)}const{verifier:h,challenge:u}=await this.cryptoProvider.generatePkceCodes(),d=a||new j,g=d.listenForAuthCode(n,o),p=d.getRedirectUri(),y={...c,correlationId:t,scopes:e.scopes||i.OIDC_DEFAULT_SCOPES,redirectUri:p,responseMode:i.ResponseMode.QUERY,codeChallenge:u,codeChallengeMethod:i.CodeChallengeMethodValues.S256},m=await this.getAuthCodeUrl(y);await r(m);const C=await g.finally(()=>{d.closeServer()});if(C.error)throw new i.ServerError(C.error,C.error_description,C.suberror);if(!C.code)throw B.createNoAuthCodeInResponseError();const f={code:C.code,codeVerifier:h,clientInfo:C.client_info||i.Constants.EMPTY_STRING,...y};return this.acquireTokenByCode(f)}async acquireTokenSilent(e){const t=e.correlationId||this.cryptoProvider.createNewGuid();if(this.logger.trace("acquireTokenSilent called",t),this.nativeBrokerPlugin){const r={...e,clientId:this.config.auth.clientId,scopes:e.scopes||i.OIDC_DEFAULT_SCOPES,redirectUri:"http://localhost",authority:e.authority||this.config.auth.authority,correlationId:t,extraParameters:e.tokenQueryParameters,accountId:e.account.nativeAccountId,forceRefresh:e.forceRefresh||!1};return this.nativeBrokerPlugin.acquireTokenSilent(r)}return super.acquireTokenSilent(e)}async signOut(e){if(this.nativeBrokerPlugin&&e.account.nativeAccountId){const t={clientId:this.config.auth.clientId,accountId:e.account.nativeAccountId,correlationId:e.correlationId||this.cryptoProvider.createNewGuid()};await this.nativeBrokerPlugin.signOut(t)}await this.getTokenCache().removeAccount(e.account)}async getAllAccounts(){if(this.nativeBrokerPlugin){const e=this.cryptoProvider.createNewGuid();return this.nativeBrokerPlugin.getAllAccounts(this.config.auth.clientId,e)}return this.getTokenCache().getAllAccounts()}},exports.TokenCache=z,exports.buildAppConfiguration=R,exports.version="1.18.1"; +//# sourceMappingURL=msal-node.cjs.production.min.js.map + + +/***/ }), + +/***/ 1040: +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +function once(emitter, name, { signal } = {}) { + return new Promise((resolve, reject) => { + function cleanup() { + signal === null || signal === void 0 ? void 0 : signal.removeEventListener('abort', cleanup); + emitter.removeListener(name, onEvent); + emitter.removeListener('error', onError); + } + function onEvent(...args) { + cleanup(); + resolve(args); + } + function onError(err) { + cleanup(); + reject(err); + } + signal === null || signal === void 0 ? void 0 : signal.addEventListener('abort', cleanup); + emitter.on(name, onEvent); + emitter.on('error', onError); + }); +} +exports["default"] = once; +//# sourceMappingURL=index.js.map + +/***/ }), + +/***/ 9690: +/***/ (function(module, __unused_webpack_exports, __nccwpck_require__) { + +"use strict"; + +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +const events_1 = __nccwpck_require__(2361); +const debug_1 = __importDefault(__nccwpck_require__(8237)); +const promisify_1 = __importDefault(__nccwpck_require__(6570)); +const debug = debug_1.default('agent-base'); +function isAgent(v) { + return Boolean(v) && typeof v.addRequest === 'function'; +} +function isSecureEndpoint() { + const { stack } = new Error(); + if (typeof stack !== 'string') + return false; + return stack.split('\n').some(l => l.indexOf('(https.js:') !== -1 || l.indexOf('node:https:') !== -1); +} +function createAgent(callback, opts) { + return new createAgent.Agent(callback, opts); +} +(function (createAgent) { + /** + * Base `http.Agent` implementation. + * No pooling/keep-alive is implemented by default. + * + * @param {Function} callback + * @api public + */ + class Agent extends events_1.EventEmitter { + constructor(callback, _opts) { + super(); + let opts = _opts; + if (typeof callback === 'function') { + this.callback = callback; + } + else if (callback) { + opts = callback; + } + // Timeout for the socket to be returned from the callback + this.timeout = null; + if (opts && typeof opts.timeout === 'number') { + this.timeout = opts.timeout; + } + // These aren't actually used by `agent-base`, but are required + // for the TypeScript definition files in `@types/node` :/ + this.maxFreeSockets = 1; + this.maxSockets = 1; + this.maxTotalSockets = Infinity; + this.sockets = {}; + this.freeSockets = {}; + this.requests = {}; + this.options = {}; + } + get defaultPort() { + if (typeof this.explicitDefaultPort === 'number') { + return this.explicitDefaultPort; + } + return isSecureEndpoint() ? 443 : 80; + } + set defaultPort(v) { + this.explicitDefaultPort = v; + } + get protocol() { + if (typeof this.explicitProtocol === 'string') { + return this.explicitProtocol; + } + return isSecureEndpoint() ? 'https:' : 'http:'; + } + set protocol(v) { + this.explicitProtocol = v; + } + callback(req, opts, fn) { + throw new Error('"agent-base" has no default implementation, you must subclass and override `callback()`'); + } + /** + * Called by node-core's "_http_client.js" module when creating + * a new HTTP request with this Agent instance. + * + * @api public + */ + addRequest(req, _opts) { + const opts = Object.assign({}, _opts); + if (typeof opts.secureEndpoint !== 'boolean') { + opts.secureEndpoint = isSecureEndpoint(); + } + if (opts.host == null) { + opts.host = 'localhost'; + } + if (opts.port == null) { + opts.port = opts.secureEndpoint ? 443 : 80; + } + if (opts.protocol == null) { + opts.protocol = opts.secureEndpoint ? 'https:' : 'http:'; + } + if (opts.host && opts.path) { + // If both a `host` and `path` are specified then it's most + // likely the result of a `url.parse()` call... we need to + // remove the `path` portion so that `net.connect()` doesn't + // attempt to open that as a unix socket file. + delete opts.path; + } + delete opts.agent; + delete opts.hostname; + delete opts._defaultAgent; + delete opts.defaultPort; + delete opts.createConnection; + // Hint to use "Connection: close" + // XXX: non-documented `http` module API :( + req._last = true; + req.shouldKeepAlive = false; + let timedOut = false; + let timeoutId = null; + const timeoutMs = opts.timeout || this.timeout; + const onerror = (err) => { + if (req._hadError) + return; + req.emit('error', err); + // For Safety. Some additional errors might fire later on + // and we need to make sure we don't double-fire the error event. + req._hadError = true; + }; + const ontimeout = () => { + timeoutId = null; + timedOut = true; + const err = new Error(`A "socket" was not created for HTTP request before ${timeoutMs}ms`); + err.code = 'ETIMEOUT'; + onerror(err); + }; + const callbackError = (err) => { + if (timedOut) + return; + if (timeoutId !== null) { + clearTimeout(timeoutId); + timeoutId = null; + } + onerror(err); + }; + const onsocket = (socket) => { + if (timedOut) + return; + if (timeoutId != null) { + clearTimeout(timeoutId); + timeoutId = null; + } + if (isAgent(socket)) { + // `socket` is actually an `http.Agent` instance, so + // relinquish responsibility for this `req` to the Agent + // from here on + debug('Callback returned another Agent instance %o', socket.constructor.name); + socket.addRequest(req, opts); + return; + } + if (socket) { + socket.once('free', () => { + this.freeSocket(socket, opts); + }); + req.onSocket(socket); + return; + } + const err = new Error(`no Duplex stream was returned to agent-base for \`${req.method} ${req.path}\``); + onerror(err); + }; + if (typeof this.callback !== 'function') { + onerror(new Error('`callback` is not defined')); + return; + } + if (!this.promisifiedCallback) { + if (this.callback.length >= 3) { + debug('Converting legacy callback function to promise'); + this.promisifiedCallback = promisify_1.default(this.callback); + } + else { + this.promisifiedCallback = this.callback; + } + } + if (typeof timeoutMs === 'number' && timeoutMs > 0) { + timeoutId = setTimeout(ontimeout, timeoutMs); + } + if ('port' in opts && typeof opts.port !== 'number') { + opts.port = Number(opts.port); + } + try { + debug('Resolving socket for %o request: %o', opts.protocol, `${req.method} ${req.path}`); + Promise.resolve(this.promisifiedCallback(req, opts)).then(onsocket, callbackError); + } + catch (err) { + Promise.reject(err).catch(callbackError); + } + } + freeSocket(socket, opts) { + debug('Freeing socket %o %o', socket.constructor.name, opts); + socket.destroy(); + } + destroy() { + debug('Destroying agent %o', this.constructor.name); + } + } + createAgent.Agent = Agent; + // So that `instanceof` works correctly + createAgent.prototype = createAgent.Agent.prototype; +})(createAgent || (createAgent = {})); +module.exports = createAgent; +//# sourceMappingURL=index.js.map + +/***/ }), + +/***/ 6570: +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +function promisify(fn) { + return function (req, opts) { + return new Promise((resolve, reject) => { + fn.call(this, req, opts, (err, rtn) => { + if (err) { + reject(err); + } + else { + resolve(rtn); + } + }); + }); + }; +} +exports["default"] = promisify; +//# sourceMappingURL=promisify.js.map + +/***/ }), + +/***/ 4812: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +module.exports = +{ + parallel : __nccwpck_require__(8210), + serial : __nccwpck_require__(445), + serialOrdered : __nccwpck_require__(3578) +}; + + +/***/ }), + +/***/ 1700: +/***/ ((module) => { + +// API +module.exports = abort; + +/** + * Aborts leftover active jobs + * + * @param {object} state - current state object + */ +function abort(state) +{ + Object.keys(state.jobs).forEach(clean.bind(state)); + + // reset leftover jobs + state.jobs = {}; +} + +/** + * Cleans up leftover job by invoking abort function for the provided job id + * + * @this state + * @param {string|number} key - job id to abort + */ +function clean(key) +{ + if (typeof this.jobs[key] == 'function') + { + this.jobs[key](); + } +} + + +/***/ }), + +/***/ 2794: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +var defer = __nccwpck_require__(5295); + +// API +module.exports = async; + +/** + * Runs provided callback asynchronously + * even if callback itself is not + * + * @param {function} callback - callback to invoke + * @returns {function} - augmented callback + */ +function async(callback) +{ + var isAsync = false; + + // check if async happened + defer(function() { isAsync = true; }); + + return function async_callback(err, result) + { + if (isAsync) + { + callback(err, result); + } + else + { + defer(function nextTick_callback() + { + callback(err, result); + }); + } + }; +} + + +/***/ }), + +/***/ 5295: +/***/ ((module) => { + +module.exports = defer; + +/** + * Runs provided function on next iteration of the event loop + * + * @param {function} fn - function to run + */ +function defer(fn) +{ + var nextTick = typeof setImmediate == 'function' + ? setImmediate + : ( + typeof process == 'object' && typeof process.nextTick == 'function' + ? process.nextTick + : null + ); + + if (nextTick) + { + nextTick(fn); + } + else + { + setTimeout(fn, 0); + } +} + + +/***/ }), + +/***/ 9023: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +var async = __nccwpck_require__(2794) + , abort = __nccwpck_require__(1700) + ; + +// API +module.exports = iterate; + +/** + * Iterates over each job object + * + * @param {array|object} list - array or object (named list) to iterate over + * @param {function} iterator - iterator to run + * @param {object} state - current job status + * @param {function} callback - invoked when all elements processed + */ +function iterate(list, iterator, state, callback) +{ + // store current index + var key = state['keyedList'] ? state['keyedList'][state.index] : state.index; + + state.jobs[key] = runJob(iterator, key, list[key], function(error, output) + { + // don't repeat yourself + // skip secondary callbacks + if (!(key in state.jobs)) + { + return; + } + + // clean up jobs + delete state.jobs[key]; + + if (error) + { + // don't process rest of the results + // stop still active jobs + // and reset the list + abort(state); + } + else + { + state.results[key] = output; + } + + // return salvaged results + callback(error, state.results); + }); +} + +/** + * Runs iterator over provided job element + * + * @param {function} iterator - iterator to invoke + * @param {string|number} key - key/index of the element in the list of jobs + * @param {mixed} item - job description + * @param {function} callback - invoked after iterator is done with the job + * @returns {function|mixed} - job abort function or something else + */ +function runJob(iterator, key, item, callback) +{ + var aborter; + + // allow shortcut if iterator expects only two arguments + if (iterator.length == 2) + { + aborter = iterator(item, async(callback)); + } + // otherwise go with full three arguments + else + { + aborter = iterator(item, key, async(callback)); + } + + return aborter; +} + + +/***/ }), + +/***/ 2474: +/***/ ((module) => { + +// API +module.exports = state; + +/** + * Creates initial state object + * for iteration over list + * + * @param {array|object} list - list to iterate over + * @param {function|null} sortMethod - function to use for keys sort, + * or `null` to keep them as is + * @returns {object} - initial state object + */ +function state(list, sortMethod) +{ + var isNamedList = !Array.isArray(list) + , initState = + { + index : 0, + keyedList: isNamedList || sortMethod ? Object.keys(list) : null, + jobs : {}, + results : isNamedList ? {} : [], + size : isNamedList ? Object.keys(list).length : list.length + } + ; + + if (sortMethod) + { + // sort array keys based on it's values + // sort object's keys just on own merit + initState.keyedList.sort(isNamedList ? sortMethod : function(a, b) + { + return sortMethod(list[a], list[b]); + }); + } + + return initState; +} + + +/***/ }), + +/***/ 7942: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +var abort = __nccwpck_require__(1700) + , async = __nccwpck_require__(2794) + ; + +// API +module.exports = terminator; + +/** + * Terminates jobs in the attached state context + * + * @this AsyncKitState# + * @param {function} callback - final callback to invoke after termination + */ +function terminator(callback) +{ + if (!Object.keys(this.jobs).length) + { + return; + } + + // fast forward iteration index + this.index = this.size; + + // abort jobs + abort(this); + + // send back results we have so far + async(callback)(null, this.results); +} + + +/***/ }), + +/***/ 8210: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +var iterate = __nccwpck_require__(9023) + , initState = __nccwpck_require__(2474) + , terminator = __nccwpck_require__(7942) + ; + +// Public API +module.exports = parallel; + +/** + * Runs iterator over provided array elements in parallel + * + * @param {array|object} list - array or object (named list) to iterate over + * @param {function} iterator - iterator to run + * @param {function} callback - invoked when all elements processed + * @returns {function} - jobs terminator + */ +function parallel(list, iterator, callback) +{ + var state = initState(list); + + while (state.index < (state['keyedList'] || list).length) + { + iterate(list, iterator, state, function(error, result) + { + if (error) + { + callback(error, result); + return; + } + + // looks like it's the last one + if (Object.keys(state.jobs).length === 0) + { + callback(null, state.results); + return; + } + }); + + state.index++; + } + + return terminator.bind(state, callback); +} + + +/***/ }), + +/***/ 445: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +var serialOrdered = __nccwpck_require__(3578); + +// Public API +module.exports = serial; + +/** + * Runs iterator over provided array elements in series + * + * @param {array|object} list - array or object (named list) to iterate over + * @param {function} iterator - iterator to run + * @param {function} callback - invoked when all elements processed + * @returns {function} - jobs terminator + */ +function serial(list, iterator, callback) +{ + return serialOrdered(list, iterator, null, callback); +} + + +/***/ }), + +/***/ 3578: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +var iterate = __nccwpck_require__(9023) + , initState = __nccwpck_require__(2474) + , terminator = __nccwpck_require__(7942) + ; + +// Public API +module.exports = serialOrdered; +// sorting helpers +module.exports.ascending = ascending; +module.exports.descending = descending; + +/** + * Runs iterator over provided sorted array elements in series + * + * @param {array|object} list - array or object (named list) to iterate over + * @param {function} iterator - iterator to run + * @param {function} sortMethod - custom sort function + * @param {function} callback - invoked when all elements processed + * @returns {function} - jobs terminator + */ +function serialOrdered(list, iterator, sortMethod, callback) +{ + var state = initState(list, sortMethod); + + iterate(list, iterator, state, function iteratorHandler(error, result) + { + if (error) + { + callback(error, result); + return; + } + + state.index++; + + // are we there yet? + if (state.index < (state['keyedList'] || list).length) + { + iterate(list, iterator, state, iteratorHandler); + return; + } + + // done here + callback(null, state.results); + }); + + return terminator.bind(state, callback); +} + +/* + * -- Sort methods + */ + +/** + * sort helper to sort array elements in ascending order + * + * @param {mixed} a - an item to compare + * @param {mixed} b - an item to compare + * @returns {number} - comparison result + */ +function ascending(a, b) +{ + return a < b ? -1 : a > b ? 1 : 0; +} + +/** + * sort helper to sort array elements in descending order + * + * @param {mixed} a - an item to compare + * @param {mixed} b - an item to compare + * @returns {number} - comparison result + */ +function descending(a, b) +{ + return -1 * ascending(a, b); +} + + +/***/ }), + +/***/ 837: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __exportStar = (this && this.__exportStar) || function(m, exports) { + for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +__exportStar(__nccwpck_require__(6837), exports); +__exportStar(__nccwpck_require__(9300), exports); +//# sourceMappingURL=index.js.map + +/***/ }), + +/***/ 6837: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.Bicep = void 0; +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. +const os_1 = __importDefault(__nccwpck_require__(2037)); +const install_1 = __nccwpck_require__(1599); +const jsonrpc_1 = __nccwpck_require__(7957); +/** + * Helper class to install and interact with the Bicep CLI. + */ +class Bicep { + constructor(connection) { + this.connection = connection; + } + /** + * Initializes the Bicep library with a connection to the Bicep CLI. + * + * @param bicepPath The path to the Bicep CLI. You can point this to an existing install, or use `Bicep.install()` to obtain this path. + * @returns A `Bicep` instance. + */ + static async initialize(bicepPath) { + const connection = await (0, jsonrpc_1.openConnection)(bicepPath); + return new Bicep(connection); + } + /** + * Returns the Bicep CLI download URL. + * + * @param version The version of the Bicep CLI to download. Defaults to the latest version. + * @param platform The platform to download for. Defaults to `os.platform()`. + * @param arch The architecture to download for. Defaults to `os.arch()`. + * @returns The download URL. + */ + static async getDownloadUrl(version, platform, arch) { + platform !== null && platform !== void 0 ? platform : (platform = os_1.default.platform()); + arch !== null && arch !== void 0 ? arch : (arch = os_1.default.arch()); + return await (0, install_1.getBicepCliDownloadUrl)(platform, arch, version); + } + /** + * Downloads the Bicep CLI to the specified path. + * + * @param basePath The file system path to download the Bicep CLI to. This path must already exist. + * @param version The version of the Bicep CLI to download. Defaults to the latest version. + * @param platform The platform to download for. Defaults to `os.platform()`. + * @param arch The architecture to download for. Defaults to `os.arch()`. + * @returns The path to the Bicep CLI. + */ + static async install(basePath, version, platform, arch) { + platform !== null && platform !== void 0 ? platform : (platform = os_1.default.platform()); + arch !== null && arch !== void 0 ? arch : (arch = os_1.default.arch()); + return await (0, install_1.installBicepCliWithArch)(basePath, platform, arch, version); + } + /** + * Compiles a Bicep file. + * + * @param request The compilation request. + * @returns The compilation response. + */ + async compile(request) { + return await this.connection.sendRequest(jsonrpc_1.compileRequestType, request); + } + /** + * Validates a Bicep file against Azure. + * + * @param request The validate request. + * @returns The validate response. + */ + async validate(request) { + return await this.connection.sendRequest(jsonrpc_1.validateRequestType, request); + } + /** + * Disposes of the connection to the Bicep CLI. This MUST be called after usage to avoid leaving the process running. + */ + dispose() { + this.connection.dispose(); + } +} +exports.Bicep = Bicep; +//# sourceMappingURL=bicep.js.map + +/***/ }), + +/***/ 1599: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.installBicepCliWithArch = exports.getBicepCliDownloadUrl = void 0; +const path_1 = __importDefault(__nccwpck_require__(1017)); +const promises_1 = __importDefault(__nccwpck_require__(3292)); +const node_fetch_1 = __importDefault(__nccwpck_require__(467)); +const downloadBaseUrl = 'https://downloads.bicep.azure.com'; +const latestReleaseUrl = `${downloadBaseUrl}/releases/latest`; +const downloadUrl = (tag, artifact) => `${downloadBaseUrl}/${tag}/${artifact}`; +async function getLatestRelease() { + const response = await (0, node_fetch_1.default)(latestReleaseUrl); + if (!response.ok) { + throw `Failed to find latest release of Bicep CLI. Status code: ${response.status}`; + } + const body = await response.json(); + return body['tag_name']; +} +function getDownloadUrlForTag(osPlat, osArch, tagName) { + switch (`${osPlat}_${osArch}`.toLowerCase()) { + case 'win32_x64': return downloadUrl(tagName, 'bicep-win-x64.exe'); + case 'win32_arm64': return downloadUrl(tagName, 'bicep-win-arm64.exe'); + case 'linux_x64': return downloadUrl(tagName, 'bicep-linux-x64'); + case 'linux_arm64': return downloadUrl(tagName, 'bicep-linux-arm64'); + case 'darwin_x64': return downloadUrl(tagName, 'bicep-osx-x64'); + case 'darwin_arm64': return downloadUrl(tagName, 'bicep-osx-arm64'); + default: throw `Bicep CLI is not available for platform ${osPlat} and architecture ${osArch}`; + } +} +async function getBicepCliDownloadUrl(platform, arch, version) { + const tagName = version ? `v${version}` : await getLatestRelease(); + return getDownloadUrlForTag(platform, arch, tagName); +} +exports.getBicepCliDownloadUrl = getBicepCliDownloadUrl; +async function installBicepCliWithArch(basePath, platform, arch, version) { + const targetFile = platform === 'win32' ? 'bicep.exe' : 'bicep'; + const downloadUrl = await getBicepCliDownloadUrl(platform, arch, version); + const response = await (0, node_fetch_1.default)(downloadUrl); + if (!response.ok) { + throw `Failed to download Bicep CLI. Status code: ${response.status}`; + } + const buffer = await response.arrayBuffer(); + const toolPath = path_1.default.join(basePath, targetFile); + await promises_1.default.writeFile(toolPath, Buffer.from(buffer)); + await promises_1.default.chmod(toolPath, 0o755); + return toolPath; +} +exports.installBicepCliWithArch = installBicepCliWithArch; +//# sourceMappingURL=install.js.map + +/***/ }), + +/***/ 7957: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.openConnection = exports.validateRequestType = exports.compileRequestType = void 0; +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. +const path_1 = __importDefault(__nccwpck_require__(1017)); +const os_1 = __importDefault(__nccwpck_require__(2037)); +const child_process_1 = __nccwpck_require__(2081); +const crypto_1 = __nccwpck_require__(6113); +const net_1 = __nccwpck_require__(1808); +const node_1 = __nccwpck_require__(9827); +exports.compileRequestType = new node_1.RequestType("bicep/compile"); +exports.validateRequestType = new node_1.RequestType("bicep/validate"); +function tryGetVersionNumberError(bicepPath) { + const result = (0, child_process_1.spawnSync)(bicepPath, ["--version"], { encoding: "utf-8" }); + if (result.status !== 0) { + return `Failed to obtain valid Bicep version from '${bicepPath} --version'`; + } + const versionMatch = result.stdout.match(/Bicep CLI version ([^ ]+) /); + if (!versionMatch) { + return `Failed to obtain valid Bicep version from '${bicepPath} --version'`; + } + const minimumVersion = '0.24.24'; + const actualVersion = versionMatch[1]; + const compareResult = actualVersion.localeCompare(minimumVersion, undefined, { numeric: true, sensitivity: 'base' }); + if (compareResult < 0) { + return `A minimum Bicep version of ${minimumVersion} is required. Detected version ${actualVersion} from '${bicepPath} --version'`; + } + return; +} +function generateRandomPipeName() { + const randomSuffix = (0, crypto_1.randomBytes)(21).toString("hex"); + if (process.platform === "win32") { + return `\\\\.\\pipe\\bicep-${randomSuffix}-sock`; + } + return path_1.default.join(os_1.default.tmpdir(), `bicep-${randomSuffix}.sock`); +} +function connectClientPipe(pipeName, process) { + return new Promise((resolve, reject) => { + const onProcessExit = () => { + server.close(); + reject(); + }; + const server = (0, net_1.createServer)(socket => { + process.removeListener('exit', onProcessExit); + server.close(); + resolve([ + new node_1.SocketMessageReader(socket, 'utf-8'), + new node_1.SocketMessageWriter(socket, 'utf-8') + ]); + }); + process.on('exit', onProcessExit); + server.on('error', reject); + server.listen(pipeName, () => server.removeListener('error', reject)); + }); +} +async function openConnection(bicepPath) { + const pipePath = generateRandomPipeName(); + const process = (0, child_process_1.spawn)(bicepPath, ["jsonrpc", "--pipe", pipePath]); + let stderr = ''; + process.stderr.on("data", (x) => stderr += x.toString()); + const processExitedEarly = new Promise((_, reject) => process.on("exit", () => { + const error = tryGetVersionNumberError(bicepPath); + if (error) { + reject(error); + } + else { + reject(`Failed to invoke '${bicepPath} jsonrpc'. Error: ${stderr}`); + } + })); + const transportConnected = connectClientPipe(pipePath, process); + const result = await Promise.race([ + transportConnected, + processExitedEarly, + ]); + const [reader, writer] = result; + const connection = (0, node_1.createMessageConnection)(reader, writer, console); + connection.onDispose(() => process.kill()); + process.on("exit", () => connection.dispose()); + connection.listen(); + return connection; +} +exports.openConnection = openConnection; +//# sourceMappingURL=jsonrpc.js.map + +/***/ }), + +/***/ 9300: +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +//# sourceMappingURL=types.js.map + +/***/ }), + +/***/ 9239: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; +/*jshint node:true */ + +var Buffer = (__nccwpck_require__(4300).Buffer); // browserify +var SlowBuffer = (__nccwpck_require__(4300).SlowBuffer); + +module.exports = bufferEq; + +function bufferEq(a, b) { + + // shortcutting on type is necessary for correctness + if (!Buffer.isBuffer(a) || !Buffer.isBuffer(b)) { + return false; + } + + // buffer sizes should be well-known information, so despite this + // shortcutting, it doesn't leak any information about the *contents* of the + // buffers. + if (a.length !== b.length) { + return false; + } + + var c = 0; + for (var i = 0; i < a.length; i++) { + /*jshint bitwise:false */ + c |= a[i] ^ b[i]; // XOR + } + return c === 0; +} + +bufferEq.install = function() { + Buffer.prototype.equal = SlowBuffer.prototype.equal = function equal(that) { + return bufferEq(this, that); + }; +}; + +var origBufEqual = Buffer.prototype.equal; +var origSlowBufEqual = SlowBuffer.prototype.equal; +bufferEq.restore = function() { + Buffer.prototype.equal = origBufEqual; + SlowBuffer.prototype.equal = origSlowBufEqual; +}; + + +/***/ }), + +/***/ 5443: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +var util = __nccwpck_require__(3837); +var Stream = (__nccwpck_require__(2781).Stream); +var DelayedStream = __nccwpck_require__(8611); + +module.exports = CombinedStream; +function CombinedStream() { + this.writable = false; + this.readable = true; + this.dataSize = 0; + this.maxDataSize = 2 * 1024 * 1024; + this.pauseStreams = true; + + this._released = false; + this._streams = []; + this._currentStream = null; + this._insideLoop = false; + this._pendingNext = false; +} +util.inherits(CombinedStream, Stream); + +CombinedStream.create = function(options) { + var combinedStream = new this(); + + options = options || {}; + for (var option in options) { + combinedStream[option] = options[option]; + } + + return combinedStream; +}; + +CombinedStream.isStreamLike = function(stream) { + return (typeof stream !== 'function') + && (typeof stream !== 'string') + && (typeof stream !== 'boolean') + && (typeof stream !== 'number') + && (!Buffer.isBuffer(stream)); +}; + +CombinedStream.prototype.append = function(stream) { + var isStreamLike = CombinedStream.isStreamLike(stream); + + if (isStreamLike) { + if (!(stream instanceof DelayedStream)) { + var newStream = DelayedStream.create(stream, { + maxDataSize: Infinity, + pauseStream: this.pauseStreams, + }); + stream.on('data', this._checkDataSize.bind(this)); + stream = newStream; + } + + this._handleErrors(stream); + + if (this.pauseStreams) { + stream.pause(); + } + } + + this._streams.push(stream); + return this; +}; + +CombinedStream.prototype.pipe = function(dest, options) { + Stream.prototype.pipe.call(this, dest, options); + this.resume(); + return dest; +}; + +CombinedStream.prototype._getNext = function() { + this._currentStream = null; + + if (this._insideLoop) { + this._pendingNext = true; + return; // defer call + } + + this._insideLoop = true; + try { + do { + this._pendingNext = false; + this._realGetNext(); + } while (this._pendingNext); + } finally { + this._insideLoop = false; + } +}; + +CombinedStream.prototype._realGetNext = function() { + var stream = this._streams.shift(); + + + if (typeof stream == 'undefined') { + this.end(); + return; + } + + if (typeof stream !== 'function') { + this._pipeNext(stream); + return; + } + + var getStream = stream; + getStream(function(stream) { + var isStreamLike = CombinedStream.isStreamLike(stream); + if (isStreamLike) { + stream.on('data', this._checkDataSize.bind(this)); + this._handleErrors(stream); + } + + this._pipeNext(stream); + }.bind(this)); +}; + +CombinedStream.prototype._pipeNext = function(stream) { + this._currentStream = stream; + + var isStreamLike = CombinedStream.isStreamLike(stream); + if (isStreamLike) { + stream.on('end', this._getNext.bind(this)); + stream.pipe(this, {end: false}); + return; + } + + var value = stream; + this.write(value); + this._getNext(); +}; + +CombinedStream.prototype._handleErrors = function(stream) { + var self = this; + stream.on('error', function(err) { + self._emitError(err); + }); +}; + +CombinedStream.prototype.write = function(data) { + this.emit('data', data); +}; + +CombinedStream.prototype.pause = function() { + if (!this.pauseStreams) { + return; + } + + if(this.pauseStreams && this._currentStream && typeof(this._currentStream.pause) == 'function') this._currentStream.pause(); + this.emit('pause'); +}; + +CombinedStream.prototype.resume = function() { + if (!this._released) { + this._released = true; + this.writable = true; + this._getNext(); + } + + if(this.pauseStreams && this._currentStream && typeof(this._currentStream.resume) == 'function') this._currentStream.resume(); + this.emit('resume'); +}; + +CombinedStream.prototype.end = function() { + this._reset(); + this.emit('end'); +}; + +CombinedStream.prototype.destroy = function() { + this._reset(); + this.emit('close'); +}; + +CombinedStream.prototype._reset = function() { + this.writable = false; + this._streams = []; + this._currentStream = null; +}; + +CombinedStream.prototype._checkDataSize = function() { + this._updateDataSize(); + if (this.dataSize <= this.maxDataSize) { + return; + } + + var message = + 'DelayedStream#maxDataSize of ' + this.maxDataSize + ' bytes exceeded.'; + this._emitError(new Error(message)); +}; + +CombinedStream.prototype._updateDataSize = function() { + this.dataSize = 0; + + var self = this; + this._streams.forEach(function(stream) { + if (!stream.dataSize) { + return; + } + + self.dataSize += stream.dataSize; + }); + + if (this._currentStream && this._currentStream.dataSize) { + this.dataSize += this._currentStream.dataSize; + } +}; + +CombinedStream.prototype._emitError = function(err) { + this._reset(); + this.emit('error', err); +}; + + +/***/ }), + +/***/ 8222: +/***/ ((module, exports, __nccwpck_require__) => { + +/* eslint-env browser */ + +/** + * This is the web browser implementation of `debug()`. + */ + +exports.formatArgs = formatArgs; +exports.save = save; +exports.load = load; +exports.useColors = useColors; +exports.storage = localstorage(); +exports.destroy = (() => { + let warned = false; + + return () => { + if (!warned) { + warned = true; + console.warn('Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`.'); + } + }; +})(); + +/** + * Colors. + */ + +exports.colors = [ + '#0000CC', + '#0000FF', + '#0033CC', + '#0033FF', + '#0066CC', + '#0066FF', + '#0099CC', + '#0099FF', + '#00CC00', + '#00CC33', + '#00CC66', + '#00CC99', + '#00CCCC', + '#00CCFF', + '#3300CC', + '#3300FF', + '#3333CC', + '#3333FF', + '#3366CC', + '#3366FF', + '#3399CC', + '#3399FF', + '#33CC00', + '#33CC33', + '#33CC66', + '#33CC99', + '#33CCCC', + '#33CCFF', + '#6600CC', + '#6600FF', + '#6633CC', + '#6633FF', + '#66CC00', + '#66CC33', + '#9900CC', + '#9900FF', + '#9933CC', + '#9933FF', + '#99CC00', + '#99CC33', + '#CC0000', + '#CC0033', + '#CC0066', + '#CC0099', + '#CC00CC', + '#CC00FF', + '#CC3300', + '#CC3333', + '#CC3366', + '#CC3399', + '#CC33CC', + '#CC33FF', + '#CC6600', + '#CC6633', + '#CC9900', + '#CC9933', + '#CCCC00', + '#CCCC33', + '#FF0000', + '#FF0033', + '#FF0066', + '#FF0099', + '#FF00CC', + '#FF00FF', + '#FF3300', + '#FF3333', + '#FF3366', + '#FF3399', + '#FF33CC', + '#FF33FF', + '#FF6600', + '#FF6633', + '#FF9900', + '#FF9933', + '#FFCC00', + '#FFCC33' +]; + +/** + * Currently only WebKit-based Web Inspectors, Firefox >= v31, + * and the Firebug extension (any Firefox version) are known + * to support "%c" CSS customizations. + * + * TODO: add a `localStorage` variable to explicitly enable/disable colors + */ + +// eslint-disable-next-line complexity +function useColors() { + // NB: In an Electron preload script, document will be defined but not fully + // initialized. Since we know we're in Chrome, we'll just detect this case + // explicitly + if (typeof window !== 'undefined' && window.process && (window.process.type === 'renderer' || window.process.__nwjs)) { + return true; + } + + // Internet Explorer and Edge do not support colors. + if (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/(edge|trident)\/(\d+)/)) { + return false; + } + + // Is webkit? http://stackoverflow.com/a/16459606/376773 + // document is undefined in react-native: https://github.com/facebook/react-native/pull/1632 + return (typeof document !== 'undefined' && document.documentElement && document.documentElement.style && document.documentElement.style.WebkitAppearance) || + // Is firebug? http://stackoverflow.com/a/398120/376773 + (typeof window !== 'undefined' && window.console && (window.console.firebug || (window.console.exception && window.console.table))) || + // Is firefox >= v31? + // https://developer.mozilla.org/en-US/docs/Tools/Web_Console#Styling_messages + (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/) && parseInt(RegExp.$1, 10) >= 31) || + // Double check webkit in userAgent just in case we are in a worker + (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/applewebkit\/(\d+)/)); +} + +/** + * Colorize log arguments if enabled. + * + * @api public + */ + +function formatArgs(args) { + args[0] = (this.useColors ? '%c' : '') + + this.namespace + + (this.useColors ? ' %c' : ' ') + + args[0] + + (this.useColors ? '%c ' : ' ') + + '+' + module.exports.humanize(this.diff); + + if (!this.useColors) { + return; + } + + const c = 'color: ' + this.color; + args.splice(1, 0, c, 'color: inherit'); + + // The final "%c" is somewhat tricky, because there could be other + // arguments passed either before or after the %c, so we need to + // figure out the correct index to insert the CSS into + let index = 0; + let lastC = 0; + args[0].replace(/%[a-zA-Z%]/g, match => { + if (match === '%%') { + return; + } + index++; + if (match === '%c') { + // We only are interested in the *last* %c + // (the user may have provided their own) + lastC = index; + } + }); + + args.splice(lastC, 0, c); +} + +/** + * Invokes `console.debug()` when available. + * No-op when `console.debug` is not a "function". + * If `console.debug` is not available, falls back + * to `console.log`. + * + * @api public + */ +exports.log = console.debug || console.log || (() => {}); + +/** + * Save `namespaces`. + * + * @param {String} namespaces + * @api private + */ +function save(namespaces) { + try { + if (namespaces) { + exports.storage.setItem('debug', namespaces); + } else { + exports.storage.removeItem('debug'); + } + } catch (error) { + // Swallow + // XXX (@Qix-) should we be logging these? + } +} + +/** + * Load `namespaces`. + * + * @return {String} returns the previously persisted debug modes + * @api private + */ +function load() { + let r; + try { + r = exports.storage.getItem('debug'); + } catch (error) { + // Swallow + // XXX (@Qix-) should we be logging these? + } + + // If debug isn't set in LS, and we're in Electron, try to load $DEBUG + if (!r && typeof process !== 'undefined' && 'env' in process) { + r = process.env.DEBUG; + } + + return r; +} + +/** + * Localstorage attempts to return the localstorage. + * + * This is necessary because safari throws + * when a user disables cookies/localstorage + * and you attempt to access it. + * + * @return {LocalStorage} + * @api private + */ + +function localstorage() { + try { + // TVMLKit (Apple TV JS Runtime) does not have a window object, just localStorage in the global context + // The Browser also has localStorage in the global context. + return localStorage; + } catch (error) { + // Swallow + // XXX (@Qix-) should we be logging these? + } +} + +module.exports = __nccwpck_require__(6243)(exports); + +const {formatters} = module.exports; + +/** + * Map %j to `JSON.stringify()`, since no Web Inspectors do that by default. + */ + +formatters.j = function (v) { + try { + return JSON.stringify(v); + } catch (error) { + return '[UnexpectedJSONParseError]: ' + error.message; + } +}; + + +/***/ }), + +/***/ 6243: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + + +/** + * This is the common logic for both the Node.js and web browser + * implementations of `debug()`. + */ + +function setup(env) { + createDebug.debug = createDebug; + createDebug.default = createDebug; + createDebug.coerce = coerce; + createDebug.disable = disable; + createDebug.enable = enable; + createDebug.enabled = enabled; + createDebug.humanize = __nccwpck_require__(900); + createDebug.destroy = destroy; + + Object.keys(env).forEach(key => { + createDebug[key] = env[key]; + }); + + /** + * The currently active debug mode names, and names to skip. + */ + + createDebug.names = []; + createDebug.skips = []; + + /** + * Map of special "%n" handling functions, for the debug "format" argument. + * + * Valid key names are a single, lower or upper-case letter, i.e. "n" and "N". + */ + createDebug.formatters = {}; + + /** + * Selects a color for a debug namespace + * @param {String} namespace The namespace string for the debug instance to be colored + * @return {Number|String} An ANSI color code for the given namespace + * @api private + */ + function selectColor(namespace) { + let hash = 0; + + for (let i = 0; i < namespace.length; i++) { + hash = ((hash << 5) - hash) + namespace.charCodeAt(i); + hash |= 0; // Convert to 32bit integer + } + + return createDebug.colors[Math.abs(hash) % createDebug.colors.length]; + } + createDebug.selectColor = selectColor; + + /** + * Create a debugger with the given `namespace`. + * + * @param {String} namespace + * @return {Function} + * @api public + */ + function createDebug(namespace) { + let prevTime; + let enableOverride = null; + let namespacesCache; + let enabledCache; + + function debug(...args) { + // Disabled? + if (!debug.enabled) { + return; + } + + const self = debug; + + // Set `diff` timestamp + const curr = Number(new Date()); + const ms = curr - (prevTime || curr); + self.diff = ms; + self.prev = prevTime; + self.curr = curr; + prevTime = curr; + + args[0] = createDebug.coerce(args[0]); + + if (typeof args[0] !== 'string') { + // Anything else let's inspect with %O + args.unshift('%O'); + } + + // Apply any `formatters` transformations + let index = 0; + args[0] = args[0].replace(/%([a-zA-Z%])/g, (match, format) => { + // If we encounter an escaped % then don't increase the array index + if (match === '%%') { + return '%'; + } + index++; + const formatter = createDebug.formatters[format]; + if (typeof formatter === 'function') { + const val = args[index]; + match = formatter.call(self, val); + + // Now we need to remove `args[index]` since it's inlined in the `format` + args.splice(index, 1); + index--; + } + return match; + }); + + // Apply env-specific formatting (colors, etc.) + createDebug.formatArgs.call(self, args); + + const logFn = self.log || createDebug.log; + logFn.apply(self, args); + } + + debug.namespace = namespace; + debug.useColors = createDebug.useColors(); + debug.color = createDebug.selectColor(namespace); + debug.extend = extend; + debug.destroy = createDebug.destroy; // XXX Temporary. Will be removed in the next major release. + + Object.defineProperty(debug, 'enabled', { + enumerable: true, + configurable: false, + get: () => { + if (enableOverride !== null) { + return enableOverride; + } + if (namespacesCache !== createDebug.namespaces) { + namespacesCache = createDebug.namespaces; + enabledCache = createDebug.enabled(namespace); + } + + return enabledCache; + }, + set: v => { + enableOverride = v; + } + }); + + // Env-specific initialization logic for debug instances + if (typeof createDebug.init === 'function') { + createDebug.init(debug); + } + + return debug; + } + + function extend(namespace, delimiter) { + const newDebug = createDebug(this.namespace + (typeof delimiter === 'undefined' ? ':' : delimiter) + namespace); + newDebug.log = this.log; + return newDebug; + } + + /** + * Enables a debug mode by namespaces. This can include modes + * separated by a colon and wildcards. + * + * @param {String} namespaces + * @api public + */ + function enable(namespaces) { + createDebug.save(namespaces); + createDebug.namespaces = namespaces; + + createDebug.names = []; + createDebug.skips = []; + + let i; + const split = (typeof namespaces === 'string' ? namespaces : '').split(/[\s,]+/); + const len = split.length; + + for (i = 0; i < len; i++) { + if (!split[i]) { + // ignore empty strings + continue; + } + + namespaces = split[i].replace(/\*/g, '.*?'); + + if (namespaces[0] === '-') { + createDebug.skips.push(new RegExp('^' + namespaces.slice(1) + '$')); + } else { + createDebug.names.push(new RegExp('^' + namespaces + '$')); + } + } + } + + /** + * Disable debug output. + * + * @return {String} namespaces + * @api public + */ + function disable() { + const namespaces = [ + ...createDebug.names.map(toNamespace), + ...createDebug.skips.map(toNamespace).map(namespace => '-' + namespace) + ].join(','); + createDebug.enable(''); + return namespaces; + } + + /** + * Returns true if the given mode name is enabled, false otherwise. + * + * @param {String} name + * @return {Boolean} + * @api public + */ + function enabled(name) { + if (name[name.length - 1] === '*') { + return true; + } + + let i; + let len; + + for (i = 0, len = createDebug.skips.length; i < len; i++) { + if (createDebug.skips[i].test(name)) { + return false; + } + } + + for (i = 0, len = createDebug.names.length; i < len; i++) { + if (createDebug.names[i].test(name)) { + return true; + } + } + + return false; + } + + /** + * Convert regexp to namespace + * + * @param {RegExp} regxep + * @return {String} namespace + * @api private + */ + function toNamespace(regexp) { + return regexp.toString() + .substring(2, regexp.toString().length - 2) + .replace(/\.\*\?$/, '*'); + } + + /** + * Coerce `val`. + * + * @param {Mixed} val + * @return {Mixed} + * @api private + */ + function coerce(val) { + if (val instanceof Error) { + return val.stack || val.message; + } + return val; + } + + /** + * XXX DO NOT USE. This is a temporary stub function. + * XXX It WILL be removed in the next major release. + */ + function destroy() { + console.warn('Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`.'); + } + + createDebug.enable(createDebug.load()); + + return createDebug; +} + +module.exports = setup; + + +/***/ }), + +/***/ 8237: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +/** + * Detect Electron renderer / nwjs process, which is node, but we should + * treat as a browser. + */ + +if (typeof process === 'undefined' || process.type === 'renderer' || process.browser === true || process.__nwjs) { + module.exports = __nccwpck_require__(8222); +} else { + module.exports = __nccwpck_require__(4874); +} + + +/***/ }), + +/***/ 4874: +/***/ ((module, exports, __nccwpck_require__) => { + +/** + * Module dependencies. + */ + +const tty = __nccwpck_require__(6224); +const util = __nccwpck_require__(3837); + +/** + * This is the Node.js implementation of `debug()`. + */ + +exports.init = init; +exports.log = log; +exports.formatArgs = formatArgs; +exports.save = save; +exports.load = load; +exports.useColors = useColors; +exports.destroy = util.deprecate( + () => {}, + 'Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`.' +); + +/** + * Colors. + */ + +exports.colors = [6, 2, 3, 4, 5, 1]; + +try { + // Optional dependency (as in, doesn't need to be installed, NOT like optionalDependencies in package.json) + // eslint-disable-next-line import/no-extraneous-dependencies + const supportsColor = __nccwpck_require__(9318); + + if (supportsColor && (supportsColor.stderr || supportsColor).level >= 2) { + exports.colors = [ + 20, + 21, + 26, + 27, + 32, + 33, + 38, + 39, + 40, + 41, + 42, + 43, + 44, + 45, + 56, + 57, + 62, + 63, + 68, + 69, + 74, + 75, + 76, + 77, + 78, + 79, + 80, + 81, + 92, + 93, + 98, + 99, + 112, + 113, + 128, + 129, + 134, + 135, + 148, + 149, + 160, + 161, + 162, + 163, + 164, + 165, + 166, + 167, + 168, + 169, + 170, + 171, + 172, + 173, + 178, + 179, + 184, + 185, + 196, + 197, + 198, + 199, + 200, + 201, + 202, + 203, + 204, + 205, + 206, + 207, + 208, + 209, + 214, + 215, + 220, + 221 + ]; + } +} catch (error) { + // Swallow - we only care if `supports-color` is available; it doesn't have to be. +} + +/** + * Build up the default `inspectOpts` object from the environment variables. + * + * $ DEBUG_COLORS=no DEBUG_DEPTH=10 DEBUG_SHOW_HIDDEN=enabled node script.js + */ + +exports.inspectOpts = Object.keys(process.env).filter(key => { + return /^debug_/i.test(key); +}).reduce((obj, key) => { + // Camel-case + const prop = key + .substring(6) + .toLowerCase() + .replace(/_([a-z])/g, (_, k) => { + return k.toUpperCase(); + }); + + // Coerce string value into JS value + let val = process.env[key]; + if (/^(yes|on|true|enabled)$/i.test(val)) { + val = true; + } else if (/^(no|off|false|disabled)$/i.test(val)) { + val = false; + } else if (val === 'null') { + val = null; + } else { + val = Number(val); + } + + obj[prop] = val; + return obj; +}, {}); + +/** + * Is stdout a TTY? Colored output is enabled when `true`. + */ + +function useColors() { + return 'colors' in exports.inspectOpts ? + Boolean(exports.inspectOpts.colors) : + tty.isatty(process.stderr.fd); +} + +/** + * Adds ANSI color escape codes if enabled. + * + * @api public + */ + +function formatArgs(args) { + const {namespace: name, useColors} = this; + + if (useColors) { + const c = this.color; + const colorCode = '\u001B[3' + (c < 8 ? c : '8;5;' + c); + const prefix = ` ${colorCode};1m${name} \u001B[0m`; + + args[0] = prefix + args[0].split('\n').join('\n' + prefix); + args.push(colorCode + 'm+' + module.exports.humanize(this.diff) + '\u001B[0m'); + } else { + args[0] = getDate() + name + ' ' + args[0]; + } +} + +function getDate() { + if (exports.inspectOpts.hideDate) { + return ''; + } + return new Date().toISOString() + ' '; +} + +/** + * Invokes `util.format()` with the specified arguments and writes to stderr. + */ + +function log(...args) { + return process.stderr.write(util.format(...args) + '\n'); +} + +/** + * Save `namespaces`. + * + * @param {String} namespaces + * @api private + */ +function save(namespaces) { + if (namespaces) { + process.env.DEBUG = namespaces; + } else { + // If you set a process.env field to null or undefined, it gets cast to the + // string 'null' or 'undefined'. Just delete instead. + delete process.env.DEBUG; + } +} + +/** + * Load `namespaces`. + * + * @return {String} returns the previously persisted debug modes + * @api private + */ + +function load() { + return process.env.DEBUG; +} + +/** + * Init logic for `debug` instances. + * + * Create a new `inspectOpts` object in case `useColors` is set + * differently for a particular `debug` instance. + */ + +function init(debug) { + debug.inspectOpts = {}; + + const keys = Object.keys(exports.inspectOpts); + for (let i = 0; i < keys.length; i++) { + debug.inspectOpts[keys[i]] = exports.inspectOpts[keys[i]]; + } +} + +module.exports = __nccwpck_require__(6243)(exports); + +const {formatters} = module.exports; + +/** + * Map %o to `util.inspect()`, all on a single line. + */ + +formatters.o = function (v) { + this.inspectOpts.colors = this.useColors; + return util.inspect(v, this.inspectOpts) + .split('\n') + .map(str => str.trim()) + .join(' '); +}; + +/** + * Map %O to `util.inspect()`, allowing multiple lines if needed. + */ + +formatters.O = function (v) { + this.inspectOpts.colors = this.useColors; + return util.inspect(v, this.inspectOpts); +}; + + +/***/ }), + +/***/ 961: +/***/ ((module) => { + +"use strict"; + +module.exports = (object, propertyName, fn) => { + const define = value => Object.defineProperty(object, propertyName, {value, enumerable: true, writable: true}); + + Object.defineProperty(object, propertyName, { + configurable: true, + enumerable: true, + get() { + const result = fn(); + define(result); + return result; + }, + set(value) { + define(value); + } + }); + + return object; +}; + + +/***/ }), + +/***/ 8611: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +var Stream = (__nccwpck_require__(2781).Stream); +var util = __nccwpck_require__(3837); + +module.exports = DelayedStream; +function DelayedStream() { + this.source = null; + this.dataSize = 0; + this.maxDataSize = 1024 * 1024; + this.pauseStream = true; + + this._maxDataSizeExceeded = false; + this._released = false; + this._bufferedEvents = []; +} +util.inherits(DelayedStream, Stream); + +DelayedStream.create = function(source, options) { + var delayedStream = new this(); + + options = options || {}; + for (var option in options) { + delayedStream[option] = options[option]; + } + + delayedStream.source = source; + + var realEmit = source.emit; + source.emit = function() { + delayedStream._handleEmit(arguments); + return realEmit.apply(source, arguments); + }; + + source.on('error', function() {}); + if (delayedStream.pauseStream) { + source.pause(); + } + + return delayedStream; +}; + +Object.defineProperty(DelayedStream.prototype, 'readable', { + configurable: true, + enumerable: true, + get: function() { + return this.source.readable; + } +}); + +DelayedStream.prototype.setEncoding = function() { + return this.source.setEncoding.apply(this.source, arguments); +}; + +DelayedStream.prototype.resume = function() { + if (!this._released) { + this.release(); + } + + this.source.resume(); +}; + +DelayedStream.prototype.pause = function() { + this.source.pause(); +}; + +DelayedStream.prototype.release = function() { + this._released = true; + + this._bufferedEvents.forEach(function(args) { + this.emit.apply(this, args); + }.bind(this)); + this._bufferedEvents = []; +}; + +DelayedStream.prototype.pipe = function() { + var r = Stream.prototype.pipe.apply(this, arguments); + this.resume(); + return r; +}; + +DelayedStream.prototype._handleEmit = function(args) { + if (this._released) { + this.emit.apply(this, args); + return; + } + + if (args[0] === 'data') { + this.dataSize += args[1].length; + this._checkIfMaxDataSizeExceeded(); + } + + this._bufferedEvents.push(args); +}; + +DelayedStream.prototype._checkIfMaxDataSizeExceeded = function() { + if (this._maxDataSizeExceeded) { + return; + } + + if (this.dataSize <= this.maxDataSize) { + return; + } + + this._maxDataSizeExceeded = true; + var message = + 'DelayedStream#maxDataSize of ' + this.maxDataSize + ' bytes exceeded.' + this.emit('error', new Error(message)); +}; + + +/***/ }), + +/***/ 1728: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +var Buffer = (__nccwpck_require__(1867).Buffer); + +var getParamBytesForAlg = __nccwpck_require__(528); + +var MAX_OCTET = 0x80, + CLASS_UNIVERSAL = 0, + PRIMITIVE_BIT = 0x20, + TAG_SEQ = 0x10, + TAG_INT = 0x02, + ENCODED_TAG_SEQ = (TAG_SEQ | PRIMITIVE_BIT) | (CLASS_UNIVERSAL << 6), + ENCODED_TAG_INT = TAG_INT | (CLASS_UNIVERSAL << 6); + +function base64Url(base64) { + return base64 + .replace(/=/g, '') + .replace(/\+/g, '-') + .replace(/\//g, '_'); +} + +function signatureAsBuffer(signature) { + if (Buffer.isBuffer(signature)) { + return signature; + } else if ('string' === typeof signature) { + return Buffer.from(signature, 'base64'); + } + + throw new TypeError('ECDSA signature must be a Base64 string or a Buffer'); +} + +function derToJose(signature, alg) { + signature = signatureAsBuffer(signature); + var paramBytes = getParamBytesForAlg(alg); + + // the DER encoded param should at most be the param size, plus a padding + // zero, since due to being a signed integer + var maxEncodedParamLength = paramBytes + 1; + + var inputLength = signature.length; + + var offset = 0; + if (signature[offset++] !== ENCODED_TAG_SEQ) { + throw new Error('Could not find expected "seq"'); + } + + var seqLength = signature[offset++]; + if (seqLength === (MAX_OCTET | 1)) { + seqLength = signature[offset++]; + } + + if (inputLength - offset < seqLength) { + throw new Error('"seq" specified length of "' + seqLength + '", only "' + (inputLength - offset) + '" remaining'); + } + + if (signature[offset++] !== ENCODED_TAG_INT) { + throw new Error('Could not find expected "int" for "r"'); + } + + var rLength = signature[offset++]; + + if (inputLength - offset - 2 < rLength) { + throw new Error('"r" specified length of "' + rLength + '", only "' + (inputLength - offset - 2) + '" available'); + } + + if (maxEncodedParamLength < rLength) { + throw new Error('"r" specified length of "' + rLength + '", max of "' + maxEncodedParamLength + '" is acceptable'); + } + + var rOffset = offset; + offset += rLength; + + if (signature[offset++] !== ENCODED_TAG_INT) { + throw new Error('Could not find expected "int" for "s"'); + } + + var sLength = signature[offset++]; + + if (inputLength - offset !== sLength) { + throw new Error('"s" specified length of "' + sLength + '", expected "' + (inputLength - offset) + '"'); + } + + if (maxEncodedParamLength < sLength) { + throw new Error('"s" specified length of "' + sLength + '", max of "' + maxEncodedParamLength + '" is acceptable'); + } + + var sOffset = offset; + offset += sLength; + + if (offset !== inputLength) { + throw new Error('Expected to consume entire buffer, but "' + (inputLength - offset) + '" bytes remain'); + } + + var rPadding = paramBytes - rLength, + sPadding = paramBytes - sLength; + + var dst = Buffer.allocUnsafe(rPadding + rLength + sPadding + sLength); + + for (offset = 0; offset < rPadding; ++offset) { + dst[offset] = 0; + } + signature.copy(dst, offset, rOffset + Math.max(-rPadding, 0), rOffset + rLength); + + offset = paramBytes; + + for (var o = offset; offset < o + sPadding; ++offset) { + dst[offset] = 0; + } + signature.copy(dst, offset, sOffset + Math.max(-sPadding, 0), sOffset + sLength); + + dst = dst.toString('base64'); + dst = base64Url(dst); + + return dst; +} + +function countPadding(buf, start, stop) { + var padding = 0; + while (start + padding < stop && buf[start + padding] === 0) { + ++padding; + } + + var needsSign = buf[start + padding] >= MAX_OCTET; + if (needsSign) { + --padding; + } + + return padding; +} + +function joseToDer(signature, alg) { + signature = signatureAsBuffer(signature); + var paramBytes = getParamBytesForAlg(alg); + + var signatureBytes = signature.length; + if (signatureBytes !== paramBytes * 2) { + throw new TypeError('"' + alg + '" signatures must be "' + paramBytes * 2 + '" bytes, saw "' + signatureBytes + '"'); + } + + var rPadding = countPadding(signature, 0, paramBytes); + var sPadding = countPadding(signature, paramBytes, signature.length); + var rLength = paramBytes - rPadding; + var sLength = paramBytes - sPadding; + + var rsBytes = 1 + 1 + rLength + 1 + 1 + sLength; + + var shortLength = rsBytes < MAX_OCTET; + + var dst = Buffer.allocUnsafe((shortLength ? 2 : 3) + rsBytes); + + var offset = 0; + dst[offset++] = ENCODED_TAG_SEQ; + if (shortLength) { + // Bit 8 has value "0" + // bits 7-1 give the length. + dst[offset++] = rsBytes; + } else { + // Bit 8 of first octet has value "1" + // bits 7-1 give the number of additional length octets. + dst[offset++] = MAX_OCTET | 1; + // length, base 256 + dst[offset++] = rsBytes & 0xff; + } + dst[offset++] = ENCODED_TAG_INT; + dst[offset++] = rLength; + if (rPadding < 0) { + dst[offset++] = 0; + offset += signature.copy(dst, offset, 0, paramBytes); + } else { + offset += signature.copy(dst, offset, rPadding, paramBytes); + } + dst[offset++] = ENCODED_TAG_INT; + dst[offset++] = sLength; + if (sPadding < 0) { + dst[offset++] = 0; + signature.copy(dst, offset, paramBytes); + } else { + signature.copy(dst, offset, paramBytes + sPadding); + } + + return dst; +} + +module.exports = { + derToJose: derToJose, + joseToDer: joseToDer +}; + + +/***/ }), + +/***/ 528: +/***/ ((module) => { + +"use strict"; + + +function getParamSize(keySize) { + var result = ((keySize / 8) | 0) + (keySize % 8 === 0 ? 0 : 1); + return result; +} + +var paramBytesForAlg = { + ES256: getParamSize(256), + ES384: getParamSize(384), + ES512: getParamSize(521) +}; + +function getParamBytesForAlg(alg) { + var paramBytes = paramBytesForAlg[alg]; + if (paramBytes) { + return paramBytes; + } + + throw new Error('Unknown algorithm "' + alg + '"'); +} + +module.exports = getParamBytesForAlg; + + +/***/ }), + +/***/ 4334: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +var CombinedStream = __nccwpck_require__(5443); +var util = __nccwpck_require__(3837); +var path = __nccwpck_require__(1017); +var http = __nccwpck_require__(3685); +var https = __nccwpck_require__(5687); +var parseUrl = (__nccwpck_require__(7310).parse); +var fs = __nccwpck_require__(7147); +var Stream = (__nccwpck_require__(2781).Stream); +var mime = __nccwpck_require__(3583); +var asynckit = __nccwpck_require__(4812); +var populate = __nccwpck_require__(7142); + +// Public API +module.exports = FormData; + +// make it a Stream +util.inherits(FormData, CombinedStream); + +/** + * Create readable "multipart/form-data" streams. + * Can be used to submit forms + * and file uploads to other web applications. + * + * @constructor + * @param {Object} options - Properties to be added/overriden for FormData and CombinedStream + */ +function FormData(options) { + if (!(this instanceof FormData)) { + return new FormData(options); + } + + this._overheadLength = 0; + this._valueLength = 0; + this._valuesToMeasure = []; + + CombinedStream.call(this); + + options = options || {}; + for (var option in options) { + this[option] = options[option]; + } +} + +FormData.LINE_BREAK = '\r\n'; +FormData.DEFAULT_CONTENT_TYPE = 'application/octet-stream'; + +FormData.prototype.append = function(field, value, options) { + + options = options || {}; + + // allow filename as single option + if (typeof options == 'string') { + options = {filename: options}; + } + + var append = CombinedStream.prototype.append.bind(this); + + // all that streamy business can't handle numbers + if (typeof value == 'number') { + value = '' + value; + } + + // https://github.com/felixge/node-form-data/issues/38 + if (util.isArray(value)) { + // Please convert your array into string + // the way web server expects it + this._error(new Error('Arrays are not supported.')); + return; + } + + var header = this._multiPartHeader(field, value, options); + var footer = this._multiPartFooter(); + + append(header); + append(value); + append(footer); + + // pass along options.knownLength + this._trackLength(header, value, options); +}; + +FormData.prototype._trackLength = function(header, value, options) { + var valueLength = 0; + + // used w/ getLengthSync(), when length is known. + // e.g. for streaming directly from a remote server, + // w/ a known file a size, and not wanting to wait for + // incoming file to finish to get its size. + if (options.knownLength != null) { + valueLength += +options.knownLength; + } else if (Buffer.isBuffer(value)) { + valueLength = value.length; + } else if (typeof value === 'string') { + valueLength = Buffer.byteLength(value); + } + + this._valueLength += valueLength; + + // @check why add CRLF? does this account for custom/multiple CRLFs? + this._overheadLength += + Buffer.byteLength(header) + + FormData.LINE_BREAK.length; + + // empty or either doesn't have path or not an http response or not a stream + if (!value || ( !value.path && !(value.readable && value.hasOwnProperty('httpVersion')) && !(value instanceof Stream))) { + return; + } + + // no need to bother with the length + if (!options.knownLength) { + this._valuesToMeasure.push(value); + } +}; + +FormData.prototype._lengthRetriever = function(value, callback) { + + if (value.hasOwnProperty('fd')) { + + // take read range into a account + // `end` = Infinity –> read file till the end + // + // TODO: Looks like there is bug in Node fs.createReadStream + // it doesn't respect `end` options without `start` options + // Fix it when node fixes it. + // https://github.com/joyent/node/issues/7819 + if (value.end != undefined && value.end != Infinity && value.start != undefined) { + + // when end specified + // no need to calculate range + // inclusive, starts with 0 + callback(null, value.end + 1 - (value.start ? value.start : 0)); + + // not that fast snoopy + } else { + // still need to fetch file size from fs + fs.stat(value.path, function(err, stat) { + + var fileSize; + + if (err) { + callback(err); + return; + } + + // update final size based on the range options + fileSize = stat.size - (value.start ? value.start : 0); + callback(null, fileSize); + }); + } + + // or http response + } else if (value.hasOwnProperty('httpVersion')) { + callback(null, +value.headers['content-length']); + + // or request stream http://github.com/mikeal/request + } else if (value.hasOwnProperty('httpModule')) { + // wait till response come back + value.on('response', function(response) { + value.pause(); + callback(null, +response.headers['content-length']); + }); + value.resume(); + + // something else + } else { + callback('Unknown stream'); + } +}; + +FormData.prototype._multiPartHeader = function(field, value, options) { + // custom header specified (as string)? + // it becomes responsible for boundary + // (e.g. to handle extra CRLFs on .NET servers) + if (typeof options.header == 'string') { + return options.header; + } + + var contentDisposition = this._getContentDisposition(value, options); + var contentType = this._getContentType(value, options); + + var contents = ''; + var headers = { + // add custom disposition as third element or keep it two elements if not + 'Content-Disposition': ['form-data', 'name="' + field + '"'].concat(contentDisposition || []), + // if no content type. allow it to be empty array + 'Content-Type': [].concat(contentType || []) + }; + + // allow custom headers. + if (typeof options.header == 'object') { + populate(headers, options.header); + } + + var header; + for (var prop in headers) { + if (!headers.hasOwnProperty(prop)) continue; + header = headers[prop]; + + // skip nullish headers. + if (header == null) { + continue; + } + + // convert all headers to arrays. + if (!Array.isArray(header)) { + header = [header]; + } + + // add non-empty headers. + if (header.length) { + contents += prop + ': ' + header.join('; ') + FormData.LINE_BREAK; + } + } + + return '--' + this.getBoundary() + FormData.LINE_BREAK + contents + FormData.LINE_BREAK; +}; + +FormData.prototype._getContentDisposition = function(value, options) { + + var filename + , contentDisposition + ; + + if (typeof options.filepath === 'string') { + // custom filepath for relative paths + filename = path.normalize(options.filepath).replace(/\\/g, '/'); + } else if (options.filename || value.name || value.path) { + // custom filename take precedence + // formidable and the browser add a name property + // fs- and request- streams have path property + filename = path.basename(options.filename || value.name || value.path); + } else if (value.readable && value.hasOwnProperty('httpVersion')) { + // or try http response + filename = path.basename(value.client._httpMessage.path || ''); + } + + if (filename) { + contentDisposition = 'filename="' + filename + '"'; + } + + return contentDisposition; +}; + +FormData.prototype._getContentType = function(value, options) { + + // use custom content-type above all + var contentType = options.contentType; + + // or try `name` from formidable, browser + if (!contentType && value.name) { + contentType = mime.lookup(value.name); + } + + // or try `path` from fs-, request- streams + if (!contentType && value.path) { + contentType = mime.lookup(value.path); + } + + // or if it's http-reponse + if (!contentType && value.readable && value.hasOwnProperty('httpVersion')) { + contentType = value.headers['content-type']; + } + + // or guess it from the filepath or filename + if (!contentType && (options.filepath || options.filename)) { + contentType = mime.lookup(options.filepath || options.filename); + } + + // fallback to the default content type if `value` is not simple value + if (!contentType && typeof value == 'object') { + contentType = FormData.DEFAULT_CONTENT_TYPE; + } + + return contentType; +}; + +FormData.prototype._multiPartFooter = function() { + return function(next) { + var footer = FormData.LINE_BREAK; + + var lastPart = (this._streams.length === 0); + if (lastPart) { + footer += this._lastBoundary(); + } + + next(footer); + }.bind(this); +}; + +FormData.prototype._lastBoundary = function() { + return '--' + this.getBoundary() + '--' + FormData.LINE_BREAK; +}; + +FormData.prototype.getHeaders = function(userHeaders) { + var header; + var formHeaders = { + 'content-type': 'multipart/form-data; boundary=' + this.getBoundary() + }; + + for (header in userHeaders) { + if (userHeaders.hasOwnProperty(header)) { + formHeaders[header.toLowerCase()] = userHeaders[header]; + } + } + + return formHeaders; +}; + +FormData.prototype.setBoundary = function(boundary) { + this._boundary = boundary; +}; + +FormData.prototype.getBoundary = function() { + if (!this._boundary) { + this._generateBoundary(); + } + + return this._boundary; +}; + +FormData.prototype.getBuffer = function() { + var dataBuffer = new Buffer.alloc( 0 ); + var boundary = this.getBoundary(); + + // Create the form content. Add Line breaks to the end of data. + for (var i = 0, len = this._streams.length; i < len; i++) { + if (typeof this._streams[i] !== 'function') { + + // Add content to the buffer. + if(Buffer.isBuffer(this._streams[i])) { + dataBuffer = Buffer.concat( [dataBuffer, this._streams[i]]); + }else { + dataBuffer = Buffer.concat( [dataBuffer, Buffer.from(this._streams[i])]); + } + + // Add break after content. + if (typeof this._streams[i] !== 'string' || this._streams[i].substring( 2, boundary.length + 2 ) !== boundary) { + dataBuffer = Buffer.concat( [dataBuffer, Buffer.from(FormData.LINE_BREAK)] ); + } + } + } + + // Add the footer and return the Buffer object. + return Buffer.concat( [dataBuffer, Buffer.from(this._lastBoundary())] ); +}; + +FormData.prototype._generateBoundary = function() { + // This generates a 50 character boundary similar to those used by Firefox. + // They are optimized for boyer-moore parsing. + var boundary = '--------------------------'; + for (var i = 0; i < 24; i++) { + boundary += Math.floor(Math.random() * 10).toString(16); + } + + this._boundary = boundary; +}; + +// Note: getLengthSync DOESN'T calculate streams length +// As workaround one can calculate file size manually +// and add it as knownLength option +FormData.prototype.getLengthSync = function() { + var knownLength = this._overheadLength + this._valueLength; + + // Don't get confused, there are 3 "internal" streams for each keyval pair + // so it basically checks if there is any value added to the form + if (this._streams.length) { + knownLength += this._lastBoundary().length; + } + + // https://github.com/form-data/form-data/issues/40 + if (!this.hasKnownLength()) { + // Some async length retrievers are present + // therefore synchronous length calculation is false. + // Please use getLength(callback) to get proper length + this._error(new Error('Cannot calculate proper length in synchronous way.')); + } + + return knownLength; +}; + +// Public API to check if length of added values is known +// https://github.com/form-data/form-data/issues/196 +// https://github.com/form-data/form-data/issues/262 +FormData.prototype.hasKnownLength = function() { + var hasKnownLength = true; + + if (this._valuesToMeasure.length) { + hasKnownLength = false; + } + + return hasKnownLength; +}; + +FormData.prototype.getLength = function(cb) { + var knownLength = this._overheadLength + this._valueLength; + + if (this._streams.length) { + knownLength += this._lastBoundary().length; + } + + if (!this._valuesToMeasure.length) { + process.nextTick(cb.bind(this, null, knownLength)); + return; + } + + asynckit.parallel(this._valuesToMeasure, this._lengthRetriever, function(err, values) { + if (err) { + cb(err); + return; + } + + values.forEach(function(length) { + knownLength += length; + }); + + cb(null, knownLength); + }); +}; + +FormData.prototype.submit = function(params, cb) { + var request + , options + , defaults = {method: 'post'} + ; + + // parse provided url if it's string + // or treat it as options object + if (typeof params == 'string') { + + params = parseUrl(params); + options = populate({ + port: params.port, + path: params.pathname, + host: params.hostname, + protocol: params.protocol + }, defaults); + + // use custom params + } else { + + options = populate(params, defaults); + // if no port provided use default one + if (!options.port) { + options.port = options.protocol == 'https:' ? 443 : 80; + } + } + + // put that good code in getHeaders to some use + options.headers = this.getHeaders(params.headers); + + // https if specified, fallback to http in any other case + if (options.protocol == 'https:') { + request = https.request(options); + } else { + request = http.request(options); + } + + // get content length and fire away + this.getLength(function(err, length) { + if (err && err !== 'Unknown stream') { + this._error(err); + return; + } + + // add content length + if (length) { + request.setHeader('Content-Length', length); + } + + this.pipe(request); + if (cb) { + var onResponse; + + var callback = function (error, responce) { + request.removeListener('error', callback); + request.removeListener('response', onResponse); + + return cb.call(this, error, responce); + }; + + onResponse = callback.bind(this, null); + + request.on('error', callback); + request.on('response', onResponse); + } + }.bind(this)); + + return request; +}; + +FormData.prototype._error = function(err) { + if (!this.error) { + this.error = err; + this.pause(); + this.emit('error', err); + } +}; + +FormData.prototype.toString = function () { + return '[object FormData]'; +}; + + +/***/ }), + +/***/ 7142: +/***/ ((module) => { + +// populates missing values +module.exports = function(dst, src) { + + Object.keys(src).forEach(function(prop) + { + dst[prop] = dst[prop] || src[prop]; + }); + + return dst; +}; + + +/***/ }), + +/***/ 1621: +/***/ ((module) => { + +"use strict"; + + +module.exports = (flag, argv = process.argv) => { + const prefix = flag.startsWith('-') ? '' : (flag.length === 1 ? '-' : '--'); + const position = argv.indexOf(prefix + flag); + const terminatorPosition = argv.indexOf('--'); + return position !== -1 && (terminatorPosition === -1 || position < terminatorPosition); +}; + + +/***/ }), + +/***/ 7492: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +const net_1 = __importDefault(__nccwpck_require__(1808)); +const tls_1 = __importDefault(__nccwpck_require__(4404)); +const url_1 = __importDefault(__nccwpck_require__(7310)); +const debug_1 = __importDefault(__nccwpck_require__(8237)); +const once_1 = __importDefault(__nccwpck_require__(1040)); +const agent_base_1 = __nccwpck_require__(9690); +const debug = (0, debug_1.default)('http-proxy-agent'); +function isHTTPS(protocol) { + return typeof protocol === 'string' ? /^https:?$/i.test(protocol) : false; +} +/** + * The `HttpProxyAgent` implements an HTTP Agent subclass that connects + * to the specified "HTTP proxy server" in order to proxy HTTP requests. + * + * @api public + */ +class HttpProxyAgent extends agent_base_1.Agent { + constructor(_opts) { + let opts; + if (typeof _opts === 'string') { + opts = url_1.default.parse(_opts); + } + else { + opts = _opts; + } + if (!opts) { + throw new Error('an HTTP(S) proxy server `host` and `port` must be specified!'); + } + debug('Creating new HttpProxyAgent instance: %o', opts); + super(opts); + const proxy = Object.assign({}, opts); + // If `true`, then connect to the proxy server over TLS. + // Defaults to `false`. + this.secureProxy = opts.secureProxy || isHTTPS(proxy.protocol); + // Prefer `hostname` over `host`, and set the `port` if needed. + proxy.host = proxy.hostname || proxy.host; + if (typeof proxy.port === 'string') { + proxy.port = parseInt(proxy.port, 10); + } + if (!proxy.port && proxy.host) { + proxy.port = this.secureProxy ? 443 : 80; + } + if (proxy.host && proxy.path) { + // If both a `host` and `path` are specified then it's most likely + // the result of a `url.parse()` call... we need to remove the + // `path` portion so that `net.connect()` doesn't attempt to open + // that as a Unix socket file. + delete proxy.path; + delete proxy.pathname; + } + this.proxy = proxy; + } + /** + * Called when the node-core HTTP client library is creating a + * new HTTP request. + * + * @api protected + */ + callback(req, opts) { + return __awaiter(this, void 0, void 0, function* () { + const { proxy, secureProxy } = this; + const parsed = url_1.default.parse(req.path); + if (!parsed.protocol) { + parsed.protocol = 'http:'; + } + if (!parsed.hostname) { + parsed.hostname = opts.hostname || opts.host || null; + } + if (parsed.port == null && typeof opts.port) { + parsed.port = String(opts.port); + } + if (parsed.port === '80') { + // if port is 80, then we can remove the port so that the + // ":80" portion is not on the produced URL + parsed.port = ''; + } + // Change the `http.ClientRequest` instance's "path" field + // to the absolute path of the URL that will be requested. + req.path = url_1.default.format(parsed); + // Inject the `Proxy-Authorization` header if necessary. + if (proxy.auth) { + req.setHeader('Proxy-Authorization', `Basic ${Buffer.from(proxy.auth).toString('base64')}`); + } + // Create a socket connection to the proxy server. + let socket; + if (secureProxy) { + debug('Creating `tls.Socket`: %o', proxy); + socket = tls_1.default.connect(proxy); + } + else { + debug('Creating `net.Socket`: %o', proxy); + socket = net_1.default.connect(proxy); + } + // At this point, the http ClientRequest's internal `_header` field + // might have already been set. If this is the case then we'll need + // to re-generate the string since we just changed the `req.path`. + if (req._header) { + let first; + let endOfHeaders; + debug('Regenerating stored HTTP header string for request'); + req._header = null; + req._implicitHeader(); + if (req.output && req.output.length > 0) { + // Node < 12 + debug('Patching connection write() output buffer with updated header'); + first = req.output[0]; + endOfHeaders = first.indexOf('\r\n\r\n') + 4; + req.output[0] = req._header + first.substring(endOfHeaders); + debug('Output buffer: %o', req.output); + } + else if (req.outputData && req.outputData.length > 0) { + // Node >= 12 + debug('Patching connection write() output buffer with updated header'); + first = req.outputData[0].data; + endOfHeaders = first.indexOf('\r\n\r\n') + 4; + req.outputData[0].data = + req._header + first.substring(endOfHeaders); + debug('Output buffer: %o', req.outputData[0].data); + } + } + // Wait for the socket's `connect` event, so that this `callback()` + // function throws instead of the `http` request machinery. This is + // important for i.e. `PacProxyAgent` which determines a failed proxy + // connection via the `callback()` function throwing. + yield (0, once_1.default)(socket, 'connect'); + return socket; + }); + } +} +exports["default"] = HttpProxyAgent; +//# sourceMappingURL=agent.js.map + +/***/ }), + +/***/ 3764: +/***/ (function(module, __unused_webpack_exports, __nccwpck_require__) { + +"use strict"; + +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +const agent_1 = __importDefault(__nccwpck_require__(7492)); +function createHttpProxyAgent(opts) { + return new agent_1.default(opts); +} +(function (createHttpProxyAgent) { + createHttpProxyAgent.HttpProxyAgent = agent_1.default; + createHttpProxyAgent.prototype = agent_1.default.prototype; +})(createHttpProxyAgent || (createHttpProxyAgent = {})); +module.exports = createHttpProxyAgent; +//# sourceMappingURL=index.js.map + +/***/ }), + +/***/ 5098: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +const net_1 = __importDefault(__nccwpck_require__(1808)); +const tls_1 = __importDefault(__nccwpck_require__(4404)); +const url_1 = __importDefault(__nccwpck_require__(7310)); +const assert_1 = __importDefault(__nccwpck_require__(9491)); +const debug_1 = __importDefault(__nccwpck_require__(8237)); +const agent_base_1 = __nccwpck_require__(9690); +const parse_proxy_response_1 = __importDefault(__nccwpck_require__(595)); +const debug = debug_1.default('https-proxy-agent:agent'); +/** + * The `HttpsProxyAgent` implements an HTTP Agent subclass that connects to + * the specified "HTTP(s) proxy server" in order to proxy HTTPS requests. + * + * Outgoing HTTP requests are first tunneled through the proxy server using the + * `CONNECT` HTTP request method to establish a connection to the proxy server, + * and then the proxy server connects to the destination target and issues the + * HTTP request from the proxy server. + * + * `https:` requests have their socket connection upgraded to TLS once + * the connection to the proxy server has been established. + * + * @api public + */ +class HttpsProxyAgent extends agent_base_1.Agent { + constructor(_opts) { + let opts; + if (typeof _opts === 'string') { + opts = url_1.default.parse(_opts); + } + else { + opts = _opts; + } + if (!opts) { + throw new Error('an HTTP(S) proxy server `host` and `port` must be specified!'); + } + debug('creating new HttpsProxyAgent instance: %o', opts); + super(opts); + const proxy = Object.assign({}, opts); + // If `true`, then connect to the proxy server over TLS. + // Defaults to `false`. + this.secureProxy = opts.secureProxy || isHTTPS(proxy.protocol); + // Prefer `hostname` over `host`, and set the `port` if needed. + proxy.host = proxy.hostname || proxy.host; + if (typeof proxy.port === 'string') { + proxy.port = parseInt(proxy.port, 10); + } + if (!proxy.port && proxy.host) { + proxy.port = this.secureProxy ? 443 : 80; + } + // ALPN is supported by Node.js >= v5. + // attempt to negotiate http/1.1 for proxy servers that support http/2 + if (this.secureProxy && !('ALPNProtocols' in proxy)) { + proxy.ALPNProtocols = ['http 1.1']; + } + if (proxy.host && proxy.path) { + // If both a `host` and `path` are specified then it's most likely + // the result of a `url.parse()` call... we need to remove the + // `path` portion so that `net.connect()` doesn't attempt to open + // that as a Unix socket file. + delete proxy.path; + delete proxy.pathname; + } + this.proxy = proxy; + } + /** + * Called when the node-core HTTP client library is creating a + * new HTTP request. + * + * @api protected + */ + callback(req, opts) { + return __awaiter(this, void 0, void 0, function* () { + const { proxy, secureProxy } = this; + // Create a socket connection to the proxy server. + let socket; + if (secureProxy) { + debug('Creating `tls.Socket`: %o', proxy); + socket = tls_1.default.connect(proxy); + } + else { + debug('Creating `net.Socket`: %o', proxy); + socket = net_1.default.connect(proxy); + } + const headers = Object.assign({}, proxy.headers); + const hostname = `${opts.host}:${opts.port}`; + let payload = `CONNECT ${hostname} HTTP/1.1\r\n`; + // Inject the `Proxy-Authorization` header if necessary. + if (proxy.auth) { + headers['Proxy-Authorization'] = `Basic ${Buffer.from(proxy.auth).toString('base64')}`; + } + // The `Host` header should only include the port + // number when it is not the default port. + let { host, port, secureEndpoint } = opts; + if (!isDefaultPort(port, secureEndpoint)) { + host += `:${port}`; + } + headers.Host = host; + headers.Connection = 'close'; + for (const name of Object.keys(headers)) { + payload += `${name}: ${headers[name]}\r\n`; + } + const proxyResponsePromise = parse_proxy_response_1.default(socket); + socket.write(`${payload}\r\n`); + const { statusCode, buffered } = yield proxyResponsePromise; + if (statusCode === 200) { + req.once('socket', resume); + if (opts.secureEndpoint) { + // The proxy is connecting to a TLS server, so upgrade + // this socket connection to a TLS connection. + debug('Upgrading socket connection to TLS'); + const servername = opts.servername || opts.host; + return tls_1.default.connect(Object.assign(Object.assign({}, omit(opts, 'host', 'hostname', 'path', 'port')), { socket, + servername })); + } + return socket; + } + // Some other status code that's not 200... need to re-play the HTTP + // header "data" events onto the socket once the HTTP machinery is + // attached so that the node core `http` can parse and handle the + // error status code. + // Close the original socket, and a new "fake" socket is returned + // instead, so that the proxy doesn't get the HTTP request + // written to it (which may contain `Authorization` headers or other + // sensitive data). + // + // See: https://hackerone.com/reports/541502 + socket.destroy(); + const fakeSocket = new net_1.default.Socket({ writable: false }); + fakeSocket.readable = true; + // Need to wait for the "socket" event to re-play the "data" events. + req.once('socket', (s) => { + debug('replaying proxy buffer for failed request'); + assert_1.default(s.listenerCount('data') > 0); + // Replay the "buffered" Buffer onto the fake `socket`, since at + // this point the HTTP module machinery has been hooked up for + // the user. + s.push(buffered); + s.push(null); + }); + return fakeSocket; + }); + } +} +exports["default"] = HttpsProxyAgent; +function resume(socket) { + socket.resume(); +} +function isDefaultPort(port, secure) { + return Boolean((!secure && port === 80) || (secure && port === 443)); +} +function isHTTPS(protocol) { + return typeof protocol === 'string' ? /^https:?$/i.test(protocol) : false; +} +function omit(obj, ...keys) { + const ret = {}; + let key; + for (key in obj) { + if (!keys.includes(key)) { + ret[key] = obj[key]; + } + } + return ret; +} +//# sourceMappingURL=agent.js.map + +/***/ }), + +/***/ 7219: +/***/ (function(module, __unused_webpack_exports, __nccwpck_require__) { + +"use strict"; + +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +const agent_1 = __importDefault(__nccwpck_require__(5098)); +function createHttpsProxyAgent(opts) { + return new agent_1.default(opts); +} +(function (createHttpsProxyAgent) { + createHttpsProxyAgent.HttpsProxyAgent = agent_1.default; + createHttpsProxyAgent.prototype = agent_1.default.prototype; +})(createHttpsProxyAgent || (createHttpsProxyAgent = {})); +module.exports = createHttpsProxyAgent; +//# sourceMappingURL=index.js.map + +/***/ }), + +/***/ 595: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +const debug_1 = __importDefault(__nccwpck_require__(8237)); +const debug = debug_1.default('https-proxy-agent:parse-proxy-response'); +function parseProxyResponse(socket) { + return new Promise((resolve, reject) => { + // we need to buffer any HTTP traffic that happens with the proxy before we get + // the CONNECT response, so that if the response is anything other than an "200" + // response code, then we can re-play the "data" events on the socket once the + // HTTP parser is hooked up... + let buffersLength = 0; + const buffers = []; + function read() { + const b = socket.read(); + if (b) + ondata(b); + else + socket.once('readable', read); + } + function cleanup() { + socket.removeListener('end', onend); + socket.removeListener('error', onerror); + socket.removeListener('close', onclose); + socket.removeListener('readable', read); + } + function onclose(err) { + debug('onclose had error %o', err); + } + function onend() { + debug('onend'); + } + function onerror(err) { + cleanup(); + debug('onerror %o', err); + reject(err); + } + function ondata(b) { + buffers.push(b); + buffersLength += b.length; + const buffered = Buffer.concat(buffers, buffersLength); + const endOfHeaders = buffered.indexOf('\r\n\r\n'); + if (endOfHeaders === -1) { + // keep buffering + debug('have not received end of HTTP headers yet...'); + read(); + return; + } + const firstLine = buffered.toString('ascii', 0, buffered.indexOf('\r\n')); + const statusCode = +firstLine.split(' ')[1]; + debug('got proxy server response: %o', firstLine); + resolve({ + statusCode, + buffered + }); + } + socket.on('error', onerror); + socket.on('close', onclose); + socket.on('end', onend); + read(); + }); +} +exports["default"] = parseProxyResponse; +//# sourceMappingURL=parse-proxy-response.js.map + +/***/ }), + +/***/ 8768: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + +const fs = __nccwpck_require__(7147); + +let isDocker; + +function hasDockerEnv() { + try { + fs.statSync('/.dockerenv'); + return true; + } catch (_) { + return false; + } +} + +function hasDockerCGroup() { + try { + return fs.readFileSync('/proc/self/cgroup', 'utf8').includes('docker'); + } catch (_) { + return false; + } +} + +module.exports = () => { + if (isDocker === undefined) { + isDocker = hasDockerEnv() || hasDockerCGroup(); + } + + return isDocker; +}; + + +/***/ }), + +/***/ 2559: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + +const os = __nccwpck_require__(2037); +const fs = __nccwpck_require__(7147); +const isDocker = __nccwpck_require__(8768); + +const isWsl = () => { + if (process.platform !== 'linux') { + return false; + } + + if (os.release().toLowerCase().includes('microsoft')) { + if (isDocker()) { + return false; + } + + return true; + } + + try { + return fs.readFileSync('/proc/version', 'utf8').toLowerCase().includes('microsoft') ? + !isDocker() : false; + } catch (_) { + return false; + } +}; + +if (process.env.__IS_WSL_TEST__) { + module.exports = isWsl; +} else { + module.exports = isWsl(); +} + + +/***/ }), + +/***/ 3359: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +var jws = __nccwpck_require__(2597); + +module.exports = function (jwt, options) { + options = options || {}; + var decoded = jws.decode(jwt, options); + if (!decoded) { return null; } + var payload = decoded.payload; + + //try parse the payload + if(typeof payload === 'string') { + try { + var obj = JSON.parse(payload); + if(obj !== null && typeof obj === 'object') { + payload = obj; + } + } catch (e) { } + } + + //return header if `complete` option is enabled. header includes claims + //such as `kid` and `alg` used to select the key within a JWKS needed to + //verify the signature + if (options.complete === true) { + return { + header: decoded.header, + payload: payload, + signature: decoded.signature + }; + } + return payload; +}; + + +/***/ }), + +/***/ 7486: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +module.exports = { + decode: __nccwpck_require__(3359), + verify: __nccwpck_require__(2327), + sign: __nccwpck_require__(2022), + JsonWebTokenError: __nccwpck_require__(405), + NotBeforeError: __nccwpck_require__(4383), + TokenExpiredError: __nccwpck_require__(6637), +}; + + +/***/ }), + +/***/ 405: +/***/ ((module) => { + +var JsonWebTokenError = function (message, error) { + Error.call(this, message); + if(Error.captureStackTrace) { + Error.captureStackTrace(this, this.constructor); + } + this.name = 'JsonWebTokenError'; + this.message = message; + if (error) this.inner = error; +}; + +JsonWebTokenError.prototype = Object.create(Error.prototype); +JsonWebTokenError.prototype.constructor = JsonWebTokenError; + +module.exports = JsonWebTokenError; + + +/***/ }), + +/***/ 4383: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +var JsonWebTokenError = __nccwpck_require__(405); + +var NotBeforeError = function (message, date) { + JsonWebTokenError.call(this, message); + this.name = 'NotBeforeError'; + this.date = date; +}; + +NotBeforeError.prototype = Object.create(JsonWebTokenError.prototype); + +NotBeforeError.prototype.constructor = NotBeforeError; + +module.exports = NotBeforeError; + +/***/ }), + +/***/ 6637: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +var JsonWebTokenError = __nccwpck_require__(405); + +var TokenExpiredError = function (message, expiredAt) { + JsonWebTokenError.call(this, message); + this.name = 'TokenExpiredError'; + this.expiredAt = expiredAt; +}; + +TokenExpiredError.prototype = Object.create(JsonWebTokenError.prototype); + +TokenExpiredError.prototype.constructor = TokenExpiredError; + +module.exports = TokenExpiredError; + +/***/ }), + +/***/ 7622: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +const semver = __nccwpck_require__(1383); + +module.exports = semver.satisfies(process.version, '>=15.7.0'); + + +/***/ }), + +/***/ 9085: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +var semver = __nccwpck_require__(1383); + +module.exports = semver.satisfies(process.version, '^6.12.0 || >=8.0.0'); + + +/***/ }), + +/***/ 5170: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +const semver = __nccwpck_require__(1383); + +module.exports = semver.satisfies(process.version, '>=16.9.0'); + + +/***/ }), + +/***/ 6098: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +var ms = __nccwpck_require__(900); + +module.exports = function (time, iat) { + var timestamp = iat || Math.floor(Date.now() / 1000); + + if (typeof time === 'string') { + var milliseconds = ms(time); + if (typeof milliseconds === 'undefined') { + return; + } + return Math.floor(timestamp + milliseconds / 1000); + } else if (typeof time === 'number') { + return timestamp + time; + } else { + return; + } + +}; + +/***/ }), + +/***/ 7596: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +const ASYMMETRIC_KEY_DETAILS_SUPPORTED = __nccwpck_require__(7622); +const RSA_PSS_KEY_DETAILS_SUPPORTED = __nccwpck_require__(5170); + +const allowedAlgorithmsForKeys = { + 'ec': ['ES256', 'ES384', 'ES512'], + 'rsa': ['RS256', 'PS256', 'RS384', 'PS384', 'RS512', 'PS512'], + 'rsa-pss': ['PS256', 'PS384', 'PS512'] +}; + +const allowedCurves = { + ES256: 'prime256v1', + ES384: 'secp384r1', + ES512: 'secp521r1', +}; + +module.exports = function(algorithm, key) { + if (!algorithm || !key) return; + + const keyType = key.asymmetricKeyType; + if (!keyType) return; + + const allowedAlgorithms = allowedAlgorithmsForKeys[keyType]; + + if (!allowedAlgorithms) { + throw new Error(`Unknown key type "${keyType}".`); + } + + if (!allowedAlgorithms.includes(algorithm)) { + throw new Error(`"alg" parameter for "${keyType}" key type must be one of: ${allowedAlgorithms.join(', ')}.`) + } + + /* + * Ignore the next block from test coverage because it gets executed + * conditionally depending on the Node version. Not ignoring it would + * prevent us from reaching the target % of coverage for versions of + * Node under 15.7.0. + */ + /* istanbul ignore next */ + if (ASYMMETRIC_KEY_DETAILS_SUPPORTED) { + switch (keyType) { + case 'ec': + const keyCurve = key.asymmetricKeyDetails.namedCurve; + const allowedCurve = allowedCurves[algorithm]; + + if (keyCurve !== allowedCurve) { + throw new Error(`"alg" parameter "${algorithm}" requires curve "${allowedCurve}".`); + } + break; + + case 'rsa-pss': + if (RSA_PSS_KEY_DETAILS_SUPPORTED) { + const length = parseInt(algorithm.slice(-3), 10); + const { hashAlgorithm, mgf1HashAlgorithm, saltLength } = key.asymmetricKeyDetails; + + if (hashAlgorithm !== `sha${length}` || mgf1HashAlgorithm !== hashAlgorithm) { + throw new Error(`Invalid key for this operation, its RSA-PSS parameters do not meet the requirements of "alg" ${algorithm}.`); + } + + if (saltLength !== undefined && saltLength > length >> 3) { + throw new Error(`Invalid key for this operation, its RSA-PSS parameter saltLength does not meet the requirements of "alg" ${algorithm}.`) + } + } + break; + } + } +} + + +/***/ }), + +/***/ 2321: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +var bufferEqual = __nccwpck_require__(9239); +var Buffer = (__nccwpck_require__(1867).Buffer); +var crypto = __nccwpck_require__(6113); +var formatEcdsa = __nccwpck_require__(1728); +var util = __nccwpck_require__(3837); + +var MSG_INVALID_ALGORITHM = '"%s" is not a valid algorithm.\n Supported algorithms are:\n "HS256", "HS384", "HS512", "RS256", "RS384", "RS512", "PS256", "PS384", "PS512", "ES256", "ES384", "ES512" and "none".' +var MSG_INVALID_SECRET = 'secret must be a string or buffer'; +var MSG_INVALID_VERIFIER_KEY = 'key must be a string or a buffer'; +var MSG_INVALID_SIGNER_KEY = 'key must be a string, a buffer or an object'; + +var supportsKeyObjects = typeof crypto.createPublicKey === 'function'; +if (supportsKeyObjects) { + MSG_INVALID_VERIFIER_KEY += ' or a KeyObject'; + MSG_INVALID_SECRET += 'or a KeyObject'; +} + +function checkIsPublicKey(key) { + if (Buffer.isBuffer(key)) { + return; + } + + if (typeof key === 'string') { + return; + } + + if (!supportsKeyObjects) { + throw typeError(MSG_INVALID_VERIFIER_KEY); + } + + if (typeof key !== 'object') { + throw typeError(MSG_INVALID_VERIFIER_KEY); + } + + if (typeof key.type !== 'string') { + throw typeError(MSG_INVALID_VERIFIER_KEY); + } + + if (typeof key.asymmetricKeyType !== 'string') { + throw typeError(MSG_INVALID_VERIFIER_KEY); + } + + if (typeof key.export !== 'function') { + throw typeError(MSG_INVALID_VERIFIER_KEY); + } +}; + +function checkIsPrivateKey(key) { + if (Buffer.isBuffer(key)) { + return; + } + + if (typeof key === 'string') { + return; + } + + if (typeof key === 'object') { + return; + } + + throw typeError(MSG_INVALID_SIGNER_KEY); +}; + +function checkIsSecretKey(key) { + if (Buffer.isBuffer(key)) { + return; + } + + if (typeof key === 'string') { + return key; + } + + if (!supportsKeyObjects) { + throw typeError(MSG_INVALID_SECRET); + } + + if (typeof key !== 'object') { + throw typeError(MSG_INVALID_SECRET); + } + + if (key.type !== 'secret') { + throw typeError(MSG_INVALID_SECRET); + } + + if (typeof key.export !== 'function') { + throw typeError(MSG_INVALID_SECRET); + } +} + +function fromBase64(base64) { + return base64 + .replace(/=/g, '') + .replace(/\+/g, '-') + .replace(/\//g, '_'); +} + +function toBase64(base64url) { + base64url = base64url.toString(); + + var padding = 4 - base64url.length % 4; + if (padding !== 4) { + for (var i = 0; i < padding; ++i) { + base64url += '='; + } + } + + return base64url + .replace(/\-/g, '+') + .replace(/_/g, '/'); +} + +function typeError(template) { + var args = [].slice.call(arguments, 1); + var errMsg = util.format.bind(util, template).apply(null, args); + return new TypeError(errMsg); +} + +function bufferOrString(obj) { + return Buffer.isBuffer(obj) || typeof obj === 'string'; +} + +function normalizeInput(thing) { + if (!bufferOrString(thing)) + thing = JSON.stringify(thing); + return thing; +} + +function createHmacSigner(bits) { + return function sign(thing, secret) { + checkIsSecretKey(secret); + thing = normalizeInput(thing); + var hmac = crypto.createHmac('sha' + bits, secret); + var sig = (hmac.update(thing), hmac.digest('base64')) + return fromBase64(sig); + } +} + +function createHmacVerifier(bits) { + return function verify(thing, signature, secret) { + var computedSig = createHmacSigner(bits)(thing, secret); + return bufferEqual(Buffer.from(signature), Buffer.from(computedSig)); + } +} + +function createKeySigner(bits) { + return function sign(thing, privateKey) { + checkIsPrivateKey(privateKey); + thing = normalizeInput(thing); + // Even though we are specifying "RSA" here, this works with ECDSA + // keys as well. + var signer = crypto.createSign('RSA-SHA' + bits); + var sig = (signer.update(thing), signer.sign(privateKey, 'base64')); + return fromBase64(sig); + } +} + +function createKeyVerifier(bits) { + return function verify(thing, signature, publicKey) { + checkIsPublicKey(publicKey); + thing = normalizeInput(thing); + signature = toBase64(signature); + var verifier = crypto.createVerify('RSA-SHA' + bits); + verifier.update(thing); + return verifier.verify(publicKey, signature, 'base64'); + } +} + +function createPSSKeySigner(bits) { + return function sign(thing, privateKey) { + checkIsPrivateKey(privateKey); + thing = normalizeInput(thing); + var signer = crypto.createSign('RSA-SHA' + bits); + var sig = (signer.update(thing), signer.sign({ + key: privateKey, + padding: crypto.constants.RSA_PKCS1_PSS_PADDING, + saltLength: crypto.constants.RSA_PSS_SALTLEN_DIGEST + }, 'base64')); + return fromBase64(sig); + } +} + +function createPSSKeyVerifier(bits) { + return function verify(thing, signature, publicKey) { + checkIsPublicKey(publicKey); + thing = normalizeInput(thing); + signature = toBase64(signature); + var verifier = crypto.createVerify('RSA-SHA' + bits); + verifier.update(thing); + return verifier.verify({ + key: publicKey, + padding: crypto.constants.RSA_PKCS1_PSS_PADDING, + saltLength: crypto.constants.RSA_PSS_SALTLEN_DIGEST + }, signature, 'base64'); + } +} + +function createECDSASigner(bits) { + var inner = createKeySigner(bits); + return function sign() { + var signature = inner.apply(null, arguments); + signature = formatEcdsa.derToJose(signature, 'ES' + bits); + return signature; + }; +} + +function createECDSAVerifer(bits) { + var inner = createKeyVerifier(bits); + return function verify(thing, signature, publicKey) { + signature = formatEcdsa.joseToDer(signature, 'ES' + bits).toString('base64'); + var result = inner(thing, signature, publicKey); + return result; + }; +} + +function createNoneSigner() { + return function sign() { + return ''; + } +} + +function createNoneVerifier() { + return function verify(thing, signature) { + return signature === ''; + } +} + +module.exports = function jwa(algorithm) { + var signerFactories = { + hs: createHmacSigner, + rs: createKeySigner, + ps: createPSSKeySigner, + es: createECDSASigner, + none: createNoneSigner, + } + var verifierFactories = { + hs: createHmacVerifier, + rs: createKeyVerifier, + ps: createPSSKeyVerifier, + es: createECDSAVerifer, + none: createNoneVerifier, + } + var match = algorithm.match(/^(RS|PS|ES|HS)(256|384|512)$|^(none)$/i); + if (!match) + throw typeError(MSG_INVALID_ALGORITHM, algorithm); + var algo = (match[1] || match[3]).toLowerCase(); + var bits = match[2]; + + return { + sign: signerFactories[algo](bits), + verify: verifierFactories[algo](bits), + } +}; + + +/***/ }), + +/***/ 2597: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +/*global exports*/ +var SignStream = __nccwpck_require__(5070); +var VerifyStream = __nccwpck_require__(3974); + +var ALGORITHMS = [ + 'HS256', 'HS384', 'HS512', + 'RS256', 'RS384', 'RS512', + 'PS256', 'PS384', 'PS512', + 'ES256', 'ES384', 'ES512' +]; + +exports.ALGORITHMS = ALGORITHMS; +exports.sign = SignStream.sign; +exports.verify = VerifyStream.verify; +exports.decode = VerifyStream.decode; +exports.isValid = VerifyStream.isValid; +exports.createSign = function createSign(opts) { + return new SignStream(opts); +}; +exports.createVerify = function createVerify(opts) { + return new VerifyStream(opts); +}; + + +/***/ }), + +/***/ 704: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +/*global module, process*/ +var Buffer = (__nccwpck_require__(1867).Buffer); +var Stream = __nccwpck_require__(2781); +var util = __nccwpck_require__(3837); + +function DataStream(data) { + this.buffer = null; + this.writable = true; + this.readable = true; + + // No input + if (!data) { + this.buffer = Buffer.alloc(0); + return this; + } + + // Stream + if (typeof data.pipe === 'function') { + this.buffer = Buffer.alloc(0); + data.pipe(this); + return this; + } + + // Buffer or String + // or Object (assumedly a passworded key) + if (data.length || typeof data === 'object') { + this.buffer = data; + this.writable = false; + process.nextTick(function () { + this.emit('end', data); + this.readable = false; + this.emit('close'); + }.bind(this)); + return this; + } + + throw new TypeError('Unexpected data type ('+ typeof data + ')'); +} +util.inherits(DataStream, Stream); + +DataStream.prototype.write = function write(data) { + this.buffer = Buffer.concat([this.buffer, Buffer.from(data)]); + this.emit('data', data); +}; + +DataStream.prototype.end = function end(data) { + if (data) + this.write(data); + this.emit('end', data); + this.emit('close'); + this.writable = false; + this.readable = false; +}; + +module.exports = DataStream; + + +/***/ }), + +/***/ 5070: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +/*global module*/ +var Buffer = (__nccwpck_require__(1867).Buffer); +var DataStream = __nccwpck_require__(704); +var jwa = __nccwpck_require__(2321); +var Stream = __nccwpck_require__(2781); +var toString = __nccwpck_require__(6206); +var util = __nccwpck_require__(3837); + +function base64url(string, encoding) { + return Buffer + .from(string, encoding) + .toString('base64') + .replace(/=/g, '') + .replace(/\+/g, '-') + .replace(/\//g, '_'); +} + +function jwsSecuredInput(header, payload, encoding) { + encoding = encoding || 'utf8'; + var encodedHeader = base64url(toString(header), 'binary'); + var encodedPayload = base64url(toString(payload), encoding); + return util.format('%s.%s', encodedHeader, encodedPayload); +} + +function jwsSign(opts) { + var header = opts.header; + var payload = opts.payload; + var secretOrKey = opts.secret || opts.privateKey; + var encoding = opts.encoding; + var algo = jwa(header.alg); + var securedInput = jwsSecuredInput(header, payload, encoding); + var signature = algo.sign(securedInput, secretOrKey); + return util.format('%s.%s', securedInput, signature); +} + +function SignStream(opts) { + var secret = opts.secret||opts.privateKey||opts.key; + var secretStream = new DataStream(secret); + this.readable = true; + this.header = opts.header; + this.encoding = opts.encoding; + this.secret = this.privateKey = this.key = secretStream; + this.payload = new DataStream(opts.payload); + this.secret.once('close', function () { + if (!this.payload.writable && this.readable) + this.sign(); + }.bind(this)); + + this.payload.once('close', function () { + if (!this.secret.writable && this.readable) + this.sign(); + }.bind(this)); +} +util.inherits(SignStream, Stream); + +SignStream.prototype.sign = function sign() { + try { + var signature = jwsSign({ + header: this.header, + payload: this.payload.buffer, + secret: this.secret.buffer, + encoding: this.encoding + }); + this.emit('done', signature); + this.emit('data', signature); + this.emit('end'); + this.readable = false; + return signature; + } catch (e) { + this.readable = false; + this.emit('error', e); + this.emit('close'); + } +}; + +SignStream.sign = jwsSign; + +module.exports = SignStream; + + +/***/ }), + +/***/ 6206: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +/*global module*/ +var Buffer = (__nccwpck_require__(4300).Buffer); + +module.exports = function toString(obj) { + if (typeof obj === 'string') + return obj; + if (typeof obj === 'number' || Buffer.isBuffer(obj)) + return obj.toString(); + return JSON.stringify(obj); +}; + + +/***/ }), + +/***/ 3974: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +/*global module*/ +var Buffer = (__nccwpck_require__(1867).Buffer); +var DataStream = __nccwpck_require__(704); +var jwa = __nccwpck_require__(2321); +var Stream = __nccwpck_require__(2781); +var toString = __nccwpck_require__(6206); +var util = __nccwpck_require__(3837); +var JWS_REGEX = /^[a-zA-Z0-9\-_]+?\.[a-zA-Z0-9\-_]+?\.([a-zA-Z0-9\-_]+)?$/; + +function isObject(thing) { + return Object.prototype.toString.call(thing) === '[object Object]'; +} + +function safeJsonParse(thing) { + if (isObject(thing)) + return thing; + try { return JSON.parse(thing); } + catch (e) { return undefined; } +} + +function headerFromJWS(jwsSig) { + var encodedHeader = jwsSig.split('.', 1)[0]; + return safeJsonParse(Buffer.from(encodedHeader, 'base64').toString('binary')); +} + +function securedInputFromJWS(jwsSig) { + return jwsSig.split('.', 2).join('.'); +} + +function signatureFromJWS(jwsSig) { + return jwsSig.split('.')[2]; +} + +function payloadFromJWS(jwsSig, encoding) { + encoding = encoding || 'utf8'; + var payload = jwsSig.split('.')[1]; + return Buffer.from(payload, 'base64').toString(encoding); +} + +function isValidJws(string) { + return JWS_REGEX.test(string) && !!headerFromJWS(string); +} + +function jwsVerify(jwsSig, algorithm, secretOrKey) { + if (!algorithm) { + var err = new Error("Missing algorithm parameter for jws.verify"); + err.code = "MISSING_ALGORITHM"; + throw err; + } + jwsSig = toString(jwsSig); + var signature = signatureFromJWS(jwsSig); + var securedInput = securedInputFromJWS(jwsSig); + var algo = jwa(algorithm); + return algo.verify(securedInput, signature, secretOrKey); +} + +function jwsDecode(jwsSig, opts) { + opts = opts || {}; + jwsSig = toString(jwsSig); + + if (!isValidJws(jwsSig)) + return null; + + var header = headerFromJWS(jwsSig); + + if (!header) + return null; + + var payload = payloadFromJWS(jwsSig); + if (header.typ === 'JWT' || opts.json) + payload = JSON.parse(payload, opts.encoding); + + return { + header: header, + payload: payload, + signature: signatureFromJWS(jwsSig) + }; +} + +function VerifyStream(opts) { + opts = opts || {}; + var secretOrKey = opts.secret||opts.publicKey||opts.key; + var secretStream = new DataStream(secretOrKey); + this.readable = true; + this.algorithm = opts.algorithm; + this.encoding = opts.encoding; + this.secret = this.publicKey = this.key = secretStream; + this.signature = new DataStream(opts.signature); + this.secret.once('close', function () { + if (!this.signature.writable && this.readable) + this.verify(); + }.bind(this)); + + this.signature.once('close', function () { + if (!this.secret.writable && this.readable) + this.verify(); + }.bind(this)); +} +util.inherits(VerifyStream, Stream); +VerifyStream.prototype.verify = function verify() { + try { + var valid = jwsVerify(this.signature.buffer, this.algorithm, this.key.buffer); + var obj = jwsDecode(this.signature.buffer, this.encoding); + this.emit('done', valid, obj); + this.emit('data', valid); + this.emit('end'); + this.readable = false; + return valid; + } catch (e) { + this.readable = false; + this.emit('error', e); + this.emit('close'); + } +}; + +VerifyStream.decode = jwsDecode; +VerifyStream.isValid = isValidJws; +VerifyStream.verify = jwsVerify; + +module.exports = VerifyStream; + + +/***/ }), + +/***/ 2022: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +const timespan = __nccwpck_require__(6098); +const PS_SUPPORTED = __nccwpck_require__(9085); +const validateAsymmetricKey = __nccwpck_require__(7596); +const jws = __nccwpck_require__(2597); +const {includes, isBoolean, isInteger, isNumber, isPlainObject, isString, once} = __nccwpck_require__(250) +const { KeyObject, createSecretKey, createPrivateKey } = __nccwpck_require__(6113) + +const SUPPORTED_ALGS = ['RS256', 'RS384', 'RS512', 'ES256', 'ES384', 'ES512', 'HS256', 'HS384', 'HS512', 'none']; +if (PS_SUPPORTED) { + SUPPORTED_ALGS.splice(3, 0, 'PS256', 'PS384', 'PS512'); +} + +const sign_options_schema = { + expiresIn: { isValid: function(value) { return isInteger(value) || (isString(value) && value); }, message: '"expiresIn" should be a number of seconds or string representing a timespan' }, + notBefore: { isValid: function(value) { return isInteger(value) || (isString(value) && value); }, message: '"notBefore" should be a number of seconds or string representing a timespan' }, + audience: { isValid: function(value) { return isString(value) || Array.isArray(value); }, message: '"audience" must be a string or array' }, + algorithm: { isValid: includes.bind(null, SUPPORTED_ALGS), message: '"algorithm" must be a valid string enum value' }, + header: { isValid: isPlainObject, message: '"header" must be an object' }, + encoding: { isValid: isString, message: '"encoding" must be a string' }, + issuer: { isValid: isString, message: '"issuer" must be a string' }, + subject: { isValid: isString, message: '"subject" must be a string' }, + jwtid: { isValid: isString, message: '"jwtid" must be a string' }, + noTimestamp: { isValid: isBoolean, message: '"noTimestamp" must be a boolean' }, + keyid: { isValid: isString, message: '"keyid" must be a string' }, + mutatePayload: { isValid: isBoolean, message: '"mutatePayload" must be a boolean' }, + allowInsecureKeySizes: { isValid: isBoolean, message: '"allowInsecureKeySizes" must be a boolean'}, + allowInvalidAsymmetricKeyTypes: { isValid: isBoolean, message: '"allowInvalidAsymmetricKeyTypes" must be a boolean'} +}; + +const registered_claims_schema = { + iat: { isValid: isNumber, message: '"iat" should be a number of seconds' }, + exp: { isValid: isNumber, message: '"exp" should be a number of seconds' }, + nbf: { isValid: isNumber, message: '"nbf" should be a number of seconds' } +}; + +function validate(schema, allowUnknown, object, parameterName) { + if (!isPlainObject(object)) { + throw new Error('Expected "' + parameterName + '" to be a plain object.'); + } + Object.keys(object) + .forEach(function(key) { + const validator = schema[key]; + if (!validator) { + if (!allowUnknown) { + throw new Error('"' + key + '" is not allowed in "' + parameterName + '"'); + } + return; + } + if (!validator.isValid(object[key])) { + throw new Error(validator.message); + } + }); +} + +function validateOptions(options) { + return validate(sign_options_schema, false, options, 'options'); +} + +function validatePayload(payload) { + return validate(registered_claims_schema, true, payload, 'payload'); +} + +const options_to_payload = { + 'audience': 'aud', + 'issuer': 'iss', + 'subject': 'sub', + 'jwtid': 'jti' +}; + +const options_for_objects = [ + 'expiresIn', + 'notBefore', + 'noTimestamp', + 'audience', + 'issuer', + 'subject', + 'jwtid', +]; + +module.exports = function (payload, secretOrPrivateKey, options, callback) { + if (typeof options === 'function') { + callback = options; + options = {}; + } else { + options = options || {}; + } + + const isObjectPayload = typeof payload === 'object' && + !Buffer.isBuffer(payload); + + const header = Object.assign({ + alg: options.algorithm || 'HS256', + typ: isObjectPayload ? 'JWT' : undefined, + kid: options.keyid + }, options.header); + + function failure(err) { + if (callback) { + return callback(err); + } + throw err; + } + + if (!secretOrPrivateKey && options.algorithm !== 'none') { + return failure(new Error('secretOrPrivateKey must have a value')); + } + + if (secretOrPrivateKey != null && !(secretOrPrivateKey instanceof KeyObject)) { + try { + secretOrPrivateKey = createPrivateKey(secretOrPrivateKey) + } catch (_) { + try { + secretOrPrivateKey = createSecretKey(typeof secretOrPrivateKey === 'string' ? Buffer.from(secretOrPrivateKey) : secretOrPrivateKey) + } catch (_) { + return failure(new Error('secretOrPrivateKey is not valid key material')); + } + } + } + + if (header.alg.startsWith('HS') && secretOrPrivateKey.type !== 'secret') { + return failure(new Error((`secretOrPrivateKey must be a symmetric key when using ${header.alg}`))) + } else if (/^(?:RS|PS|ES)/.test(header.alg)) { + if (secretOrPrivateKey.type !== 'private') { + return failure(new Error((`secretOrPrivateKey must be an asymmetric key when using ${header.alg}`))) + } + if (!options.allowInsecureKeySizes && + !header.alg.startsWith('ES') && + secretOrPrivateKey.asymmetricKeyDetails !== undefined && //KeyObject.asymmetricKeyDetails is supported in Node 15+ + secretOrPrivateKey.asymmetricKeyDetails.modulusLength < 2048) { + return failure(new Error(`secretOrPrivateKey has a minimum key size of 2048 bits for ${header.alg}`)); + } + } + + if (typeof payload === 'undefined') { + return failure(new Error('payload is required')); + } else if (isObjectPayload) { + try { + validatePayload(payload); + } + catch (error) { + return failure(error); + } + if (!options.mutatePayload) { + payload = Object.assign({},payload); + } + } else { + const invalid_options = options_for_objects.filter(function (opt) { + return typeof options[opt] !== 'undefined'; + }); + + if (invalid_options.length > 0) { + return failure(new Error('invalid ' + invalid_options.join(',') + ' option for ' + (typeof payload ) + ' payload')); + } + } + + if (typeof payload.exp !== 'undefined' && typeof options.expiresIn !== 'undefined') { + return failure(new Error('Bad "options.expiresIn" option the payload already has an "exp" property.')); + } + + if (typeof payload.nbf !== 'undefined' && typeof options.notBefore !== 'undefined') { + return failure(new Error('Bad "options.notBefore" option the payload already has an "nbf" property.')); + } + + try { + validateOptions(options); + } + catch (error) { + return failure(error); + } + + if (!options.allowInvalidAsymmetricKeyTypes) { + try { + validateAsymmetricKey(header.alg, secretOrPrivateKey); + } catch (error) { + return failure(error); + } + } + + const timestamp = payload.iat || Math.floor(Date.now() / 1000); + + if (options.noTimestamp) { + delete payload.iat; + } else if (isObjectPayload) { + payload.iat = timestamp; + } + + if (typeof options.notBefore !== 'undefined') { + try { + payload.nbf = timespan(options.notBefore, timestamp); + } + catch (err) { + return failure(err); + } + if (typeof payload.nbf === 'undefined') { + return failure(new Error('"notBefore" should be a number of seconds or string representing a timespan eg: "1d", "20h", 60')); + } + } + + if (typeof options.expiresIn !== 'undefined' && typeof payload === 'object') { + try { + payload.exp = timespan(options.expiresIn, timestamp); + } + catch (err) { + return failure(err); + } + if (typeof payload.exp === 'undefined') { + return failure(new Error('"expiresIn" should be a number of seconds or string representing a timespan eg: "1d", "20h", 60')); + } + } + + Object.keys(options_to_payload).forEach(function (key) { + const claim = options_to_payload[key]; + if (typeof options[key] !== 'undefined') { + if (typeof payload[claim] !== 'undefined') { + return failure(new Error('Bad "options.' + key + '" option. The payload already has an "' + claim + '" property.')); + } + payload[claim] = options[key]; + } + }); + + const encoding = options.encoding || 'utf8'; + + if (typeof callback === 'function') { + callback = callback && once(callback); + + jws.createSign({ + header: header, + privateKey: secretOrPrivateKey, + payload: payload, + encoding: encoding + }).once('error', callback) + .once('done', function (signature) { + // TODO: Remove in favor of the modulus length check before signing once node 15+ is the minimum supported version + if(!options.allowInsecureKeySizes && /^(?:RS|PS)/.test(header.alg) && signature.length < 256) { + return callback(new Error(`secretOrPrivateKey has a minimum key size of 2048 bits for ${header.alg}`)) + } + callback(null, signature); + }); + } else { + let signature = jws.sign({header: header, payload: payload, secret: secretOrPrivateKey, encoding: encoding}); + // TODO: Remove in favor of the modulus length check before signing once node 15+ is the minimum supported version + if(!options.allowInsecureKeySizes && /^(?:RS|PS)/.test(header.alg) && signature.length < 256) { + throw new Error(`secretOrPrivateKey has a minimum key size of 2048 bits for ${header.alg}`) + } + return signature + } +}; + + +/***/ }), + +/***/ 2327: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +const JsonWebTokenError = __nccwpck_require__(405); +const NotBeforeError = __nccwpck_require__(4383); +const TokenExpiredError = __nccwpck_require__(6637); +const decode = __nccwpck_require__(3359); +const timespan = __nccwpck_require__(6098); +const validateAsymmetricKey = __nccwpck_require__(7596); +const PS_SUPPORTED = __nccwpck_require__(9085); +const jws = __nccwpck_require__(2597); +const {KeyObject, createSecretKey, createPublicKey} = __nccwpck_require__(6113); + +const PUB_KEY_ALGS = ['RS256', 'RS384', 'RS512']; +const EC_KEY_ALGS = ['ES256', 'ES384', 'ES512']; +const RSA_KEY_ALGS = ['RS256', 'RS384', 'RS512']; +const HS_ALGS = ['HS256', 'HS384', 'HS512']; + +if (PS_SUPPORTED) { + PUB_KEY_ALGS.splice(PUB_KEY_ALGS.length, 0, 'PS256', 'PS384', 'PS512'); + RSA_KEY_ALGS.splice(RSA_KEY_ALGS.length, 0, 'PS256', 'PS384', 'PS512'); +} + +module.exports = function (jwtString, secretOrPublicKey, options, callback) { + if ((typeof options === 'function') && !callback) { + callback = options; + options = {}; + } + + if (!options) { + options = {}; + } + + //clone this object since we are going to mutate it. + options = Object.assign({}, options); + + let done; + + if (callback) { + done = callback; + } else { + done = function(err, data) { + if (err) throw err; + return data; + }; + } + + if (options.clockTimestamp && typeof options.clockTimestamp !== 'number') { + return done(new JsonWebTokenError('clockTimestamp must be a number')); + } + + if (options.nonce !== undefined && (typeof options.nonce !== 'string' || options.nonce.trim() === '')) { + return done(new JsonWebTokenError('nonce must be a non-empty string')); + } + + if (options.allowInvalidAsymmetricKeyTypes !== undefined && typeof options.allowInvalidAsymmetricKeyTypes !== 'boolean') { + return done(new JsonWebTokenError('allowInvalidAsymmetricKeyTypes must be a boolean')); + } + + const clockTimestamp = options.clockTimestamp || Math.floor(Date.now() / 1000); + + if (!jwtString){ + return done(new JsonWebTokenError('jwt must be provided')); + } + + if (typeof jwtString !== 'string') { + return done(new JsonWebTokenError('jwt must be a string')); + } + + const parts = jwtString.split('.'); + + if (parts.length !== 3){ + return done(new JsonWebTokenError('jwt malformed')); + } + + let decodedToken; + + try { + decodedToken = decode(jwtString, { complete: true }); + } catch(err) { + return done(err); + } + + if (!decodedToken) { + return done(new JsonWebTokenError('invalid token')); + } + + const header = decodedToken.header; + let getSecret; + + if(typeof secretOrPublicKey === 'function') { + if(!callback) { + return done(new JsonWebTokenError('verify must be called asynchronous if secret or public key is provided as a callback')); + } + + getSecret = secretOrPublicKey; + } + else { + getSecret = function(header, secretCallback) { + return secretCallback(null, secretOrPublicKey); + }; + } + + return getSecret(header, function(err, secretOrPublicKey) { + if(err) { + return done(new JsonWebTokenError('error in secret or public key callback: ' + err.message)); + } + + const hasSignature = parts[2].trim() !== ''; + + if (!hasSignature && secretOrPublicKey){ + return done(new JsonWebTokenError('jwt signature is required')); + } + + if (hasSignature && !secretOrPublicKey) { + return done(new JsonWebTokenError('secret or public key must be provided')); + } + + if (!hasSignature && !options.algorithms) { + return done(new JsonWebTokenError('please specify "none" in "algorithms" to verify unsigned tokens')); + } + + if (secretOrPublicKey != null && !(secretOrPublicKey instanceof KeyObject)) { + try { + secretOrPublicKey = createPublicKey(secretOrPublicKey); + } catch (_) { + try { + secretOrPublicKey = createSecretKey(typeof secretOrPublicKey === 'string' ? Buffer.from(secretOrPublicKey) : secretOrPublicKey); + } catch (_) { + return done(new JsonWebTokenError('secretOrPublicKey is not valid key material')) + } + } + } + + if (!options.algorithms) { + if (secretOrPublicKey.type === 'secret') { + options.algorithms = HS_ALGS; + } else if (['rsa', 'rsa-pss'].includes(secretOrPublicKey.asymmetricKeyType)) { + options.algorithms = RSA_KEY_ALGS + } else if (secretOrPublicKey.asymmetricKeyType === 'ec') { + options.algorithms = EC_KEY_ALGS + } else { + options.algorithms = PUB_KEY_ALGS + } + } + + if (options.algorithms.indexOf(decodedToken.header.alg) === -1) { + return done(new JsonWebTokenError('invalid algorithm')); + } + + if (header.alg.startsWith('HS') && secretOrPublicKey.type !== 'secret') { + return done(new JsonWebTokenError((`secretOrPublicKey must be a symmetric key when using ${header.alg}`))) + } else if (/^(?:RS|PS|ES)/.test(header.alg) && secretOrPublicKey.type !== 'public') { + return done(new JsonWebTokenError((`secretOrPublicKey must be an asymmetric key when using ${header.alg}`))) + } + + if (!options.allowInvalidAsymmetricKeyTypes) { + try { + validateAsymmetricKey(header.alg, secretOrPublicKey); + } catch (e) { + return done(e); + } + } + + let valid; + + try { + valid = jws.verify(jwtString, decodedToken.header.alg, secretOrPublicKey); + } catch (e) { + return done(e); + } + + if (!valid) { + return done(new JsonWebTokenError('invalid signature')); + } + + const payload = decodedToken.payload; + + if (typeof payload.nbf !== 'undefined' && !options.ignoreNotBefore) { + if (typeof payload.nbf !== 'number') { + return done(new JsonWebTokenError('invalid nbf value')); + } + if (payload.nbf > clockTimestamp + (options.clockTolerance || 0)) { + return done(new NotBeforeError('jwt not active', new Date(payload.nbf * 1000))); + } + } + + if (typeof payload.exp !== 'undefined' && !options.ignoreExpiration) { + if (typeof payload.exp !== 'number') { + return done(new JsonWebTokenError('invalid exp value')); + } + if (clockTimestamp >= payload.exp + (options.clockTolerance || 0)) { + return done(new TokenExpiredError('jwt expired', new Date(payload.exp * 1000))); + } + } + + if (options.audience) { + const audiences = Array.isArray(options.audience) ? options.audience : [options.audience]; + const target = Array.isArray(payload.aud) ? payload.aud : [payload.aud]; + + const match = target.some(function (targetAudience) { + return audiences.some(function (audience) { + return audience instanceof RegExp ? audience.test(targetAudience) : audience === targetAudience; + }); + }); + + if (!match) { + return done(new JsonWebTokenError('jwt audience invalid. expected: ' + audiences.join(' or '))); + } + } + + if (options.issuer) { + const invalid_issuer = + (typeof options.issuer === 'string' && payload.iss !== options.issuer) || + (Array.isArray(options.issuer) && options.issuer.indexOf(payload.iss) === -1); + + if (invalid_issuer) { + return done(new JsonWebTokenError('jwt issuer invalid. expected: ' + options.issuer)); + } + } + + if (options.subject) { + if (payload.sub !== options.subject) { + return done(new JsonWebTokenError('jwt subject invalid. expected: ' + options.subject)); + } + } + + if (options.jwtid) { + if (payload.jti !== options.jwtid) { + return done(new JsonWebTokenError('jwt jwtid invalid. expected: ' + options.jwtid)); + } + } + + if (options.nonce) { + if (payload.nonce !== options.nonce) { + return done(new JsonWebTokenError('jwt nonce invalid. expected: ' + options.nonce)); + } + } + + if (options.maxAge) { + if (typeof payload.iat !== 'number') { + return done(new JsonWebTokenError('iat required when maxAge is specified')); + } + + const maxAgeTimestamp = timespan(options.maxAge, payload.iat); + if (typeof maxAgeTimestamp === 'undefined') { + return done(new JsonWebTokenError('"maxAge" should be a number of seconds or string representing a timespan eg: "1d", "20h", 60')); + } + if (clockTimestamp >= maxAgeTimestamp + (options.clockTolerance || 0)) { + return done(new TokenExpiredError('maxAge exceeded', new Date(maxAgeTimestamp * 1000))); + } + } + + if (options.complete === true) { + const signature = decodedToken.signature; + + return done(null, { + header: header, + payload: payload, + signature: signature + }); + } + + return done(null, payload); + }); +}; + + +/***/ }), + +/***/ 250: +/***/ (function(module, exports, __nccwpck_require__) { + +/* module decorator */ module = __nccwpck_require__.nmd(module); +/** + * @license + * Lodash + * Copyright OpenJS Foundation and other contributors + * Released under MIT license + * Based on Underscore.js 1.8.3 + * Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors + */ +;(function() { + + /** Used as a safe reference for `undefined` in pre-ES5 environments. */ + var undefined; + + /** Used as the semantic version number. */ + var VERSION = '4.17.21'; + + /** Used as the size to enable large array optimizations. */ + var LARGE_ARRAY_SIZE = 200; + + /** Error message constants. */ + var CORE_ERROR_TEXT = 'Unsupported core-js use. Try https://npms.io/search?q=ponyfill.', + FUNC_ERROR_TEXT = 'Expected a function', + INVALID_TEMPL_VAR_ERROR_TEXT = 'Invalid `variable` option passed into `_.template`'; + + /** Used to stand-in for `undefined` hash values. */ + var HASH_UNDEFINED = '__lodash_hash_undefined__'; + + /** Used as the maximum memoize cache size. */ + var MAX_MEMOIZE_SIZE = 500; + + /** Used as the internal argument placeholder. */ + var PLACEHOLDER = '__lodash_placeholder__'; + + /** Used to compose bitmasks for cloning. */ + var CLONE_DEEP_FLAG = 1, + CLONE_FLAT_FLAG = 2, + CLONE_SYMBOLS_FLAG = 4; + + /** Used to compose bitmasks for value comparisons. */ + var COMPARE_PARTIAL_FLAG = 1, + COMPARE_UNORDERED_FLAG = 2; + + /** Used to compose bitmasks for function metadata. */ + var WRAP_BIND_FLAG = 1, + WRAP_BIND_KEY_FLAG = 2, + WRAP_CURRY_BOUND_FLAG = 4, + WRAP_CURRY_FLAG = 8, + WRAP_CURRY_RIGHT_FLAG = 16, + WRAP_PARTIAL_FLAG = 32, + WRAP_PARTIAL_RIGHT_FLAG = 64, + WRAP_ARY_FLAG = 128, + WRAP_REARG_FLAG = 256, + WRAP_FLIP_FLAG = 512; + + /** Used as default options for `_.truncate`. */ + var DEFAULT_TRUNC_LENGTH = 30, + DEFAULT_TRUNC_OMISSION = '...'; + + /** Used to detect hot functions by number of calls within a span of milliseconds. */ + var HOT_COUNT = 800, + HOT_SPAN = 16; + + /** Used to indicate the type of lazy iteratees. */ + var LAZY_FILTER_FLAG = 1, + LAZY_MAP_FLAG = 2, + LAZY_WHILE_FLAG = 3; + + /** Used as references for various `Number` constants. */ + var INFINITY = 1 / 0, + MAX_SAFE_INTEGER = 9007199254740991, + MAX_INTEGER = 1.7976931348623157e+308, + NAN = 0 / 0; + + /** Used as references for the maximum length and index of an array. */ + var MAX_ARRAY_LENGTH = 4294967295, + MAX_ARRAY_INDEX = MAX_ARRAY_LENGTH - 1, + HALF_MAX_ARRAY_LENGTH = MAX_ARRAY_LENGTH >>> 1; + + /** Used to associate wrap methods with their bit flags. */ + var wrapFlags = [ + ['ary', WRAP_ARY_FLAG], + ['bind', WRAP_BIND_FLAG], + ['bindKey', WRAP_BIND_KEY_FLAG], + ['curry', WRAP_CURRY_FLAG], + ['curryRight', WRAP_CURRY_RIGHT_FLAG], + ['flip', WRAP_FLIP_FLAG], + ['partial', WRAP_PARTIAL_FLAG], + ['partialRight', WRAP_PARTIAL_RIGHT_FLAG], + ['rearg', WRAP_REARG_FLAG] + ]; + + /** `Object#toString` result references. */ + var argsTag = '[object Arguments]', + arrayTag = '[object Array]', + asyncTag = '[object AsyncFunction]', + boolTag = '[object Boolean]', + dateTag = '[object Date]', + domExcTag = '[object DOMException]', + errorTag = '[object Error]', + funcTag = '[object Function]', + genTag = '[object GeneratorFunction]', + mapTag = '[object Map]', + numberTag = '[object Number]', + nullTag = '[object Null]', + objectTag = '[object Object]', + promiseTag = '[object Promise]', + proxyTag = '[object Proxy]', + regexpTag = '[object RegExp]', + setTag = '[object Set]', + stringTag = '[object String]', + symbolTag = '[object Symbol]', + undefinedTag = '[object Undefined]', + weakMapTag = '[object WeakMap]', + weakSetTag = '[object WeakSet]'; + + var arrayBufferTag = '[object ArrayBuffer]', + dataViewTag = '[object DataView]', + float32Tag = '[object Float32Array]', + float64Tag = '[object Float64Array]', + int8Tag = '[object Int8Array]', + int16Tag = '[object Int16Array]', + int32Tag = '[object Int32Array]', + uint8Tag = '[object Uint8Array]', + uint8ClampedTag = '[object Uint8ClampedArray]', + uint16Tag = '[object Uint16Array]', + uint32Tag = '[object Uint32Array]'; + + /** Used to match empty string literals in compiled template source. */ + var reEmptyStringLeading = /\b__p \+= '';/g, + reEmptyStringMiddle = /\b(__p \+=) '' \+/g, + reEmptyStringTrailing = /(__e\(.*?\)|\b__t\)) \+\n'';/g; + + /** Used to match HTML entities and HTML characters. */ + var reEscapedHtml = /&(?:amp|lt|gt|quot|#39);/g, + reUnescapedHtml = /[&<>"']/g, + reHasEscapedHtml = RegExp(reEscapedHtml.source), + reHasUnescapedHtml = RegExp(reUnescapedHtml.source); + + /** Used to match template delimiters. */ + var reEscape = /<%-([\s\S]+?)%>/g, + reEvaluate = /<%([\s\S]+?)%>/g, + reInterpolate = /<%=([\s\S]+?)%>/g; + + /** Used to match property names within property paths. */ + var reIsDeepProp = /\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/, + reIsPlainProp = /^\w*$/, + rePropName = /[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g; + + /** + * Used to match `RegExp` + * [syntax characters](http://ecma-international.org/ecma-262/7.0/#sec-patterns). + */ + var reRegExpChar = /[\\^$.*+?()[\]{}|]/g, + reHasRegExpChar = RegExp(reRegExpChar.source); + + /** Used to match leading whitespace. */ + var reTrimStart = /^\s+/; + + /** Used to match a single whitespace character. */ + var reWhitespace = /\s/; + + /** Used to match wrap detail comments. */ + var reWrapComment = /\{(?:\n\/\* \[wrapped with .+\] \*\/)?\n?/, + reWrapDetails = /\{\n\/\* \[wrapped with (.+)\] \*/, + reSplitDetails = /,? & /; + + /** Used to match words composed of alphanumeric characters. */ + var reAsciiWord = /[^\x00-\x2f\x3a-\x40\x5b-\x60\x7b-\x7f]+/g; + + /** + * Used to validate the `validate` option in `_.template` variable. + * + * Forbids characters which could potentially change the meaning of the function argument definition: + * - "()," (modification of function parameters) + * - "=" (default value) + * - "[]{}" (destructuring of function parameters) + * - "/" (beginning of a comment) + * - whitespace + */ + var reForbiddenIdentifierChars = /[()=,{}\[\]\/\s]/; + + /** Used to match backslashes in property paths. */ + var reEscapeChar = /\\(\\)?/g; + + /** + * Used to match + * [ES template delimiters](http://ecma-international.org/ecma-262/7.0/#sec-template-literal-lexical-components). + */ + var reEsTemplate = /\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g; + + /** Used to match `RegExp` flags from their coerced string values. */ + var reFlags = /\w*$/; + + /** Used to detect bad signed hexadecimal string values. */ + var reIsBadHex = /^[-+]0x[0-9a-f]+$/i; + + /** Used to detect binary string values. */ + var reIsBinary = /^0b[01]+$/i; + + /** Used to detect host constructors (Safari). */ + var reIsHostCtor = /^\[object .+?Constructor\]$/; + + /** Used to detect octal string values. */ + var reIsOctal = /^0o[0-7]+$/i; + + /** Used to detect unsigned integer values. */ + var reIsUint = /^(?:0|[1-9]\d*)$/; + + /** Used to match Latin Unicode letters (excluding mathematical operators). */ + var reLatin = /[\xc0-\xd6\xd8-\xf6\xf8-\xff\u0100-\u017f]/g; + + /** Used to ensure capturing order of template delimiters. */ + var reNoMatch = /($^)/; + + /** Used to match unescaped characters in compiled string literals. */ + var reUnescapedString = /['\n\r\u2028\u2029\\]/g; + + /** Used to compose unicode character classes. */ + var rsAstralRange = '\\ud800-\\udfff', + rsComboMarksRange = '\\u0300-\\u036f', + reComboHalfMarksRange = '\\ufe20-\\ufe2f', + rsComboSymbolsRange = '\\u20d0-\\u20ff', + rsComboRange = rsComboMarksRange + reComboHalfMarksRange + rsComboSymbolsRange, + rsDingbatRange = '\\u2700-\\u27bf', + rsLowerRange = 'a-z\\xdf-\\xf6\\xf8-\\xff', + rsMathOpRange = '\\xac\\xb1\\xd7\\xf7', + rsNonCharRange = '\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\xbf', + rsPunctuationRange = '\\u2000-\\u206f', + rsSpaceRange = ' \\t\\x0b\\f\\xa0\\ufeff\\n\\r\\u2028\\u2029\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000', + rsUpperRange = 'A-Z\\xc0-\\xd6\\xd8-\\xde', + rsVarRange = '\\ufe0e\\ufe0f', + rsBreakRange = rsMathOpRange + rsNonCharRange + rsPunctuationRange + rsSpaceRange; + + /** Used to compose unicode capture groups. */ + var rsApos = "['\u2019]", + rsAstral = '[' + rsAstralRange + ']', + rsBreak = '[' + rsBreakRange + ']', + rsCombo = '[' + rsComboRange + ']', + rsDigits = '\\d+', + rsDingbat = '[' + rsDingbatRange + ']', + rsLower = '[' + rsLowerRange + ']', + rsMisc = '[^' + rsAstralRange + rsBreakRange + rsDigits + rsDingbatRange + rsLowerRange + rsUpperRange + ']', + rsFitz = '\\ud83c[\\udffb-\\udfff]', + rsModifier = '(?:' + rsCombo + '|' + rsFitz + ')', + rsNonAstral = '[^' + rsAstralRange + ']', + rsRegional = '(?:\\ud83c[\\udde6-\\uddff]){2}', + rsSurrPair = '[\\ud800-\\udbff][\\udc00-\\udfff]', + rsUpper = '[' + rsUpperRange + ']', + rsZWJ = '\\u200d'; + + /** Used to compose unicode regexes. */ + var rsMiscLower = '(?:' + rsLower + '|' + rsMisc + ')', + rsMiscUpper = '(?:' + rsUpper + '|' + rsMisc + ')', + rsOptContrLower = '(?:' + rsApos + '(?:d|ll|m|re|s|t|ve))?', + rsOptContrUpper = '(?:' + rsApos + '(?:D|LL|M|RE|S|T|VE))?', + reOptMod = rsModifier + '?', + rsOptVar = '[' + rsVarRange + ']?', + rsOptJoin = '(?:' + rsZWJ + '(?:' + [rsNonAstral, rsRegional, rsSurrPair].join('|') + ')' + rsOptVar + reOptMod + ')*', + rsOrdLower = '\\d*(?:1st|2nd|3rd|(?![123])\\dth)(?=\\b|[A-Z_])', + rsOrdUpper = '\\d*(?:1ST|2ND|3RD|(?![123])\\dTH)(?=\\b|[a-z_])', + rsSeq = rsOptVar + reOptMod + rsOptJoin, + rsEmoji = '(?:' + [rsDingbat, rsRegional, rsSurrPair].join('|') + ')' + rsSeq, + rsSymbol = '(?:' + [rsNonAstral + rsCombo + '?', rsCombo, rsRegional, rsSurrPair, rsAstral].join('|') + ')'; + + /** Used to match apostrophes. */ + var reApos = RegExp(rsApos, 'g'); + + /** + * Used to match [combining diacritical marks](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks) and + * [combining diacritical marks for symbols](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks_for_Symbols). + */ + var reComboMark = RegExp(rsCombo, 'g'); + + /** Used to match [string symbols](https://mathiasbynens.be/notes/javascript-unicode). */ + var reUnicode = RegExp(rsFitz + '(?=' + rsFitz + ')|' + rsSymbol + rsSeq, 'g'); + + /** Used to match complex or compound words. */ + var reUnicodeWord = RegExp([ + rsUpper + '?' + rsLower + '+' + rsOptContrLower + '(?=' + [rsBreak, rsUpper, '$'].join('|') + ')', + rsMiscUpper + '+' + rsOptContrUpper + '(?=' + [rsBreak, rsUpper + rsMiscLower, '$'].join('|') + ')', + rsUpper + '?' + rsMiscLower + '+' + rsOptContrLower, + rsUpper + '+' + rsOptContrUpper, + rsOrdUpper, + rsOrdLower, + rsDigits, + rsEmoji + ].join('|'), 'g'); + + /** Used to detect strings with [zero-width joiners or code points from the astral planes](http://eev.ee/blog/2015/09/12/dark-corners-of-unicode/). */ + var reHasUnicode = RegExp('[' + rsZWJ + rsAstralRange + rsComboRange + rsVarRange + ']'); + + /** Used to detect strings that need a more robust regexp to match words. */ + var reHasUnicodeWord = /[a-z][A-Z]|[A-Z]{2}[a-z]|[0-9][a-zA-Z]|[a-zA-Z][0-9]|[^a-zA-Z0-9 ]/; + + /** Used to assign default `context` object properties. */ + var contextProps = [ + 'Array', 'Buffer', 'DataView', 'Date', 'Error', 'Float32Array', 'Float64Array', + 'Function', 'Int8Array', 'Int16Array', 'Int32Array', 'Map', 'Math', 'Object', + 'Promise', 'RegExp', 'Set', 'String', 'Symbol', 'TypeError', 'Uint8Array', + 'Uint8ClampedArray', 'Uint16Array', 'Uint32Array', 'WeakMap', + '_', 'clearTimeout', 'isFinite', 'parseInt', 'setTimeout' + ]; + + /** Used to make template sourceURLs easier to identify. */ + var templateCounter = -1; + + /** Used to identify `toStringTag` values of typed arrays. */ + var typedArrayTags = {}; + typedArrayTags[float32Tag] = typedArrayTags[float64Tag] = + typedArrayTags[int8Tag] = typedArrayTags[int16Tag] = + typedArrayTags[int32Tag] = typedArrayTags[uint8Tag] = + typedArrayTags[uint8ClampedTag] = typedArrayTags[uint16Tag] = + typedArrayTags[uint32Tag] = true; + typedArrayTags[argsTag] = typedArrayTags[arrayTag] = + typedArrayTags[arrayBufferTag] = typedArrayTags[boolTag] = + typedArrayTags[dataViewTag] = typedArrayTags[dateTag] = + typedArrayTags[errorTag] = typedArrayTags[funcTag] = + typedArrayTags[mapTag] = typedArrayTags[numberTag] = + typedArrayTags[objectTag] = typedArrayTags[regexpTag] = + typedArrayTags[setTag] = typedArrayTags[stringTag] = + typedArrayTags[weakMapTag] = false; + + /** Used to identify `toStringTag` values supported by `_.clone`. */ + var cloneableTags = {}; + cloneableTags[argsTag] = cloneableTags[arrayTag] = + cloneableTags[arrayBufferTag] = cloneableTags[dataViewTag] = + cloneableTags[boolTag] = cloneableTags[dateTag] = + cloneableTags[float32Tag] = cloneableTags[float64Tag] = + cloneableTags[int8Tag] = cloneableTags[int16Tag] = + cloneableTags[int32Tag] = cloneableTags[mapTag] = + cloneableTags[numberTag] = cloneableTags[objectTag] = + cloneableTags[regexpTag] = cloneableTags[setTag] = + cloneableTags[stringTag] = cloneableTags[symbolTag] = + cloneableTags[uint8Tag] = cloneableTags[uint8ClampedTag] = + cloneableTags[uint16Tag] = cloneableTags[uint32Tag] = true; + cloneableTags[errorTag] = cloneableTags[funcTag] = + cloneableTags[weakMapTag] = false; + + /** Used to map Latin Unicode letters to basic Latin letters. */ + var deburredLetters = { + // Latin-1 Supplement block. + '\xc0': 'A', '\xc1': 'A', '\xc2': 'A', '\xc3': 'A', '\xc4': 'A', '\xc5': 'A', + '\xe0': 'a', '\xe1': 'a', '\xe2': 'a', '\xe3': 'a', '\xe4': 'a', '\xe5': 'a', + '\xc7': 'C', '\xe7': 'c', + '\xd0': 'D', '\xf0': 'd', + '\xc8': 'E', '\xc9': 'E', '\xca': 'E', '\xcb': 'E', + '\xe8': 'e', '\xe9': 'e', '\xea': 'e', '\xeb': 'e', + '\xcc': 'I', '\xcd': 'I', '\xce': 'I', '\xcf': 'I', + '\xec': 'i', '\xed': 'i', '\xee': 'i', '\xef': 'i', + '\xd1': 'N', '\xf1': 'n', + '\xd2': 'O', '\xd3': 'O', '\xd4': 'O', '\xd5': 'O', '\xd6': 'O', '\xd8': 'O', + '\xf2': 'o', '\xf3': 'o', '\xf4': 'o', '\xf5': 'o', '\xf6': 'o', '\xf8': 'o', + '\xd9': 'U', '\xda': 'U', '\xdb': 'U', '\xdc': 'U', + '\xf9': 'u', '\xfa': 'u', '\xfb': 'u', '\xfc': 'u', + '\xdd': 'Y', '\xfd': 'y', '\xff': 'y', + '\xc6': 'Ae', '\xe6': 'ae', + '\xde': 'Th', '\xfe': 'th', + '\xdf': 'ss', + // Latin Extended-A block. + '\u0100': 'A', '\u0102': 'A', '\u0104': 'A', + '\u0101': 'a', '\u0103': 'a', '\u0105': 'a', + '\u0106': 'C', '\u0108': 'C', '\u010a': 'C', '\u010c': 'C', + '\u0107': 'c', '\u0109': 'c', '\u010b': 'c', '\u010d': 'c', + '\u010e': 'D', '\u0110': 'D', '\u010f': 'd', '\u0111': 'd', + '\u0112': 'E', '\u0114': 'E', '\u0116': 'E', '\u0118': 'E', '\u011a': 'E', + '\u0113': 'e', '\u0115': 'e', '\u0117': 'e', '\u0119': 'e', '\u011b': 'e', + '\u011c': 'G', '\u011e': 'G', '\u0120': 'G', '\u0122': 'G', + '\u011d': 'g', '\u011f': 'g', '\u0121': 'g', '\u0123': 'g', + '\u0124': 'H', '\u0126': 'H', '\u0125': 'h', '\u0127': 'h', + '\u0128': 'I', '\u012a': 'I', '\u012c': 'I', '\u012e': 'I', '\u0130': 'I', + '\u0129': 'i', '\u012b': 'i', '\u012d': 'i', '\u012f': 'i', '\u0131': 'i', + '\u0134': 'J', '\u0135': 'j', + '\u0136': 'K', '\u0137': 'k', '\u0138': 'k', + '\u0139': 'L', '\u013b': 'L', '\u013d': 'L', '\u013f': 'L', '\u0141': 'L', + '\u013a': 'l', '\u013c': 'l', '\u013e': 'l', '\u0140': 'l', '\u0142': 'l', + '\u0143': 'N', '\u0145': 'N', '\u0147': 'N', '\u014a': 'N', + '\u0144': 'n', '\u0146': 'n', '\u0148': 'n', '\u014b': 'n', + '\u014c': 'O', '\u014e': 'O', '\u0150': 'O', + '\u014d': 'o', '\u014f': 'o', '\u0151': 'o', + '\u0154': 'R', '\u0156': 'R', '\u0158': 'R', + '\u0155': 'r', '\u0157': 'r', '\u0159': 'r', + '\u015a': 'S', '\u015c': 'S', '\u015e': 'S', '\u0160': 'S', + '\u015b': 's', '\u015d': 's', '\u015f': 's', '\u0161': 's', + '\u0162': 'T', '\u0164': 'T', '\u0166': 'T', + '\u0163': 't', '\u0165': 't', '\u0167': 't', + '\u0168': 'U', '\u016a': 'U', '\u016c': 'U', '\u016e': 'U', '\u0170': 'U', '\u0172': 'U', + '\u0169': 'u', '\u016b': 'u', '\u016d': 'u', '\u016f': 'u', '\u0171': 'u', '\u0173': 'u', + '\u0174': 'W', '\u0175': 'w', + '\u0176': 'Y', '\u0177': 'y', '\u0178': 'Y', + '\u0179': 'Z', '\u017b': 'Z', '\u017d': 'Z', + '\u017a': 'z', '\u017c': 'z', '\u017e': 'z', + '\u0132': 'IJ', '\u0133': 'ij', + '\u0152': 'Oe', '\u0153': 'oe', + '\u0149': "'n", '\u017f': 's' + }; + + /** Used to map characters to HTML entities. */ + var htmlEscapes = { + '&': '&', + '<': '<', + '>': '>', + '"': '"', + "'": ''' + }; + + /** Used to map HTML entities to characters. */ + var htmlUnescapes = { + '&': '&', + '<': '<', + '>': '>', + '"': '"', + ''': "'" + }; + + /** Used to escape characters for inclusion in compiled string literals. */ + var stringEscapes = { + '\\': '\\', + "'": "'", + '\n': 'n', + '\r': 'r', + '\u2028': 'u2028', + '\u2029': 'u2029' + }; + + /** Built-in method references without a dependency on `root`. */ + var freeParseFloat = parseFloat, + freeParseInt = parseInt; + + /** Detect free variable `global` from Node.js. */ + var freeGlobal = typeof global == 'object' && global && global.Object === Object && global; + + /** Detect free variable `self`. */ + var freeSelf = typeof self == 'object' && self && self.Object === Object && self; + + /** Used as a reference to the global object. */ + var root = freeGlobal || freeSelf || Function('return this')(); + + /** Detect free variable `exports`. */ + var freeExports = true && exports && !exports.nodeType && exports; + + /** Detect free variable `module`. */ + var freeModule = freeExports && "object" == 'object' && module && !module.nodeType && module; + + /** Detect the popular CommonJS extension `module.exports`. */ + var moduleExports = freeModule && freeModule.exports === freeExports; + + /** Detect free variable `process` from Node.js. */ + var freeProcess = moduleExports && freeGlobal.process; + + /** Used to access faster Node.js helpers. */ + var nodeUtil = (function() { + try { + // Use `util.types` for Node.js 10+. + var types = freeModule && freeModule.require && freeModule.require('util').types; + + if (types) { + return types; + } + + // Legacy `process.binding('util')` for Node.js < 10. + return freeProcess && freeProcess.binding && freeProcess.binding('util'); + } catch (e) {} + }()); + + /* Node.js helper references. */ + var nodeIsArrayBuffer = nodeUtil && nodeUtil.isArrayBuffer, + nodeIsDate = nodeUtil && nodeUtil.isDate, + nodeIsMap = nodeUtil && nodeUtil.isMap, + nodeIsRegExp = nodeUtil && nodeUtil.isRegExp, + nodeIsSet = nodeUtil && nodeUtil.isSet, + nodeIsTypedArray = nodeUtil && nodeUtil.isTypedArray; + + /*--------------------------------------------------------------------------*/ + + /** + * A faster alternative to `Function#apply`, this function invokes `func` + * with the `this` binding of `thisArg` and the arguments of `args`. + * + * @private + * @param {Function} func The function to invoke. + * @param {*} thisArg The `this` binding of `func`. + * @param {Array} args The arguments to invoke `func` with. + * @returns {*} Returns the result of `func`. + */ + function apply(func, thisArg, args) { + switch (args.length) { + case 0: return func.call(thisArg); + case 1: return func.call(thisArg, args[0]); + case 2: return func.call(thisArg, args[0], args[1]); + case 3: return func.call(thisArg, args[0], args[1], args[2]); + } + return func.apply(thisArg, args); + } + + /** + * A specialized version of `baseAggregator` for arrays. + * + * @private + * @param {Array} [array] The array to iterate over. + * @param {Function} setter The function to set `accumulator` values. + * @param {Function} iteratee The iteratee to transform keys. + * @param {Object} accumulator The initial aggregated object. + * @returns {Function} Returns `accumulator`. + */ + function arrayAggregator(array, setter, iteratee, accumulator) { + var index = -1, + length = array == null ? 0 : array.length; + + while (++index < length) { + var value = array[index]; + setter(accumulator, value, iteratee(value), array); + } + return accumulator; + } + + /** + * A specialized version of `_.forEach` for arrays without support for + * iteratee shorthands. + * + * @private + * @param {Array} [array] The array to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @returns {Array} Returns `array`. + */ + function arrayEach(array, iteratee) { + var index = -1, + length = array == null ? 0 : array.length; + + while (++index < length) { + if (iteratee(array[index], index, array) === false) { + break; + } + } + return array; + } + + /** + * A specialized version of `_.forEachRight` for arrays without support for + * iteratee shorthands. + * + * @private + * @param {Array} [array] The array to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @returns {Array} Returns `array`. + */ + function arrayEachRight(array, iteratee) { + var length = array == null ? 0 : array.length; + + while (length--) { + if (iteratee(array[length], length, array) === false) { + break; + } + } + return array; + } + + /** + * A specialized version of `_.every` for arrays without support for + * iteratee shorthands. + * + * @private + * @param {Array} [array] The array to iterate over. + * @param {Function} predicate The function invoked per iteration. + * @returns {boolean} Returns `true` if all elements pass the predicate check, + * else `false`. + */ + function arrayEvery(array, predicate) { + var index = -1, + length = array == null ? 0 : array.length; + + while (++index < length) { + if (!predicate(array[index], index, array)) { + return false; + } + } + return true; + } + + /** + * A specialized version of `_.filter` for arrays without support for + * iteratee shorthands. + * + * @private + * @param {Array} [array] The array to iterate over. + * @param {Function} predicate The function invoked per iteration. + * @returns {Array} Returns the new filtered array. + */ + function arrayFilter(array, predicate) { + var index = -1, + length = array == null ? 0 : array.length, + resIndex = 0, + result = []; + + while (++index < length) { + var value = array[index]; + if (predicate(value, index, array)) { + result[resIndex++] = value; + } + } + return result; + } + + /** + * A specialized version of `_.includes` for arrays without support for + * specifying an index to search from. + * + * @private + * @param {Array} [array] The array to inspect. + * @param {*} target The value to search for. + * @returns {boolean} Returns `true` if `target` is found, else `false`. + */ + function arrayIncludes(array, value) { + var length = array == null ? 0 : array.length; + return !!length && baseIndexOf(array, value, 0) > -1; + } + + /** + * This function is like `arrayIncludes` except that it accepts a comparator. + * + * @private + * @param {Array} [array] The array to inspect. + * @param {*} target The value to search for. + * @param {Function} comparator The comparator invoked per element. + * @returns {boolean} Returns `true` if `target` is found, else `false`. + */ + function arrayIncludesWith(array, value, comparator) { + var index = -1, + length = array == null ? 0 : array.length; + + while (++index < length) { + if (comparator(value, array[index])) { + return true; + } + } + return false; + } + + /** + * A specialized version of `_.map` for arrays without support for iteratee + * shorthands. + * + * @private + * @param {Array} [array] The array to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @returns {Array} Returns the new mapped array. + */ + function arrayMap(array, iteratee) { + var index = -1, + length = array == null ? 0 : array.length, + result = Array(length); + + while (++index < length) { + result[index] = iteratee(array[index], index, array); + } + return result; + } + + /** + * Appends the elements of `values` to `array`. + * + * @private + * @param {Array} array The array to modify. + * @param {Array} values The values to append. + * @returns {Array} Returns `array`. + */ + function arrayPush(array, values) { + var index = -1, + length = values.length, + offset = array.length; + + while (++index < length) { + array[offset + index] = values[index]; + } + return array; + } + + /** + * A specialized version of `_.reduce` for arrays without support for + * iteratee shorthands. + * + * @private + * @param {Array} [array] The array to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @param {*} [accumulator] The initial value. + * @param {boolean} [initAccum] Specify using the first element of `array` as + * the initial value. + * @returns {*} Returns the accumulated value. + */ + function arrayReduce(array, iteratee, accumulator, initAccum) { + var index = -1, + length = array == null ? 0 : array.length; + + if (initAccum && length) { + accumulator = array[++index]; + } + while (++index < length) { + accumulator = iteratee(accumulator, array[index], index, array); + } + return accumulator; + } + + /** + * A specialized version of `_.reduceRight` for arrays without support for + * iteratee shorthands. + * + * @private + * @param {Array} [array] The array to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @param {*} [accumulator] The initial value. + * @param {boolean} [initAccum] Specify using the last element of `array` as + * the initial value. + * @returns {*} Returns the accumulated value. + */ + function arrayReduceRight(array, iteratee, accumulator, initAccum) { + var length = array == null ? 0 : array.length; + if (initAccum && length) { + accumulator = array[--length]; + } + while (length--) { + accumulator = iteratee(accumulator, array[length], length, array); + } + return accumulator; + } + + /** + * A specialized version of `_.some` for arrays without support for iteratee + * shorthands. + * + * @private + * @param {Array} [array] The array to iterate over. + * @param {Function} predicate The function invoked per iteration. + * @returns {boolean} Returns `true` if any element passes the predicate check, + * else `false`. + */ + function arraySome(array, predicate) { + var index = -1, + length = array == null ? 0 : array.length; + + while (++index < length) { + if (predicate(array[index], index, array)) { + return true; + } + } + return false; + } + + /** + * Gets the size of an ASCII `string`. + * + * @private + * @param {string} string The string inspect. + * @returns {number} Returns the string size. + */ + var asciiSize = baseProperty('length'); + + /** + * Converts an ASCII `string` to an array. + * + * @private + * @param {string} string The string to convert. + * @returns {Array} Returns the converted array. + */ + function asciiToArray(string) { + return string.split(''); + } + + /** + * Splits an ASCII `string` into an array of its words. + * + * @private + * @param {string} The string to inspect. + * @returns {Array} Returns the words of `string`. + */ + function asciiWords(string) { + return string.match(reAsciiWord) || []; + } + + /** + * The base implementation of methods like `_.findKey` and `_.findLastKey`, + * without support for iteratee shorthands, which iterates over `collection` + * using `eachFunc`. + * + * @private + * @param {Array|Object} collection The collection to inspect. + * @param {Function} predicate The function invoked per iteration. + * @param {Function} eachFunc The function to iterate over `collection`. + * @returns {*} Returns the found element or its key, else `undefined`. + */ + function baseFindKey(collection, predicate, eachFunc) { + var result; + eachFunc(collection, function(value, key, collection) { + if (predicate(value, key, collection)) { + result = key; + return false; + } + }); + return result; + } + + /** + * The base implementation of `_.findIndex` and `_.findLastIndex` without + * support for iteratee shorthands. + * + * @private + * @param {Array} array The array to inspect. + * @param {Function} predicate The function invoked per iteration. + * @param {number} fromIndex The index to search from. + * @param {boolean} [fromRight] Specify iterating from right to left. + * @returns {number} Returns the index of the matched value, else `-1`. + */ + function baseFindIndex(array, predicate, fromIndex, fromRight) { + var length = array.length, + index = fromIndex + (fromRight ? 1 : -1); + + while ((fromRight ? index-- : ++index < length)) { + if (predicate(array[index], index, array)) { + return index; + } + } + return -1; + } + + /** + * The base implementation of `_.indexOf` without `fromIndex` bounds checks. + * + * @private + * @param {Array} array The array to inspect. + * @param {*} value The value to search for. + * @param {number} fromIndex The index to search from. + * @returns {number} Returns the index of the matched value, else `-1`. + */ + function baseIndexOf(array, value, fromIndex) { + return value === value + ? strictIndexOf(array, value, fromIndex) + : baseFindIndex(array, baseIsNaN, fromIndex); + } + + /** + * This function is like `baseIndexOf` except that it accepts a comparator. + * + * @private + * @param {Array} array The array to inspect. + * @param {*} value The value to search for. + * @param {number} fromIndex The index to search from. + * @param {Function} comparator The comparator invoked per element. + * @returns {number} Returns the index of the matched value, else `-1`. + */ + function baseIndexOfWith(array, value, fromIndex, comparator) { + var index = fromIndex - 1, + length = array.length; + + while (++index < length) { + if (comparator(array[index], value)) { + return index; + } + } + return -1; + } + + /** + * The base implementation of `_.isNaN` without support for number objects. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is `NaN`, else `false`. + */ + function baseIsNaN(value) { + return value !== value; + } + + /** + * The base implementation of `_.mean` and `_.meanBy` without support for + * iteratee shorthands. + * + * @private + * @param {Array} array The array to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @returns {number} Returns the mean. + */ + function baseMean(array, iteratee) { + var length = array == null ? 0 : array.length; + return length ? (baseSum(array, iteratee) / length) : NAN; + } + + /** + * The base implementation of `_.property` without support for deep paths. + * + * @private + * @param {string} key The key of the property to get. + * @returns {Function} Returns the new accessor function. + */ + function baseProperty(key) { + return function(object) { + return object == null ? undefined : object[key]; + }; + } + + /** + * The base implementation of `_.propertyOf` without support for deep paths. + * + * @private + * @param {Object} object The object to query. + * @returns {Function} Returns the new accessor function. + */ + function basePropertyOf(object) { + return function(key) { + return object == null ? undefined : object[key]; + }; + } + + /** + * The base implementation of `_.reduce` and `_.reduceRight`, without support + * for iteratee shorthands, which iterates over `collection` using `eachFunc`. + * + * @private + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @param {*} accumulator The initial value. + * @param {boolean} initAccum Specify using the first or last element of + * `collection` as the initial value. + * @param {Function} eachFunc The function to iterate over `collection`. + * @returns {*} Returns the accumulated value. + */ + function baseReduce(collection, iteratee, accumulator, initAccum, eachFunc) { + eachFunc(collection, function(value, index, collection) { + accumulator = initAccum + ? (initAccum = false, value) + : iteratee(accumulator, value, index, collection); + }); + return accumulator; + } + + /** + * The base implementation of `_.sortBy` which uses `comparer` to define the + * sort order of `array` and replaces criteria objects with their corresponding + * values. + * + * @private + * @param {Array} array The array to sort. + * @param {Function} comparer The function to define sort order. + * @returns {Array} Returns `array`. + */ + function baseSortBy(array, comparer) { + var length = array.length; + + array.sort(comparer); + while (length--) { + array[length] = array[length].value; + } + return array; + } + + /** + * The base implementation of `_.sum` and `_.sumBy` without support for + * iteratee shorthands. + * + * @private + * @param {Array} array The array to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @returns {number} Returns the sum. + */ + function baseSum(array, iteratee) { + var result, + index = -1, + length = array.length; + + while (++index < length) { + var current = iteratee(array[index]); + if (current !== undefined) { + result = result === undefined ? current : (result + current); + } + } + return result; + } + + /** + * The base implementation of `_.times` without support for iteratee shorthands + * or max array length checks. + * + * @private + * @param {number} n The number of times to invoke `iteratee`. + * @param {Function} iteratee The function invoked per iteration. + * @returns {Array} Returns the array of results. + */ + function baseTimes(n, iteratee) { + var index = -1, + result = Array(n); + + while (++index < n) { + result[index] = iteratee(index); + } + return result; + } + + /** + * The base implementation of `_.toPairs` and `_.toPairsIn` which creates an array + * of key-value pairs for `object` corresponding to the property names of `props`. + * + * @private + * @param {Object} object The object to query. + * @param {Array} props The property names to get values for. + * @returns {Object} Returns the key-value pairs. + */ + function baseToPairs(object, props) { + return arrayMap(props, function(key) { + return [key, object[key]]; + }); + } + + /** + * The base implementation of `_.trim`. + * + * @private + * @param {string} string The string to trim. + * @returns {string} Returns the trimmed string. + */ + function baseTrim(string) { + return string + ? string.slice(0, trimmedEndIndex(string) + 1).replace(reTrimStart, '') + : string; + } + + /** + * The base implementation of `_.unary` without support for storing metadata. + * + * @private + * @param {Function} func The function to cap arguments for. + * @returns {Function} Returns the new capped function. + */ + function baseUnary(func) { + return function(value) { + return func(value); + }; + } + + /** + * The base implementation of `_.values` and `_.valuesIn` which creates an + * array of `object` property values corresponding to the property names + * of `props`. + * + * @private + * @param {Object} object The object to query. + * @param {Array} props The property names to get values for. + * @returns {Object} Returns the array of property values. + */ + function baseValues(object, props) { + return arrayMap(props, function(key) { + return object[key]; + }); + } + + /** + * Checks if a `cache` value for `key` exists. + * + * @private + * @param {Object} cache The cache to query. + * @param {string} key The key of the entry to check. + * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. + */ + function cacheHas(cache, key) { + return cache.has(key); + } + + /** + * Used by `_.trim` and `_.trimStart` to get the index of the first string symbol + * that is not found in the character symbols. + * + * @private + * @param {Array} strSymbols The string symbols to inspect. + * @param {Array} chrSymbols The character symbols to find. + * @returns {number} Returns the index of the first unmatched string symbol. + */ + function charsStartIndex(strSymbols, chrSymbols) { + var index = -1, + length = strSymbols.length; + + while (++index < length && baseIndexOf(chrSymbols, strSymbols[index], 0) > -1) {} + return index; + } + + /** + * Used by `_.trim` and `_.trimEnd` to get the index of the last string symbol + * that is not found in the character symbols. + * + * @private + * @param {Array} strSymbols The string symbols to inspect. + * @param {Array} chrSymbols The character symbols to find. + * @returns {number} Returns the index of the last unmatched string symbol. + */ + function charsEndIndex(strSymbols, chrSymbols) { + var index = strSymbols.length; + + while (index-- && baseIndexOf(chrSymbols, strSymbols[index], 0) > -1) {} + return index; + } + + /** + * Gets the number of `placeholder` occurrences in `array`. + * + * @private + * @param {Array} array The array to inspect. + * @param {*} placeholder The placeholder to search for. + * @returns {number} Returns the placeholder count. + */ + function countHolders(array, placeholder) { + var length = array.length, + result = 0; + + while (length--) { + if (array[length] === placeholder) { + ++result; + } + } + return result; + } + + /** + * Used by `_.deburr` to convert Latin-1 Supplement and Latin Extended-A + * letters to basic Latin letters. + * + * @private + * @param {string} letter The matched letter to deburr. + * @returns {string} Returns the deburred letter. + */ + var deburrLetter = basePropertyOf(deburredLetters); + + /** + * Used by `_.escape` to convert characters to HTML entities. + * + * @private + * @param {string} chr The matched character to escape. + * @returns {string} Returns the escaped character. + */ + var escapeHtmlChar = basePropertyOf(htmlEscapes); + + /** + * Used by `_.template` to escape characters for inclusion in compiled string literals. + * + * @private + * @param {string} chr The matched character to escape. + * @returns {string} Returns the escaped character. + */ + function escapeStringChar(chr) { + return '\\' + stringEscapes[chr]; + } + + /** + * Gets the value at `key` of `object`. + * + * @private + * @param {Object} [object] The object to query. + * @param {string} key The key of the property to get. + * @returns {*} Returns the property value. + */ + function getValue(object, key) { + return object == null ? undefined : object[key]; + } + + /** + * Checks if `string` contains Unicode symbols. + * + * @private + * @param {string} string The string to inspect. + * @returns {boolean} Returns `true` if a symbol is found, else `false`. + */ + function hasUnicode(string) { + return reHasUnicode.test(string); + } + + /** + * Checks if `string` contains a word composed of Unicode symbols. + * + * @private + * @param {string} string The string to inspect. + * @returns {boolean} Returns `true` if a word is found, else `false`. + */ + function hasUnicodeWord(string) { + return reHasUnicodeWord.test(string); + } + + /** + * Converts `iterator` to an array. + * + * @private + * @param {Object} iterator The iterator to convert. + * @returns {Array} Returns the converted array. + */ + function iteratorToArray(iterator) { + var data, + result = []; + + while (!(data = iterator.next()).done) { + result.push(data.value); + } + return result; + } + + /** + * Converts `map` to its key-value pairs. + * + * @private + * @param {Object} map The map to convert. + * @returns {Array} Returns the key-value pairs. + */ + function mapToArray(map) { + var index = -1, + result = Array(map.size); + + map.forEach(function(value, key) { + result[++index] = [key, value]; + }); + return result; + } + + /** + * Creates a unary function that invokes `func` with its argument transformed. + * + * @private + * @param {Function} func The function to wrap. + * @param {Function} transform The argument transform. + * @returns {Function} Returns the new function. + */ + function overArg(func, transform) { + return function(arg) { + return func(transform(arg)); + }; + } + + /** + * Replaces all `placeholder` elements in `array` with an internal placeholder + * and returns an array of their indexes. + * + * @private + * @param {Array} array The array to modify. + * @param {*} placeholder The placeholder to replace. + * @returns {Array} Returns the new array of placeholder indexes. + */ + function replaceHolders(array, placeholder) { + var index = -1, + length = array.length, + resIndex = 0, + result = []; + + while (++index < length) { + var value = array[index]; + if (value === placeholder || value === PLACEHOLDER) { + array[index] = PLACEHOLDER; + result[resIndex++] = index; + } + } + return result; + } + + /** + * Converts `set` to an array of its values. + * + * @private + * @param {Object} set The set to convert. + * @returns {Array} Returns the values. + */ + function setToArray(set) { + var index = -1, + result = Array(set.size); + + set.forEach(function(value) { + result[++index] = value; + }); + return result; + } + + /** + * Converts `set` to its value-value pairs. + * + * @private + * @param {Object} set The set to convert. + * @returns {Array} Returns the value-value pairs. + */ + function setToPairs(set) { + var index = -1, + result = Array(set.size); + + set.forEach(function(value) { + result[++index] = [value, value]; + }); + return result; + } + + /** + * A specialized version of `_.indexOf` which performs strict equality + * comparisons of values, i.e. `===`. + * + * @private + * @param {Array} array The array to inspect. + * @param {*} value The value to search for. + * @param {number} fromIndex The index to search from. + * @returns {number} Returns the index of the matched value, else `-1`. + */ + function strictIndexOf(array, value, fromIndex) { + var index = fromIndex - 1, + length = array.length; + + while (++index < length) { + if (array[index] === value) { + return index; + } + } + return -1; + } + + /** + * A specialized version of `_.lastIndexOf` which performs strict equality + * comparisons of values, i.e. `===`. + * + * @private + * @param {Array} array The array to inspect. + * @param {*} value The value to search for. + * @param {number} fromIndex The index to search from. + * @returns {number} Returns the index of the matched value, else `-1`. + */ + function strictLastIndexOf(array, value, fromIndex) { + var index = fromIndex + 1; + while (index--) { + if (array[index] === value) { + return index; + } + } + return index; + } + + /** + * Gets the number of symbols in `string`. + * + * @private + * @param {string} string The string to inspect. + * @returns {number} Returns the string size. + */ + function stringSize(string) { + return hasUnicode(string) + ? unicodeSize(string) + : asciiSize(string); + } + + /** + * Converts `string` to an array. + * + * @private + * @param {string} string The string to convert. + * @returns {Array} Returns the converted array. + */ + function stringToArray(string) { + return hasUnicode(string) + ? unicodeToArray(string) + : asciiToArray(string); + } + + /** + * Used by `_.trim` and `_.trimEnd` to get the index of the last non-whitespace + * character of `string`. + * + * @private + * @param {string} string The string to inspect. + * @returns {number} Returns the index of the last non-whitespace character. + */ + function trimmedEndIndex(string) { + var index = string.length; + + while (index-- && reWhitespace.test(string.charAt(index))) {} + return index; + } + + /** + * Used by `_.unescape` to convert HTML entities to characters. + * + * @private + * @param {string} chr The matched character to unescape. + * @returns {string} Returns the unescaped character. + */ + var unescapeHtmlChar = basePropertyOf(htmlUnescapes); + + /** + * Gets the size of a Unicode `string`. + * + * @private + * @param {string} string The string inspect. + * @returns {number} Returns the string size. + */ + function unicodeSize(string) { + var result = reUnicode.lastIndex = 0; + while (reUnicode.test(string)) { + ++result; + } + return result; + } + + /** + * Converts a Unicode `string` to an array. + * + * @private + * @param {string} string The string to convert. + * @returns {Array} Returns the converted array. + */ + function unicodeToArray(string) { + return string.match(reUnicode) || []; + } + + /** + * Splits a Unicode `string` into an array of its words. + * + * @private + * @param {string} The string to inspect. + * @returns {Array} Returns the words of `string`. + */ + function unicodeWords(string) { + return string.match(reUnicodeWord) || []; + } + + /*--------------------------------------------------------------------------*/ + + /** + * Create a new pristine `lodash` function using the `context` object. + * + * @static + * @memberOf _ + * @since 1.1.0 + * @category Util + * @param {Object} [context=root] The context object. + * @returns {Function} Returns a new `lodash` function. + * @example + * + * _.mixin({ 'foo': _.constant('foo') }); + * + * var lodash = _.runInContext(); + * lodash.mixin({ 'bar': lodash.constant('bar') }); + * + * _.isFunction(_.foo); + * // => true + * _.isFunction(_.bar); + * // => false + * + * lodash.isFunction(lodash.foo); + * // => false + * lodash.isFunction(lodash.bar); + * // => true + * + * // Create a suped-up `defer` in Node.js. + * var defer = _.runInContext({ 'setTimeout': setImmediate }).defer; + */ + var runInContext = (function runInContext(context) { + context = context == null ? root : _.defaults(root.Object(), context, _.pick(root, contextProps)); + + /** Built-in constructor references. */ + var Array = context.Array, + Date = context.Date, + Error = context.Error, + Function = context.Function, + Math = context.Math, + Object = context.Object, + RegExp = context.RegExp, + String = context.String, + TypeError = context.TypeError; + + /** Used for built-in method references. */ + var arrayProto = Array.prototype, + funcProto = Function.prototype, + objectProto = Object.prototype; + + /** Used to detect overreaching core-js shims. */ + var coreJsData = context['__core-js_shared__']; + + /** Used to resolve the decompiled source of functions. */ + var funcToString = funcProto.toString; + + /** Used to check objects for own properties. */ + var hasOwnProperty = objectProto.hasOwnProperty; + + /** Used to generate unique IDs. */ + var idCounter = 0; + + /** Used to detect methods masquerading as native. */ + var maskSrcKey = (function() { + var uid = /[^.]+$/.exec(coreJsData && coreJsData.keys && coreJsData.keys.IE_PROTO || ''); + return uid ? ('Symbol(src)_1.' + uid) : ''; + }()); + + /** + * Used to resolve the + * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring) + * of values. + */ + var nativeObjectToString = objectProto.toString; + + /** Used to infer the `Object` constructor. */ + var objectCtorString = funcToString.call(Object); + + /** Used to restore the original `_` reference in `_.noConflict`. */ + var oldDash = root._; + + /** Used to detect if a method is native. */ + var reIsNative = RegExp('^' + + funcToString.call(hasOwnProperty).replace(reRegExpChar, '\\$&') + .replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$' + ); + + /** Built-in value references. */ + var Buffer = moduleExports ? context.Buffer : undefined, + Symbol = context.Symbol, + Uint8Array = context.Uint8Array, + allocUnsafe = Buffer ? Buffer.allocUnsafe : undefined, + getPrototype = overArg(Object.getPrototypeOf, Object), + objectCreate = Object.create, + propertyIsEnumerable = objectProto.propertyIsEnumerable, + splice = arrayProto.splice, + spreadableSymbol = Symbol ? Symbol.isConcatSpreadable : undefined, + symIterator = Symbol ? Symbol.iterator : undefined, + symToStringTag = Symbol ? Symbol.toStringTag : undefined; + + var defineProperty = (function() { + try { + var func = getNative(Object, 'defineProperty'); + func({}, '', {}); + return func; + } catch (e) {} + }()); + + /** Mocked built-ins. */ + var ctxClearTimeout = context.clearTimeout !== root.clearTimeout && context.clearTimeout, + ctxNow = Date && Date.now !== root.Date.now && Date.now, + ctxSetTimeout = context.setTimeout !== root.setTimeout && context.setTimeout; + + /* Built-in method references for those with the same name as other `lodash` methods. */ + var nativeCeil = Math.ceil, + nativeFloor = Math.floor, + nativeGetSymbols = Object.getOwnPropertySymbols, + nativeIsBuffer = Buffer ? Buffer.isBuffer : undefined, + nativeIsFinite = context.isFinite, + nativeJoin = arrayProto.join, + nativeKeys = overArg(Object.keys, Object), + nativeMax = Math.max, + nativeMin = Math.min, + nativeNow = Date.now, + nativeParseInt = context.parseInt, + nativeRandom = Math.random, + nativeReverse = arrayProto.reverse; + + /* Built-in method references that are verified to be native. */ + var DataView = getNative(context, 'DataView'), + Map = getNative(context, 'Map'), + Promise = getNative(context, 'Promise'), + Set = getNative(context, 'Set'), + WeakMap = getNative(context, 'WeakMap'), + nativeCreate = getNative(Object, 'create'); + + /** Used to store function metadata. */ + var metaMap = WeakMap && new WeakMap; + + /** Used to lookup unminified function names. */ + var realNames = {}; + + /** Used to detect maps, sets, and weakmaps. */ + var dataViewCtorString = toSource(DataView), + mapCtorString = toSource(Map), + promiseCtorString = toSource(Promise), + setCtorString = toSource(Set), + weakMapCtorString = toSource(WeakMap); + + /** Used to convert symbols to primitives and strings. */ + var symbolProto = Symbol ? Symbol.prototype : undefined, + symbolValueOf = symbolProto ? symbolProto.valueOf : undefined, + symbolToString = symbolProto ? symbolProto.toString : undefined; + + /*------------------------------------------------------------------------*/ + + /** + * Creates a `lodash` object which wraps `value` to enable implicit method + * chain sequences. Methods that operate on and return arrays, collections, + * and functions can be chained together. Methods that retrieve a single value + * or may return a primitive value will automatically end the chain sequence + * and return the unwrapped value. Otherwise, the value must be unwrapped + * with `_#value`. + * + * Explicit chain sequences, which must be unwrapped with `_#value`, may be + * enabled using `_.chain`. + * + * The execution of chained methods is lazy, that is, it's deferred until + * `_#value` is implicitly or explicitly called. + * + * Lazy evaluation allows several methods to support shortcut fusion. + * Shortcut fusion is an optimization to merge iteratee calls; this avoids + * the creation of intermediate arrays and can greatly reduce the number of + * iteratee executions. Sections of a chain sequence qualify for shortcut + * fusion if the section is applied to an array and iteratees accept only + * one argument. The heuristic for whether a section qualifies for shortcut + * fusion is subject to change. + * + * Chaining is supported in custom builds as long as the `_#value` method is + * directly or indirectly included in the build. + * + * In addition to lodash methods, wrappers have `Array` and `String` methods. + * + * The wrapper `Array` methods are: + * `concat`, `join`, `pop`, `push`, `shift`, `sort`, `splice`, and `unshift` + * + * The wrapper `String` methods are: + * `replace` and `split` + * + * The wrapper methods that support shortcut fusion are: + * `at`, `compact`, `drop`, `dropRight`, `dropWhile`, `filter`, `find`, + * `findLast`, `head`, `initial`, `last`, `map`, `reject`, `reverse`, `slice`, + * `tail`, `take`, `takeRight`, `takeRightWhile`, `takeWhile`, and `toArray` + * + * The chainable wrapper methods are: + * `after`, `ary`, `assign`, `assignIn`, `assignInWith`, `assignWith`, `at`, + * `before`, `bind`, `bindAll`, `bindKey`, `castArray`, `chain`, `chunk`, + * `commit`, `compact`, `concat`, `conforms`, `constant`, `countBy`, `create`, + * `curry`, `debounce`, `defaults`, `defaultsDeep`, `defer`, `delay`, + * `difference`, `differenceBy`, `differenceWith`, `drop`, `dropRight`, + * `dropRightWhile`, `dropWhile`, `extend`, `extendWith`, `fill`, `filter`, + * `flatMap`, `flatMapDeep`, `flatMapDepth`, `flatten`, `flattenDeep`, + * `flattenDepth`, `flip`, `flow`, `flowRight`, `fromPairs`, `functions`, + * `functionsIn`, `groupBy`, `initial`, `intersection`, `intersectionBy`, + * `intersectionWith`, `invert`, `invertBy`, `invokeMap`, `iteratee`, `keyBy`, + * `keys`, `keysIn`, `map`, `mapKeys`, `mapValues`, `matches`, `matchesProperty`, + * `memoize`, `merge`, `mergeWith`, `method`, `methodOf`, `mixin`, `negate`, + * `nthArg`, `omit`, `omitBy`, `once`, `orderBy`, `over`, `overArgs`, + * `overEvery`, `overSome`, `partial`, `partialRight`, `partition`, `pick`, + * `pickBy`, `plant`, `property`, `propertyOf`, `pull`, `pullAll`, `pullAllBy`, + * `pullAllWith`, `pullAt`, `push`, `range`, `rangeRight`, `rearg`, `reject`, + * `remove`, `rest`, `reverse`, `sampleSize`, `set`, `setWith`, `shuffle`, + * `slice`, `sort`, `sortBy`, `splice`, `spread`, `tail`, `take`, `takeRight`, + * `takeRightWhile`, `takeWhile`, `tap`, `throttle`, `thru`, `toArray`, + * `toPairs`, `toPairsIn`, `toPath`, `toPlainObject`, `transform`, `unary`, + * `union`, `unionBy`, `unionWith`, `uniq`, `uniqBy`, `uniqWith`, `unset`, + * `unshift`, `unzip`, `unzipWith`, `update`, `updateWith`, `values`, + * `valuesIn`, `without`, `wrap`, `xor`, `xorBy`, `xorWith`, `zip`, + * `zipObject`, `zipObjectDeep`, and `zipWith` + * + * The wrapper methods that are **not** chainable by default are: + * `add`, `attempt`, `camelCase`, `capitalize`, `ceil`, `clamp`, `clone`, + * `cloneDeep`, `cloneDeepWith`, `cloneWith`, `conformsTo`, `deburr`, + * `defaultTo`, `divide`, `each`, `eachRight`, `endsWith`, `eq`, `escape`, + * `escapeRegExp`, `every`, `find`, `findIndex`, `findKey`, `findLast`, + * `findLastIndex`, `findLastKey`, `first`, `floor`, `forEach`, `forEachRight`, + * `forIn`, `forInRight`, `forOwn`, `forOwnRight`, `get`, `gt`, `gte`, `has`, + * `hasIn`, `head`, `identity`, `includes`, `indexOf`, `inRange`, `invoke`, + * `isArguments`, `isArray`, `isArrayBuffer`, `isArrayLike`, `isArrayLikeObject`, + * `isBoolean`, `isBuffer`, `isDate`, `isElement`, `isEmpty`, `isEqual`, + * `isEqualWith`, `isError`, `isFinite`, `isFunction`, `isInteger`, `isLength`, + * `isMap`, `isMatch`, `isMatchWith`, `isNaN`, `isNative`, `isNil`, `isNull`, + * `isNumber`, `isObject`, `isObjectLike`, `isPlainObject`, `isRegExp`, + * `isSafeInteger`, `isSet`, `isString`, `isUndefined`, `isTypedArray`, + * `isWeakMap`, `isWeakSet`, `join`, `kebabCase`, `last`, `lastIndexOf`, + * `lowerCase`, `lowerFirst`, `lt`, `lte`, `max`, `maxBy`, `mean`, `meanBy`, + * `min`, `minBy`, `multiply`, `noConflict`, `noop`, `now`, `nth`, `pad`, + * `padEnd`, `padStart`, `parseInt`, `pop`, `random`, `reduce`, `reduceRight`, + * `repeat`, `result`, `round`, `runInContext`, `sample`, `shift`, `size`, + * `snakeCase`, `some`, `sortedIndex`, `sortedIndexBy`, `sortedLastIndex`, + * `sortedLastIndexBy`, `startCase`, `startsWith`, `stubArray`, `stubFalse`, + * `stubObject`, `stubString`, `stubTrue`, `subtract`, `sum`, `sumBy`, + * `template`, `times`, `toFinite`, `toInteger`, `toJSON`, `toLength`, + * `toLower`, `toNumber`, `toSafeInteger`, `toString`, `toUpper`, `trim`, + * `trimEnd`, `trimStart`, `truncate`, `unescape`, `uniqueId`, `upperCase`, + * `upperFirst`, `value`, and `words` + * + * @name _ + * @constructor + * @category Seq + * @param {*} value The value to wrap in a `lodash` instance. + * @returns {Object} Returns the new `lodash` wrapper instance. + * @example + * + * function square(n) { + * return n * n; + * } + * + * var wrapped = _([1, 2, 3]); + * + * // Returns an unwrapped value. + * wrapped.reduce(_.add); + * // => 6 + * + * // Returns a wrapped value. + * var squares = wrapped.map(square); + * + * _.isArray(squares); + * // => false + * + * _.isArray(squares.value()); + * // => true + */ + function lodash(value) { + if (isObjectLike(value) && !isArray(value) && !(value instanceof LazyWrapper)) { + if (value instanceof LodashWrapper) { + return value; + } + if (hasOwnProperty.call(value, '__wrapped__')) { + return wrapperClone(value); + } + } + return new LodashWrapper(value); + } + + /** + * The base implementation of `_.create` without support for assigning + * properties to the created object. + * + * @private + * @param {Object} proto The object to inherit from. + * @returns {Object} Returns the new object. + */ + var baseCreate = (function() { + function object() {} + return function(proto) { + if (!isObject(proto)) { + return {}; + } + if (objectCreate) { + return objectCreate(proto); + } + object.prototype = proto; + var result = new object; + object.prototype = undefined; + return result; + }; + }()); + + /** + * The function whose prototype chain sequence wrappers inherit from. + * + * @private + */ + function baseLodash() { + // No operation performed. + } + + /** + * The base constructor for creating `lodash` wrapper objects. + * + * @private + * @param {*} value The value to wrap. + * @param {boolean} [chainAll] Enable explicit method chain sequences. + */ + function LodashWrapper(value, chainAll) { + this.__wrapped__ = value; + this.__actions__ = []; + this.__chain__ = !!chainAll; + this.__index__ = 0; + this.__values__ = undefined; + } + + /** + * By default, the template delimiters used by lodash are like those in + * embedded Ruby (ERB) as well as ES2015 template strings. Change the + * following template settings to use alternative delimiters. + * + * @static + * @memberOf _ + * @type {Object} + */ + lodash.templateSettings = { + + /** + * Used to detect `data` property values to be HTML-escaped. + * + * @memberOf _.templateSettings + * @type {RegExp} + */ + 'escape': reEscape, + + /** + * Used to detect code to be evaluated. + * + * @memberOf _.templateSettings + * @type {RegExp} + */ + 'evaluate': reEvaluate, + + /** + * Used to detect `data` property values to inject. + * + * @memberOf _.templateSettings + * @type {RegExp} + */ + 'interpolate': reInterpolate, + + /** + * Used to reference the data object in the template text. + * + * @memberOf _.templateSettings + * @type {string} + */ + 'variable': '', + + /** + * Used to import variables into the compiled template. + * + * @memberOf _.templateSettings + * @type {Object} + */ + 'imports': { + + /** + * A reference to the `lodash` function. + * + * @memberOf _.templateSettings.imports + * @type {Function} + */ + '_': lodash + } + }; + + // Ensure wrappers are instances of `baseLodash`. + lodash.prototype = baseLodash.prototype; + lodash.prototype.constructor = lodash; + + LodashWrapper.prototype = baseCreate(baseLodash.prototype); + LodashWrapper.prototype.constructor = LodashWrapper; + + /*------------------------------------------------------------------------*/ + + /** + * Creates a lazy wrapper object which wraps `value` to enable lazy evaluation. + * + * @private + * @constructor + * @param {*} value The value to wrap. + */ + function LazyWrapper(value) { + this.__wrapped__ = value; + this.__actions__ = []; + this.__dir__ = 1; + this.__filtered__ = false; + this.__iteratees__ = []; + this.__takeCount__ = MAX_ARRAY_LENGTH; + this.__views__ = []; + } + + /** + * Creates a clone of the lazy wrapper object. + * + * @private + * @name clone + * @memberOf LazyWrapper + * @returns {Object} Returns the cloned `LazyWrapper` object. + */ + function lazyClone() { + var result = new LazyWrapper(this.__wrapped__); + result.__actions__ = copyArray(this.__actions__); + result.__dir__ = this.__dir__; + result.__filtered__ = this.__filtered__; + result.__iteratees__ = copyArray(this.__iteratees__); + result.__takeCount__ = this.__takeCount__; + result.__views__ = copyArray(this.__views__); + return result; + } + + /** + * Reverses the direction of lazy iteration. + * + * @private + * @name reverse + * @memberOf LazyWrapper + * @returns {Object} Returns the new reversed `LazyWrapper` object. + */ + function lazyReverse() { + if (this.__filtered__) { + var result = new LazyWrapper(this); + result.__dir__ = -1; + result.__filtered__ = true; + } else { + result = this.clone(); + result.__dir__ *= -1; + } + return result; + } + + /** + * Extracts the unwrapped value from its lazy wrapper. + * + * @private + * @name value + * @memberOf LazyWrapper + * @returns {*} Returns the unwrapped value. + */ + function lazyValue() { + var array = this.__wrapped__.value(), + dir = this.__dir__, + isArr = isArray(array), + isRight = dir < 0, + arrLength = isArr ? array.length : 0, + view = getView(0, arrLength, this.__views__), + start = view.start, + end = view.end, + length = end - start, + index = isRight ? end : (start - 1), + iteratees = this.__iteratees__, + iterLength = iteratees.length, + resIndex = 0, + takeCount = nativeMin(length, this.__takeCount__); + + if (!isArr || (!isRight && arrLength == length && takeCount == length)) { + return baseWrapperValue(array, this.__actions__); + } + var result = []; + + outer: + while (length-- && resIndex < takeCount) { + index += dir; + + var iterIndex = -1, + value = array[index]; + + while (++iterIndex < iterLength) { + var data = iteratees[iterIndex], + iteratee = data.iteratee, + type = data.type, + computed = iteratee(value); + + if (type == LAZY_MAP_FLAG) { + value = computed; + } else if (!computed) { + if (type == LAZY_FILTER_FLAG) { + continue outer; + } else { + break outer; + } + } + } + result[resIndex++] = value; + } + return result; + } + + // Ensure `LazyWrapper` is an instance of `baseLodash`. + LazyWrapper.prototype = baseCreate(baseLodash.prototype); + LazyWrapper.prototype.constructor = LazyWrapper; + + /*------------------------------------------------------------------------*/ + + /** + * Creates a hash object. + * + * @private + * @constructor + * @param {Array} [entries] The key-value pairs to cache. + */ + function Hash(entries) { + var index = -1, + length = entries == null ? 0 : entries.length; + + this.clear(); + while (++index < length) { + var entry = entries[index]; + this.set(entry[0], entry[1]); + } + } + + /** + * Removes all key-value entries from the hash. + * + * @private + * @name clear + * @memberOf Hash + */ + function hashClear() { + this.__data__ = nativeCreate ? nativeCreate(null) : {}; + this.size = 0; + } + + /** + * Removes `key` and its value from the hash. + * + * @private + * @name delete + * @memberOf Hash + * @param {Object} hash The hash to modify. + * @param {string} key The key of the value to remove. + * @returns {boolean} Returns `true` if the entry was removed, else `false`. + */ + function hashDelete(key) { + var result = this.has(key) && delete this.__data__[key]; + this.size -= result ? 1 : 0; + return result; + } + + /** + * Gets the hash value for `key`. + * + * @private + * @name get + * @memberOf Hash + * @param {string} key The key of the value to get. + * @returns {*} Returns the entry value. + */ + function hashGet(key) { + var data = this.__data__; + if (nativeCreate) { + var result = data[key]; + return result === HASH_UNDEFINED ? undefined : result; + } + return hasOwnProperty.call(data, key) ? data[key] : undefined; + } + + /** + * Checks if a hash value for `key` exists. + * + * @private + * @name has + * @memberOf Hash + * @param {string} key The key of the entry to check. + * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. + */ + function hashHas(key) { + var data = this.__data__; + return nativeCreate ? (data[key] !== undefined) : hasOwnProperty.call(data, key); + } + + /** + * Sets the hash `key` to `value`. + * + * @private + * @name set + * @memberOf Hash + * @param {string} key The key of the value to set. + * @param {*} value The value to set. + * @returns {Object} Returns the hash instance. + */ + function hashSet(key, value) { + var data = this.__data__; + this.size += this.has(key) ? 0 : 1; + data[key] = (nativeCreate && value === undefined) ? HASH_UNDEFINED : value; + return this; + } + + // Add methods to `Hash`. + Hash.prototype.clear = hashClear; + Hash.prototype['delete'] = hashDelete; + Hash.prototype.get = hashGet; + Hash.prototype.has = hashHas; + Hash.prototype.set = hashSet; + + /*------------------------------------------------------------------------*/ + + /** + * Creates an list cache object. + * + * @private + * @constructor + * @param {Array} [entries] The key-value pairs to cache. + */ + function ListCache(entries) { + var index = -1, + length = entries == null ? 0 : entries.length; + + this.clear(); + while (++index < length) { + var entry = entries[index]; + this.set(entry[0], entry[1]); + } + } + + /** + * Removes all key-value entries from the list cache. + * + * @private + * @name clear + * @memberOf ListCache + */ + function listCacheClear() { + this.__data__ = []; + this.size = 0; + } + + /** + * Removes `key` and its value from the list cache. + * + * @private + * @name delete + * @memberOf ListCache + * @param {string} key The key of the value to remove. + * @returns {boolean} Returns `true` if the entry was removed, else `false`. + */ + function listCacheDelete(key) { + var data = this.__data__, + index = assocIndexOf(data, key); + + if (index < 0) { + return false; + } + var lastIndex = data.length - 1; + if (index == lastIndex) { + data.pop(); + } else { + splice.call(data, index, 1); + } + --this.size; + return true; + } + + /** + * Gets the list cache value for `key`. + * + * @private + * @name get + * @memberOf ListCache + * @param {string} key The key of the value to get. + * @returns {*} Returns the entry value. + */ + function listCacheGet(key) { + var data = this.__data__, + index = assocIndexOf(data, key); + + return index < 0 ? undefined : data[index][1]; + } + + /** + * Checks if a list cache value for `key` exists. + * + * @private + * @name has + * @memberOf ListCache + * @param {string} key The key of the entry to check. + * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. + */ + function listCacheHas(key) { + return assocIndexOf(this.__data__, key) > -1; + } + + /** + * Sets the list cache `key` to `value`. + * + * @private + * @name set + * @memberOf ListCache + * @param {string} key The key of the value to set. + * @param {*} value The value to set. + * @returns {Object} Returns the list cache instance. + */ + function listCacheSet(key, value) { + var data = this.__data__, + index = assocIndexOf(data, key); + + if (index < 0) { + ++this.size; + data.push([key, value]); + } else { + data[index][1] = value; + } + return this; + } + + // Add methods to `ListCache`. + ListCache.prototype.clear = listCacheClear; + ListCache.prototype['delete'] = listCacheDelete; + ListCache.prototype.get = listCacheGet; + ListCache.prototype.has = listCacheHas; + ListCache.prototype.set = listCacheSet; + + /*------------------------------------------------------------------------*/ + + /** + * Creates a map cache object to store key-value pairs. + * + * @private + * @constructor + * @param {Array} [entries] The key-value pairs to cache. + */ + function MapCache(entries) { + var index = -1, + length = entries == null ? 0 : entries.length; + + this.clear(); + while (++index < length) { + var entry = entries[index]; + this.set(entry[0], entry[1]); + } + } + + /** + * Removes all key-value entries from the map. + * + * @private + * @name clear + * @memberOf MapCache + */ + function mapCacheClear() { + this.size = 0; + this.__data__ = { + 'hash': new Hash, + 'map': new (Map || ListCache), + 'string': new Hash + }; + } + + /** + * Removes `key` and its value from the map. + * + * @private + * @name delete + * @memberOf MapCache + * @param {string} key The key of the value to remove. + * @returns {boolean} Returns `true` if the entry was removed, else `false`. + */ + function mapCacheDelete(key) { + var result = getMapData(this, key)['delete'](key); + this.size -= result ? 1 : 0; + return result; + } + + /** + * Gets the map value for `key`. + * + * @private + * @name get + * @memberOf MapCache + * @param {string} key The key of the value to get. + * @returns {*} Returns the entry value. + */ + function mapCacheGet(key) { + return getMapData(this, key).get(key); + } + + /** + * Checks if a map value for `key` exists. + * + * @private + * @name has + * @memberOf MapCache + * @param {string} key The key of the entry to check. + * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. + */ + function mapCacheHas(key) { + return getMapData(this, key).has(key); + } + + /** + * Sets the map `key` to `value`. + * + * @private + * @name set + * @memberOf MapCache + * @param {string} key The key of the value to set. + * @param {*} value The value to set. + * @returns {Object} Returns the map cache instance. + */ + function mapCacheSet(key, value) { + var data = getMapData(this, key), + size = data.size; + + data.set(key, value); + this.size += data.size == size ? 0 : 1; + return this; + } + + // Add methods to `MapCache`. + MapCache.prototype.clear = mapCacheClear; + MapCache.prototype['delete'] = mapCacheDelete; + MapCache.prototype.get = mapCacheGet; + MapCache.prototype.has = mapCacheHas; + MapCache.prototype.set = mapCacheSet; + + /*------------------------------------------------------------------------*/ + + /** + * + * Creates an array cache object to store unique values. + * + * @private + * @constructor + * @param {Array} [values] The values to cache. + */ + function SetCache(values) { + var index = -1, + length = values == null ? 0 : values.length; + + this.__data__ = new MapCache; + while (++index < length) { + this.add(values[index]); + } + } + + /** + * Adds `value` to the array cache. + * + * @private + * @name add + * @memberOf SetCache + * @alias push + * @param {*} value The value to cache. + * @returns {Object} Returns the cache instance. + */ + function setCacheAdd(value) { + this.__data__.set(value, HASH_UNDEFINED); + return this; + } + + /** + * Checks if `value` is in the array cache. + * + * @private + * @name has + * @memberOf SetCache + * @param {*} value The value to search for. + * @returns {number} Returns `true` if `value` is found, else `false`. + */ + function setCacheHas(value) { + return this.__data__.has(value); + } + + // Add methods to `SetCache`. + SetCache.prototype.add = SetCache.prototype.push = setCacheAdd; + SetCache.prototype.has = setCacheHas; + + /*------------------------------------------------------------------------*/ + + /** + * Creates a stack cache object to store key-value pairs. + * + * @private + * @constructor + * @param {Array} [entries] The key-value pairs to cache. + */ + function Stack(entries) { + var data = this.__data__ = new ListCache(entries); + this.size = data.size; + } + + /** + * Removes all key-value entries from the stack. + * + * @private + * @name clear + * @memberOf Stack + */ + function stackClear() { + this.__data__ = new ListCache; + this.size = 0; + } + + /** + * Removes `key` and its value from the stack. + * + * @private + * @name delete + * @memberOf Stack + * @param {string} key The key of the value to remove. + * @returns {boolean} Returns `true` if the entry was removed, else `false`. + */ + function stackDelete(key) { + var data = this.__data__, + result = data['delete'](key); + + this.size = data.size; + return result; + } + + /** + * Gets the stack value for `key`. + * + * @private + * @name get + * @memberOf Stack + * @param {string} key The key of the value to get. + * @returns {*} Returns the entry value. + */ + function stackGet(key) { + return this.__data__.get(key); + } + + /** + * Checks if a stack value for `key` exists. + * + * @private + * @name has + * @memberOf Stack + * @param {string} key The key of the entry to check. + * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. + */ + function stackHas(key) { + return this.__data__.has(key); + } + + /** + * Sets the stack `key` to `value`. + * + * @private + * @name set + * @memberOf Stack + * @param {string} key The key of the value to set. + * @param {*} value The value to set. + * @returns {Object} Returns the stack cache instance. + */ + function stackSet(key, value) { + var data = this.__data__; + if (data instanceof ListCache) { + var pairs = data.__data__; + if (!Map || (pairs.length < LARGE_ARRAY_SIZE - 1)) { + pairs.push([key, value]); + this.size = ++data.size; + return this; + } + data = this.__data__ = new MapCache(pairs); + } + data.set(key, value); + this.size = data.size; + return this; + } + + // Add methods to `Stack`. + Stack.prototype.clear = stackClear; + Stack.prototype['delete'] = stackDelete; + Stack.prototype.get = stackGet; + Stack.prototype.has = stackHas; + Stack.prototype.set = stackSet; + + /*------------------------------------------------------------------------*/ + + /** + * Creates an array of the enumerable property names of the array-like `value`. + * + * @private + * @param {*} value The value to query. + * @param {boolean} inherited Specify returning inherited property names. + * @returns {Array} Returns the array of property names. + */ + function arrayLikeKeys(value, inherited) { + var isArr = isArray(value), + isArg = !isArr && isArguments(value), + isBuff = !isArr && !isArg && isBuffer(value), + isType = !isArr && !isArg && !isBuff && isTypedArray(value), + skipIndexes = isArr || isArg || isBuff || isType, + result = skipIndexes ? baseTimes(value.length, String) : [], + length = result.length; + + for (var key in value) { + if ((inherited || hasOwnProperty.call(value, key)) && + !(skipIndexes && ( + // Safari 9 has enumerable `arguments.length` in strict mode. + key == 'length' || + // Node.js 0.10 has enumerable non-index properties on buffers. + (isBuff && (key == 'offset' || key == 'parent')) || + // PhantomJS 2 has enumerable non-index properties on typed arrays. + (isType && (key == 'buffer' || key == 'byteLength' || key == 'byteOffset')) || + // Skip index properties. + isIndex(key, length) + ))) { + result.push(key); + } + } + return result; + } + + /** + * A specialized version of `_.sample` for arrays. + * + * @private + * @param {Array} array The array to sample. + * @returns {*} Returns the random element. + */ + function arraySample(array) { + var length = array.length; + return length ? array[baseRandom(0, length - 1)] : undefined; + } + + /** + * A specialized version of `_.sampleSize` for arrays. + * + * @private + * @param {Array} array The array to sample. + * @param {number} n The number of elements to sample. + * @returns {Array} Returns the random elements. + */ + function arraySampleSize(array, n) { + return shuffleSelf(copyArray(array), baseClamp(n, 0, array.length)); + } + + /** + * A specialized version of `_.shuffle` for arrays. + * + * @private + * @param {Array} array The array to shuffle. + * @returns {Array} Returns the new shuffled array. + */ + function arrayShuffle(array) { + return shuffleSelf(copyArray(array)); + } + + /** + * This function is like `assignValue` except that it doesn't assign + * `undefined` values. + * + * @private + * @param {Object} object The object to modify. + * @param {string} key The key of the property to assign. + * @param {*} value The value to assign. + */ + function assignMergeValue(object, key, value) { + if ((value !== undefined && !eq(object[key], value)) || + (value === undefined && !(key in object))) { + baseAssignValue(object, key, value); + } + } + + /** + * Assigns `value` to `key` of `object` if the existing value is not equivalent + * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) + * for equality comparisons. + * + * @private + * @param {Object} object The object to modify. + * @param {string} key The key of the property to assign. + * @param {*} value The value to assign. + */ + function assignValue(object, key, value) { + var objValue = object[key]; + if (!(hasOwnProperty.call(object, key) && eq(objValue, value)) || + (value === undefined && !(key in object))) { + baseAssignValue(object, key, value); + } + } + + /** + * Gets the index at which the `key` is found in `array` of key-value pairs. + * + * @private + * @param {Array} array The array to inspect. + * @param {*} key The key to search for. + * @returns {number} Returns the index of the matched value, else `-1`. + */ + function assocIndexOf(array, key) { + var length = array.length; + while (length--) { + if (eq(array[length][0], key)) { + return length; + } + } + return -1; + } + + /** + * Aggregates elements of `collection` on `accumulator` with keys transformed + * by `iteratee` and values set by `setter`. + * + * @private + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} setter The function to set `accumulator` values. + * @param {Function} iteratee The iteratee to transform keys. + * @param {Object} accumulator The initial aggregated object. + * @returns {Function} Returns `accumulator`. + */ + function baseAggregator(collection, setter, iteratee, accumulator) { + baseEach(collection, function(value, key, collection) { + setter(accumulator, value, iteratee(value), collection); + }); + return accumulator; + } + + /** + * The base implementation of `_.assign` without support for multiple sources + * or `customizer` functions. + * + * @private + * @param {Object} object The destination object. + * @param {Object} source The source object. + * @returns {Object} Returns `object`. + */ + function baseAssign(object, source) { + return object && copyObject(source, keys(source), object); + } + + /** + * The base implementation of `_.assignIn` without support for multiple sources + * or `customizer` functions. + * + * @private + * @param {Object} object The destination object. + * @param {Object} source The source object. + * @returns {Object} Returns `object`. + */ + function baseAssignIn(object, source) { + return object && copyObject(source, keysIn(source), object); + } + + /** + * The base implementation of `assignValue` and `assignMergeValue` without + * value checks. + * + * @private + * @param {Object} object The object to modify. + * @param {string} key The key of the property to assign. + * @param {*} value The value to assign. + */ + function baseAssignValue(object, key, value) { + if (key == '__proto__' && defineProperty) { + defineProperty(object, key, { + 'configurable': true, + 'enumerable': true, + 'value': value, + 'writable': true + }); + } else { + object[key] = value; + } + } + + /** + * The base implementation of `_.at` without support for individual paths. + * + * @private + * @param {Object} object The object to iterate over. + * @param {string[]} paths The property paths to pick. + * @returns {Array} Returns the picked elements. + */ + function baseAt(object, paths) { + var index = -1, + length = paths.length, + result = Array(length), + skip = object == null; + + while (++index < length) { + result[index] = skip ? undefined : get(object, paths[index]); + } + return result; + } + + /** + * The base implementation of `_.clamp` which doesn't coerce arguments. + * + * @private + * @param {number} number The number to clamp. + * @param {number} [lower] The lower bound. + * @param {number} upper The upper bound. + * @returns {number} Returns the clamped number. + */ + function baseClamp(number, lower, upper) { + if (number === number) { + if (upper !== undefined) { + number = number <= upper ? number : upper; + } + if (lower !== undefined) { + number = number >= lower ? number : lower; + } + } + return number; + } + + /** + * The base implementation of `_.clone` and `_.cloneDeep` which tracks + * traversed objects. + * + * @private + * @param {*} value The value to clone. + * @param {boolean} bitmask The bitmask flags. + * 1 - Deep clone + * 2 - Flatten inherited properties + * 4 - Clone symbols + * @param {Function} [customizer] The function to customize cloning. + * @param {string} [key] The key of `value`. + * @param {Object} [object] The parent object of `value`. + * @param {Object} [stack] Tracks traversed objects and their clone counterparts. + * @returns {*} Returns the cloned value. + */ + function baseClone(value, bitmask, customizer, key, object, stack) { + var result, + isDeep = bitmask & CLONE_DEEP_FLAG, + isFlat = bitmask & CLONE_FLAT_FLAG, + isFull = bitmask & CLONE_SYMBOLS_FLAG; + + if (customizer) { + result = object ? customizer(value, key, object, stack) : customizer(value); + } + if (result !== undefined) { + return result; + } + if (!isObject(value)) { + return value; + } + var isArr = isArray(value); + if (isArr) { + result = initCloneArray(value); + if (!isDeep) { + return copyArray(value, result); + } + } else { + var tag = getTag(value), + isFunc = tag == funcTag || tag == genTag; + + if (isBuffer(value)) { + return cloneBuffer(value, isDeep); + } + if (tag == objectTag || tag == argsTag || (isFunc && !object)) { + result = (isFlat || isFunc) ? {} : initCloneObject(value); + if (!isDeep) { + return isFlat + ? copySymbolsIn(value, baseAssignIn(result, value)) + : copySymbols(value, baseAssign(result, value)); + } + } else { + if (!cloneableTags[tag]) { + return object ? value : {}; + } + result = initCloneByTag(value, tag, isDeep); + } + } + // Check for circular references and return its corresponding clone. + stack || (stack = new Stack); + var stacked = stack.get(value); + if (stacked) { + return stacked; + } + stack.set(value, result); + + if (isSet(value)) { + value.forEach(function(subValue) { + result.add(baseClone(subValue, bitmask, customizer, subValue, value, stack)); + }); + } else if (isMap(value)) { + value.forEach(function(subValue, key) { + result.set(key, baseClone(subValue, bitmask, customizer, key, value, stack)); + }); + } + + var keysFunc = isFull + ? (isFlat ? getAllKeysIn : getAllKeys) + : (isFlat ? keysIn : keys); + + var props = isArr ? undefined : keysFunc(value); + arrayEach(props || value, function(subValue, key) { + if (props) { + key = subValue; + subValue = value[key]; + } + // Recursively populate clone (susceptible to call stack limits). + assignValue(result, key, baseClone(subValue, bitmask, customizer, key, value, stack)); + }); + return result; + } + + /** + * The base implementation of `_.conforms` which doesn't clone `source`. + * + * @private + * @param {Object} source The object of property predicates to conform to. + * @returns {Function} Returns the new spec function. + */ + function baseConforms(source) { + var props = keys(source); + return function(object) { + return baseConformsTo(object, source, props); + }; + } + + /** + * The base implementation of `_.conformsTo` which accepts `props` to check. + * + * @private + * @param {Object} object The object to inspect. + * @param {Object} source The object of property predicates to conform to. + * @returns {boolean} Returns `true` if `object` conforms, else `false`. + */ + function baseConformsTo(object, source, props) { + var length = props.length; + if (object == null) { + return !length; + } + object = Object(object); + while (length--) { + var key = props[length], + predicate = source[key], + value = object[key]; + + if ((value === undefined && !(key in object)) || !predicate(value)) { + return false; + } + } + return true; + } + + /** + * The base implementation of `_.delay` and `_.defer` which accepts `args` + * to provide to `func`. + * + * @private + * @param {Function} func The function to delay. + * @param {number} wait The number of milliseconds to delay invocation. + * @param {Array} args The arguments to provide to `func`. + * @returns {number|Object} Returns the timer id or timeout object. + */ + function baseDelay(func, wait, args) { + if (typeof func != 'function') { + throw new TypeError(FUNC_ERROR_TEXT); + } + return setTimeout(function() { func.apply(undefined, args); }, wait); + } + + /** + * The base implementation of methods like `_.difference` without support + * for excluding multiple arrays or iteratee shorthands. + * + * @private + * @param {Array} array The array to inspect. + * @param {Array} values The values to exclude. + * @param {Function} [iteratee] The iteratee invoked per element. + * @param {Function} [comparator] The comparator invoked per element. + * @returns {Array} Returns the new array of filtered values. + */ + function baseDifference(array, values, iteratee, comparator) { + var index = -1, + includes = arrayIncludes, + isCommon = true, + length = array.length, + result = [], + valuesLength = values.length; + + if (!length) { + return result; + } + if (iteratee) { + values = arrayMap(values, baseUnary(iteratee)); + } + if (comparator) { + includes = arrayIncludesWith; + isCommon = false; + } + else if (values.length >= LARGE_ARRAY_SIZE) { + includes = cacheHas; + isCommon = false; + values = new SetCache(values); + } + outer: + while (++index < length) { + var value = array[index], + computed = iteratee == null ? value : iteratee(value); + + value = (comparator || value !== 0) ? value : 0; + if (isCommon && computed === computed) { + var valuesIndex = valuesLength; + while (valuesIndex--) { + if (values[valuesIndex] === computed) { + continue outer; + } + } + result.push(value); + } + else if (!includes(values, computed, comparator)) { + result.push(value); + } + } + return result; + } + + /** + * The base implementation of `_.forEach` without support for iteratee shorthands. + * + * @private + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @returns {Array|Object} Returns `collection`. + */ + var baseEach = createBaseEach(baseForOwn); + + /** + * The base implementation of `_.forEachRight` without support for iteratee shorthands. + * + * @private + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @returns {Array|Object} Returns `collection`. + */ + var baseEachRight = createBaseEach(baseForOwnRight, true); + + /** + * The base implementation of `_.every` without support for iteratee shorthands. + * + * @private + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} predicate The function invoked per iteration. + * @returns {boolean} Returns `true` if all elements pass the predicate check, + * else `false` + */ + function baseEvery(collection, predicate) { + var result = true; + baseEach(collection, function(value, index, collection) { + result = !!predicate(value, index, collection); + return result; + }); + return result; + } + + /** + * The base implementation of methods like `_.max` and `_.min` which accepts a + * `comparator` to determine the extremum value. + * + * @private + * @param {Array} array The array to iterate over. + * @param {Function} iteratee The iteratee invoked per iteration. + * @param {Function} comparator The comparator used to compare values. + * @returns {*} Returns the extremum value. + */ + function baseExtremum(array, iteratee, comparator) { + var index = -1, + length = array.length; + + while (++index < length) { + var value = array[index], + current = iteratee(value); + + if (current != null && (computed === undefined + ? (current === current && !isSymbol(current)) + : comparator(current, computed) + )) { + var computed = current, + result = value; + } + } + return result; + } + + /** + * The base implementation of `_.fill` without an iteratee call guard. + * + * @private + * @param {Array} array The array to fill. + * @param {*} value The value to fill `array` with. + * @param {number} [start=0] The start position. + * @param {number} [end=array.length] The end position. + * @returns {Array} Returns `array`. + */ + function baseFill(array, value, start, end) { + var length = array.length; + + start = toInteger(start); + if (start < 0) { + start = -start > length ? 0 : (length + start); + } + end = (end === undefined || end > length) ? length : toInteger(end); + if (end < 0) { + end += length; + } + end = start > end ? 0 : toLength(end); + while (start < end) { + array[start++] = value; + } + return array; + } + + /** + * The base implementation of `_.filter` without support for iteratee shorthands. + * + * @private + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} predicate The function invoked per iteration. + * @returns {Array} Returns the new filtered array. + */ + function baseFilter(collection, predicate) { + var result = []; + baseEach(collection, function(value, index, collection) { + if (predicate(value, index, collection)) { + result.push(value); + } + }); + return result; + } + + /** + * The base implementation of `_.flatten` with support for restricting flattening. + * + * @private + * @param {Array} array The array to flatten. + * @param {number} depth The maximum recursion depth. + * @param {boolean} [predicate=isFlattenable] The function invoked per iteration. + * @param {boolean} [isStrict] Restrict to values that pass `predicate` checks. + * @param {Array} [result=[]] The initial result value. + * @returns {Array} Returns the new flattened array. + */ + function baseFlatten(array, depth, predicate, isStrict, result) { + var index = -1, + length = array.length; + + predicate || (predicate = isFlattenable); + result || (result = []); + + while (++index < length) { + var value = array[index]; + if (depth > 0 && predicate(value)) { + if (depth > 1) { + // Recursively flatten arrays (susceptible to call stack limits). + baseFlatten(value, depth - 1, predicate, isStrict, result); + } else { + arrayPush(result, value); + } + } else if (!isStrict) { + result[result.length] = value; + } + } + return result; + } + + /** + * The base implementation of `baseForOwn` which iterates over `object` + * properties returned by `keysFunc` and invokes `iteratee` for each property. + * Iteratee functions may exit iteration early by explicitly returning `false`. + * + * @private + * @param {Object} object The object to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @param {Function} keysFunc The function to get the keys of `object`. + * @returns {Object} Returns `object`. + */ + var baseFor = createBaseFor(); + + /** + * This function is like `baseFor` except that it iterates over properties + * in the opposite order. + * + * @private + * @param {Object} object The object to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @param {Function} keysFunc The function to get the keys of `object`. + * @returns {Object} Returns `object`. + */ + var baseForRight = createBaseFor(true); + + /** + * The base implementation of `_.forOwn` without support for iteratee shorthands. + * + * @private + * @param {Object} object The object to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @returns {Object} Returns `object`. + */ + function baseForOwn(object, iteratee) { + return object && baseFor(object, iteratee, keys); + } + + /** + * The base implementation of `_.forOwnRight` without support for iteratee shorthands. + * + * @private + * @param {Object} object The object to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @returns {Object} Returns `object`. + */ + function baseForOwnRight(object, iteratee) { + return object && baseForRight(object, iteratee, keys); + } + + /** + * The base implementation of `_.functions` which creates an array of + * `object` function property names filtered from `props`. + * + * @private + * @param {Object} object The object to inspect. + * @param {Array} props The property names to filter. + * @returns {Array} Returns the function names. + */ + function baseFunctions(object, props) { + return arrayFilter(props, function(key) { + return isFunction(object[key]); + }); + } + + /** + * The base implementation of `_.get` without support for default values. + * + * @private + * @param {Object} object The object to query. + * @param {Array|string} path The path of the property to get. + * @returns {*} Returns the resolved value. + */ + function baseGet(object, path) { + path = castPath(path, object); + + var index = 0, + length = path.length; + + while (object != null && index < length) { + object = object[toKey(path[index++])]; + } + return (index && index == length) ? object : undefined; + } + + /** + * The base implementation of `getAllKeys` and `getAllKeysIn` which uses + * `keysFunc` and `symbolsFunc` to get the enumerable property names and + * symbols of `object`. + * + * @private + * @param {Object} object The object to query. + * @param {Function} keysFunc The function to get the keys of `object`. + * @param {Function} symbolsFunc The function to get the symbols of `object`. + * @returns {Array} Returns the array of property names and symbols. + */ + function baseGetAllKeys(object, keysFunc, symbolsFunc) { + var result = keysFunc(object); + return isArray(object) ? result : arrayPush(result, symbolsFunc(object)); + } + + /** + * The base implementation of `getTag` without fallbacks for buggy environments. + * + * @private + * @param {*} value The value to query. + * @returns {string} Returns the `toStringTag`. + */ + function baseGetTag(value) { + if (value == null) { + return value === undefined ? undefinedTag : nullTag; + } + return (symToStringTag && symToStringTag in Object(value)) + ? getRawTag(value) + : objectToString(value); + } + + /** + * The base implementation of `_.gt` which doesn't coerce arguments. + * + * @private + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @returns {boolean} Returns `true` if `value` is greater than `other`, + * else `false`. + */ + function baseGt(value, other) { + return value > other; + } + + /** + * The base implementation of `_.has` without support for deep paths. + * + * @private + * @param {Object} [object] The object to query. + * @param {Array|string} key The key to check. + * @returns {boolean} Returns `true` if `key` exists, else `false`. + */ + function baseHas(object, key) { + return object != null && hasOwnProperty.call(object, key); + } + + /** + * The base implementation of `_.hasIn` without support for deep paths. + * + * @private + * @param {Object} [object] The object to query. + * @param {Array|string} key The key to check. + * @returns {boolean} Returns `true` if `key` exists, else `false`. + */ + function baseHasIn(object, key) { + return object != null && key in Object(object); + } + + /** + * The base implementation of `_.inRange` which doesn't coerce arguments. + * + * @private + * @param {number} number The number to check. + * @param {number} start The start of the range. + * @param {number} end The end of the range. + * @returns {boolean} Returns `true` if `number` is in the range, else `false`. + */ + function baseInRange(number, start, end) { + return number >= nativeMin(start, end) && number < nativeMax(start, end); + } + + /** + * The base implementation of methods like `_.intersection`, without support + * for iteratee shorthands, that accepts an array of arrays to inspect. + * + * @private + * @param {Array} arrays The arrays to inspect. + * @param {Function} [iteratee] The iteratee invoked per element. + * @param {Function} [comparator] The comparator invoked per element. + * @returns {Array} Returns the new array of shared values. + */ + function baseIntersection(arrays, iteratee, comparator) { + var includes = comparator ? arrayIncludesWith : arrayIncludes, + length = arrays[0].length, + othLength = arrays.length, + othIndex = othLength, + caches = Array(othLength), + maxLength = Infinity, + result = []; + + while (othIndex--) { + var array = arrays[othIndex]; + if (othIndex && iteratee) { + array = arrayMap(array, baseUnary(iteratee)); + } + maxLength = nativeMin(array.length, maxLength); + caches[othIndex] = !comparator && (iteratee || (length >= 120 && array.length >= 120)) + ? new SetCache(othIndex && array) + : undefined; + } + array = arrays[0]; + + var index = -1, + seen = caches[0]; + + outer: + while (++index < length && result.length < maxLength) { + var value = array[index], + computed = iteratee ? iteratee(value) : value; + + value = (comparator || value !== 0) ? value : 0; + if (!(seen + ? cacheHas(seen, computed) + : includes(result, computed, comparator) + )) { + othIndex = othLength; + while (--othIndex) { + var cache = caches[othIndex]; + if (!(cache + ? cacheHas(cache, computed) + : includes(arrays[othIndex], computed, comparator)) + ) { + continue outer; + } + } + if (seen) { + seen.push(computed); + } + result.push(value); + } + } + return result; + } + + /** + * The base implementation of `_.invert` and `_.invertBy` which inverts + * `object` with values transformed by `iteratee` and set by `setter`. + * + * @private + * @param {Object} object The object to iterate over. + * @param {Function} setter The function to set `accumulator` values. + * @param {Function} iteratee The iteratee to transform values. + * @param {Object} accumulator The initial inverted object. + * @returns {Function} Returns `accumulator`. + */ + function baseInverter(object, setter, iteratee, accumulator) { + baseForOwn(object, function(value, key, object) { + setter(accumulator, iteratee(value), key, object); + }); + return accumulator; + } + + /** + * The base implementation of `_.invoke` without support for individual + * method arguments. + * + * @private + * @param {Object} object The object to query. + * @param {Array|string} path The path of the method to invoke. + * @param {Array} args The arguments to invoke the method with. + * @returns {*} Returns the result of the invoked method. + */ + function baseInvoke(object, path, args) { + path = castPath(path, object); + object = parent(object, path); + var func = object == null ? object : object[toKey(last(path))]; + return func == null ? undefined : apply(func, object, args); + } + + /** + * The base implementation of `_.isArguments`. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an `arguments` object, + */ + function baseIsArguments(value) { + return isObjectLike(value) && baseGetTag(value) == argsTag; + } + + /** + * The base implementation of `_.isArrayBuffer` without Node.js optimizations. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an array buffer, else `false`. + */ + function baseIsArrayBuffer(value) { + return isObjectLike(value) && baseGetTag(value) == arrayBufferTag; + } + + /** + * The base implementation of `_.isDate` without Node.js optimizations. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a date object, else `false`. + */ + function baseIsDate(value) { + return isObjectLike(value) && baseGetTag(value) == dateTag; + } + + /** + * The base implementation of `_.isEqual` which supports partial comparisons + * and tracks traversed objects. + * + * @private + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @param {boolean} bitmask The bitmask flags. + * 1 - Unordered comparison + * 2 - Partial comparison + * @param {Function} [customizer] The function to customize comparisons. + * @param {Object} [stack] Tracks traversed `value` and `other` objects. + * @returns {boolean} Returns `true` if the values are equivalent, else `false`. + */ + function baseIsEqual(value, other, bitmask, customizer, stack) { + if (value === other) { + return true; + } + if (value == null || other == null || (!isObjectLike(value) && !isObjectLike(other))) { + return value !== value && other !== other; + } + return baseIsEqualDeep(value, other, bitmask, customizer, baseIsEqual, stack); + } + + /** + * A specialized version of `baseIsEqual` for arrays and objects which performs + * deep comparisons and tracks traversed objects enabling objects with circular + * references to be compared. + * + * @private + * @param {Object} object The object to compare. + * @param {Object} other The other object to compare. + * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details. + * @param {Function} customizer The function to customize comparisons. + * @param {Function} equalFunc The function to determine equivalents of values. + * @param {Object} [stack] Tracks traversed `object` and `other` objects. + * @returns {boolean} Returns `true` if the objects are equivalent, else `false`. + */ + function baseIsEqualDeep(object, other, bitmask, customizer, equalFunc, stack) { + var objIsArr = isArray(object), + othIsArr = isArray(other), + objTag = objIsArr ? arrayTag : getTag(object), + othTag = othIsArr ? arrayTag : getTag(other); + + objTag = objTag == argsTag ? objectTag : objTag; + othTag = othTag == argsTag ? objectTag : othTag; + + var objIsObj = objTag == objectTag, + othIsObj = othTag == objectTag, + isSameTag = objTag == othTag; + + if (isSameTag && isBuffer(object)) { + if (!isBuffer(other)) { + return false; + } + objIsArr = true; + objIsObj = false; + } + if (isSameTag && !objIsObj) { + stack || (stack = new Stack); + return (objIsArr || isTypedArray(object)) + ? equalArrays(object, other, bitmask, customizer, equalFunc, stack) + : equalByTag(object, other, objTag, bitmask, customizer, equalFunc, stack); + } + if (!(bitmask & COMPARE_PARTIAL_FLAG)) { + var objIsWrapped = objIsObj && hasOwnProperty.call(object, '__wrapped__'), + othIsWrapped = othIsObj && hasOwnProperty.call(other, '__wrapped__'); + + if (objIsWrapped || othIsWrapped) { + var objUnwrapped = objIsWrapped ? object.value() : object, + othUnwrapped = othIsWrapped ? other.value() : other; + + stack || (stack = new Stack); + return equalFunc(objUnwrapped, othUnwrapped, bitmask, customizer, stack); + } + } + if (!isSameTag) { + return false; + } + stack || (stack = new Stack); + return equalObjects(object, other, bitmask, customizer, equalFunc, stack); + } + + /** + * The base implementation of `_.isMap` without Node.js optimizations. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a map, else `false`. + */ + function baseIsMap(value) { + return isObjectLike(value) && getTag(value) == mapTag; + } + + /** + * The base implementation of `_.isMatch` without support for iteratee shorthands. + * + * @private + * @param {Object} object The object to inspect. + * @param {Object} source The object of property values to match. + * @param {Array} matchData The property names, values, and compare flags to match. + * @param {Function} [customizer] The function to customize comparisons. + * @returns {boolean} Returns `true` if `object` is a match, else `false`. + */ + function baseIsMatch(object, source, matchData, customizer) { + var index = matchData.length, + length = index, + noCustomizer = !customizer; + + if (object == null) { + return !length; + } + object = Object(object); + while (index--) { + var data = matchData[index]; + if ((noCustomizer && data[2]) + ? data[1] !== object[data[0]] + : !(data[0] in object) + ) { + return false; + } + } + while (++index < length) { + data = matchData[index]; + var key = data[0], + objValue = object[key], + srcValue = data[1]; + + if (noCustomizer && data[2]) { + if (objValue === undefined && !(key in object)) { + return false; + } + } else { + var stack = new Stack; + if (customizer) { + var result = customizer(objValue, srcValue, key, object, source, stack); + } + if (!(result === undefined + ? baseIsEqual(srcValue, objValue, COMPARE_PARTIAL_FLAG | COMPARE_UNORDERED_FLAG, customizer, stack) + : result + )) { + return false; + } + } + } + return true; + } + + /** + * The base implementation of `_.isNative` without bad shim checks. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a native function, + * else `false`. + */ + function baseIsNative(value) { + if (!isObject(value) || isMasked(value)) { + return false; + } + var pattern = isFunction(value) ? reIsNative : reIsHostCtor; + return pattern.test(toSource(value)); + } + + /** + * The base implementation of `_.isRegExp` without Node.js optimizations. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a regexp, else `false`. + */ + function baseIsRegExp(value) { + return isObjectLike(value) && baseGetTag(value) == regexpTag; + } + + /** + * The base implementation of `_.isSet` without Node.js optimizations. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a set, else `false`. + */ + function baseIsSet(value) { + return isObjectLike(value) && getTag(value) == setTag; + } + + /** + * The base implementation of `_.isTypedArray` without Node.js optimizations. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a typed array, else `false`. + */ + function baseIsTypedArray(value) { + return isObjectLike(value) && + isLength(value.length) && !!typedArrayTags[baseGetTag(value)]; + } + + /** + * The base implementation of `_.iteratee`. + * + * @private + * @param {*} [value=_.identity] The value to convert to an iteratee. + * @returns {Function} Returns the iteratee. + */ + function baseIteratee(value) { + // Don't store the `typeof` result in a variable to avoid a JIT bug in Safari 9. + // See https://bugs.webkit.org/show_bug.cgi?id=156034 for more details. + if (typeof value == 'function') { + return value; + } + if (value == null) { + return identity; + } + if (typeof value == 'object') { + return isArray(value) + ? baseMatchesProperty(value[0], value[1]) + : baseMatches(value); + } + return property(value); + } + + /** + * The base implementation of `_.keys` which doesn't treat sparse arrays as dense. + * + * @private + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property names. + */ + function baseKeys(object) { + if (!isPrototype(object)) { + return nativeKeys(object); + } + var result = []; + for (var key in Object(object)) { + if (hasOwnProperty.call(object, key) && key != 'constructor') { + result.push(key); + } + } + return result; + } + + /** + * The base implementation of `_.keysIn` which doesn't treat sparse arrays as dense. + * + * @private + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property names. + */ + function baseKeysIn(object) { + if (!isObject(object)) { + return nativeKeysIn(object); + } + var isProto = isPrototype(object), + result = []; + + for (var key in object) { + if (!(key == 'constructor' && (isProto || !hasOwnProperty.call(object, key)))) { + result.push(key); + } + } + return result; + } + + /** + * The base implementation of `_.lt` which doesn't coerce arguments. + * + * @private + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @returns {boolean} Returns `true` if `value` is less than `other`, + * else `false`. + */ + function baseLt(value, other) { + return value < other; + } + + /** + * The base implementation of `_.map` without support for iteratee shorthands. + * + * @private + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @returns {Array} Returns the new mapped array. + */ + function baseMap(collection, iteratee) { + var index = -1, + result = isArrayLike(collection) ? Array(collection.length) : []; + + baseEach(collection, function(value, key, collection) { + result[++index] = iteratee(value, key, collection); + }); + return result; + } + + /** + * The base implementation of `_.matches` which doesn't clone `source`. + * + * @private + * @param {Object} source The object of property values to match. + * @returns {Function} Returns the new spec function. + */ + function baseMatches(source) { + var matchData = getMatchData(source); + if (matchData.length == 1 && matchData[0][2]) { + return matchesStrictComparable(matchData[0][0], matchData[0][1]); + } + return function(object) { + return object === source || baseIsMatch(object, source, matchData); + }; + } + + /** + * The base implementation of `_.matchesProperty` which doesn't clone `srcValue`. + * + * @private + * @param {string} path The path of the property to get. + * @param {*} srcValue The value to match. + * @returns {Function} Returns the new spec function. + */ + function baseMatchesProperty(path, srcValue) { + if (isKey(path) && isStrictComparable(srcValue)) { + return matchesStrictComparable(toKey(path), srcValue); + } + return function(object) { + var objValue = get(object, path); + return (objValue === undefined && objValue === srcValue) + ? hasIn(object, path) + : baseIsEqual(srcValue, objValue, COMPARE_PARTIAL_FLAG | COMPARE_UNORDERED_FLAG); + }; + } + + /** + * The base implementation of `_.merge` without support for multiple sources. + * + * @private + * @param {Object} object The destination object. + * @param {Object} source The source object. + * @param {number} srcIndex The index of `source`. + * @param {Function} [customizer] The function to customize merged values. + * @param {Object} [stack] Tracks traversed source values and their merged + * counterparts. + */ + function baseMerge(object, source, srcIndex, customizer, stack) { + if (object === source) { + return; + } + baseFor(source, function(srcValue, key) { + stack || (stack = new Stack); + if (isObject(srcValue)) { + baseMergeDeep(object, source, key, srcIndex, baseMerge, customizer, stack); + } + else { + var newValue = customizer + ? customizer(safeGet(object, key), srcValue, (key + ''), object, source, stack) + : undefined; + + if (newValue === undefined) { + newValue = srcValue; + } + assignMergeValue(object, key, newValue); + } + }, keysIn); + } + + /** + * A specialized version of `baseMerge` for arrays and objects which performs + * deep merges and tracks traversed objects enabling objects with circular + * references to be merged. + * + * @private + * @param {Object} object The destination object. + * @param {Object} source The source object. + * @param {string} key The key of the value to merge. + * @param {number} srcIndex The index of `source`. + * @param {Function} mergeFunc The function to merge values. + * @param {Function} [customizer] The function to customize assigned values. + * @param {Object} [stack] Tracks traversed source values and their merged + * counterparts. + */ + function baseMergeDeep(object, source, key, srcIndex, mergeFunc, customizer, stack) { + var objValue = safeGet(object, key), + srcValue = safeGet(source, key), + stacked = stack.get(srcValue); + + if (stacked) { + assignMergeValue(object, key, stacked); + return; + } + var newValue = customizer + ? customizer(objValue, srcValue, (key + ''), object, source, stack) + : undefined; + + var isCommon = newValue === undefined; + + if (isCommon) { + var isArr = isArray(srcValue), + isBuff = !isArr && isBuffer(srcValue), + isTyped = !isArr && !isBuff && isTypedArray(srcValue); + + newValue = srcValue; + if (isArr || isBuff || isTyped) { + if (isArray(objValue)) { + newValue = objValue; + } + else if (isArrayLikeObject(objValue)) { + newValue = copyArray(objValue); + } + else if (isBuff) { + isCommon = false; + newValue = cloneBuffer(srcValue, true); + } + else if (isTyped) { + isCommon = false; + newValue = cloneTypedArray(srcValue, true); + } + else { + newValue = []; + } + } + else if (isPlainObject(srcValue) || isArguments(srcValue)) { + newValue = objValue; + if (isArguments(objValue)) { + newValue = toPlainObject(objValue); + } + else if (!isObject(objValue) || isFunction(objValue)) { + newValue = initCloneObject(srcValue); + } + } + else { + isCommon = false; + } + } + if (isCommon) { + // Recursively merge objects and arrays (susceptible to call stack limits). + stack.set(srcValue, newValue); + mergeFunc(newValue, srcValue, srcIndex, customizer, stack); + stack['delete'](srcValue); + } + assignMergeValue(object, key, newValue); + } + + /** + * The base implementation of `_.nth` which doesn't coerce arguments. + * + * @private + * @param {Array} array The array to query. + * @param {number} n The index of the element to return. + * @returns {*} Returns the nth element of `array`. + */ + function baseNth(array, n) { + var length = array.length; + if (!length) { + return; + } + n += n < 0 ? length : 0; + return isIndex(n, length) ? array[n] : undefined; + } + + /** + * The base implementation of `_.orderBy` without param guards. + * + * @private + * @param {Array|Object} collection The collection to iterate over. + * @param {Function[]|Object[]|string[]} iteratees The iteratees to sort by. + * @param {string[]} orders The sort orders of `iteratees`. + * @returns {Array} Returns the new sorted array. + */ + function baseOrderBy(collection, iteratees, orders) { + if (iteratees.length) { + iteratees = arrayMap(iteratees, function(iteratee) { + if (isArray(iteratee)) { + return function(value) { + return baseGet(value, iteratee.length === 1 ? iteratee[0] : iteratee); + } + } + return iteratee; + }); + } else { + iteratees = [identity]; + } + + var index = -1; + iteratees = arrayMap(iteratees, baseUnary(getIteratee())); + + var result = baseMap(collection, function(value, key, collection) { + var criteria = arrayMap(iteratees, function(iteratee) { + return iteratee(value); + }); + return { 'criteria': criteria, 'index': ++index, 'value': value }; + }); + + return baseSortBy(result, function(object, other) { + return compareMultiple(object, other, orders); + }); + } + + /** + * The base implementation of `_.pick` without support for individual + * property identifiers. + * + * @private + * @param {Object} object The source object. + * @param {string[]} paths The property paths to pick. + * @returns {Object} Returns the new object. + */ + function basePick(object, paths) { + return basePickBy(object, paths, function(value, path) { + return hasIn(object, path); + }); + } + + /** + * The base implementation of `_.pickBy` without support for iteratee shorthands. + * + * @private + * @param {Object} object The source object. + * @param {string[]} paths The property paths to pick. + * @param {Function} predicate The function invoked per property. + * @returns {Object} Returns the new object. + */ + function basePickBy(object, paths, predicate) { + var index = -1, + length = paths.length, + result = {}; + + while (++index < length) { + var path = paths[index], + value = baseGet(object, path); + + if (predicate(value, path)) { + baseSet(result, castPath(path, object), value); + } + } + return result; + } + + /** + * A specialized version of `baseProperty` which supports deep paths. + * + * @private + * @param {Array|string} path The path of the property to get. + * @returns {Function} Returns the new accessor function. + */ + function basePropertyDeep(path) { + return function(object) { + return baseGet(object, path); + }; + } + + /** + * The base implementation of `_.pullAllBy` without support for iteratee + * shorthands. + * + * @private + * @param {Array} array The array to modify. + * @param {Array} values The values to remove. + * @param {Function} [iteratee] The iteratee invoked per element. + * @param {Function} [comparator] The comparator invoked per element. + * @returns {Array} Returns `array`. + */ + function basePullAll(array, values, iteratee, comparator) { + var indexOf = comparator ? baseIndexOfWith : baseIndexOf, + index = -1, + length = values.length, + seen = array; + + if (array === values) { + values = copyArray(values); + } + if (iteratee) { + seen = arrayMap(array, baseUnary(iteratee)); + } + while (++index < length) { + var fromIndex = 0, + value = values[index], + computed = iteratee ? iteratee(value) : value; + + while ((fromIndex = indexOf(seen, computed, fromIndex, comparator)) > -1) { + if (seen !== array) { + splice.call(seen, fromIndex, 1); + } + splice.call(array, fromIndex, 1); + } + } + return array; + } + + /** + * The base implementation of `_.pullAt` without support for individual + * indexes or capturing the removed elements. + * + * @private + * @param {Array} array The array to modify. + * @param {number[]} indexes The indexes of elements to remove. + * @returns {Array} Returns `array`. + */ + function basePullAt(array, indexes) { + var length = array ? indexes.length : 0, + lastIndex = length - 1; + + while (length--) { + var index = indexes[length]; + if (length == lastIndex || index !== previous) { + var previous = index; + if (isIndex(index)) { + splice.call(array, index, 1); + } else { + baseUnset(array, index); + } + } + } + return array; + } + + /** + * The base implementation of `_.random` without support for returning + * floating-point numbers. + * + * @private + * @param {number} lower The lower bound. + * @param {number} upper The upper bound. + * @returns {number} Returns the random number. + */ + function baseRandom(lower, upper) { + return lower + nativeFloor(nativeRandom() * (upper - lower + 1)); + } + + /** + * The base implementation of `_.range` and `_.rangeRight` which doesn't + * coerce arguments. + * + * @private + * @param {number} start The start of the range. + * @param {number} end The end of the range. + * @param {number} step The value to increment or decrement by. + * @param {boolean} [fromRight] Specify iterating from right to left. + * @returns {Array} Returns the range of numbers. + */ + function baseRange(start, end, step, fromRight) { + var index = -1, + length = nativeMax(nativeCeil((end - start) / (step || 1)), 0), + result = Array(length); + + while (length--) { + result[fromRight ? length : ++index] = start; + start += step; + } + return result; + } + + /** + * The base implementation of `_.repeat` which doesn't coerce arguments. + * + * @private + * @param {string} string The string to repeat. + * @param {number} n The number of times to repeat the string. + * @returns {string} Returns the repeated string. + */ + function baseRepeat(string, n) { + var result = ''; + if (!string || n < 1 || n > MAX_SAFE_INTEGER) { + return result; + } + // Leverage the exponentiation by squaring algorithm for a faster repeat. + // See https://en.wikipedia.org/wiki/Exponentiation_by_squaring for more details. + do { + if (n % 2) { + result += string; + } + n = nativeFloor(n / 2); + if (n) { + string += string; + } + } while (n); + + return result; + } + + /** + * The base implementation of `_.rest` which doesn't validate or coerce arguments. + * + * @private + * @param {Function} func The function to apply a rest parameter to. + * @param {number} [start=func.length-1] The start position of the rest parameter. + * @returns {Function} Returns the new function. + */ + function baseRest(func, start) { + return setToString(overRest(func, start, identity), func + ''); + } + + /** + * The base implementation of `_.sample`. + * + * @private + * @param {Array|Object} collection The collection to sample. + * @returns {*} Returns the random element. + */ + function baseSample(collection) { + return arraySample(values(collection)); + } + + /** + * The base implementation of `_.sampleSize` without param guards. + * + * @private + * @param {Array|Object} collection The collection to sample. + * @param {number} n The number of elements to sample. + * @returns {Array} Returns the random elements. + */ + function baseSampleSize(collection, n) { + var array = values(collection); + return shuffleSelf(array, baseClamp(n, 0, array.length)); + } + + /** + * The base implementation of `_.set`. + * + * @private + * @param {Object} object The object to modify. + * @param {Array|string} path The path of the property to set. + * @param {*} value The value to set. + * @param {Function} [customizer] The function to customize path creation. + * @returns {Object} Returns `object`. + */ + function baseSet(object, path, value, customizer) { + if (!isObject(object)) { + return object; + } + path = castPath(path, object); + + var index = -1, + length = path.length, + lastIndex = length - 1, + nested = object; + + while (nested != null && ++index < length) { + var key = toKey(path[index]), + newValue = value; + + if (key === '__proto__' || key === 'constructor' || key === 'prototype') { + return object; + } + + if (index != lastIndex) { + var objValue = nested[key]; + newValue = customizer ? customizer(objValue, key, nested) : undefined; + if (newValue === undefined) { + newValue = isObject(objValue) + ? objValue + : (isIndex(path[index + 1]) ? [] : {}); + } + } + assignValue(nested, key, newValue); + nested = nested[key]; + } + return object; + } + + /** + * The base implementation of `setData` without support for hot loop shorting. + * + * @private + * @param {Function} func The function to associate metadata with. + * @param {*} data The metadata. + * @returns {Function} Returns `func`. + */ + var baseSetData = !metaMap ? identity : function(func, data) { + metaMap.set(func, data); + return func; + }; + + /** + * The base implementation of `setToString` without support for hot loop shorting. + * + * @private + * @param {Function} func The function to modify. + * @param {Function} string The `toString` result. + * @returns {Function} Returns `func`. + */ + var baseSetToString = !defineProperty ? identity : function(func, string) { + return defineProperty(func, 'toString', { + 'configurable': true, + 'enumerable': false, + 'value': constant(string), + 'writable': true + }); + }; + + /** + * The base implementation of `_.shuffle`. + * + * @private + * @param {Array|Object} collection The collection to shuffle. + * @returns {Array} Returns the new shuffled array. + */ + function baseShuffle(collection) { + return shuffleSelf(values(collection)); + } + + /** + * The base implementation of `_.slice` without an iteratee call guard. + * + * @private + * @param {Array} array The array to slice. + * @param {number} [start=0] The start position. + * @param {number} [end=array.length] The end position. + * @returns {Array} Returns the slice of `array`. + */ + function baseSlice(array, start, end) { + var index = -1, + length = array.length; + + if (start < 0) { + start = -start > length ? 0 : (length + start); + } + end = end > length ? length : end; + if (end < 0) { + end += length; + } + length = start > end ? 0 : ((end - start) >>> 0); + start >>>= 0; + + var result = Array(length); + while (++index < length) { + result[index] = array[index + start]; + } + return result; + } + + /** + * The base implementation of `_.some` without support for iteratee shorthands. + * + * @private + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} predicate The function invoked per iteration. + * @returns {boolean} Returns `true` if any element passes the predicate check, + * else `false`. + */ + function baseSome(collection, predicate) { + var result; + + baseEach(collection, function(value, index, collection) { + result = predicate(value, index, collection); + return !result; + }); + return !!result; + } + + /** + * The base implementation of `_.sortedIndex` and `_.sortedLastIndex` which + * performs a binary search of `array` to determine the index at which `value` + * should be inserted into `array` in order to maintain its sort order. + * + * @private + * @param {Array} array The sorted array to inspect. + * @param {*} value The value to evaluate. + * @param {boolean} [retHighest] Specify returning the highest qualified index. + * @returns {number} Returns the index at which `value` should be inserted + * into `array`. + */ + function baseSortedIndex(array, value, retHighest) { + var low = 0, + high = array == null ? low : array.length; + + if (typeof value == 'number' && value === value && high <= HALF_MAX_ARRAY_LENGTH) { + while (low < high) { + var mid = (low + high) >>> 1, + computed = array[mid]; + + if (computed !== null && !isSymbol(computed) && + (retHighest ? (computed <= value) : (computed < value))) { + low = mid + 1; + } else { + high = mid; + } + } + return high; + } + return baseSortedIndexBy(array, value, identity, retHighest); + } + + /** + * The base implementation of `_.sortedIndexBy` and `_.sortedLastIndexBy` + * which invokes `iteratee` for `value` and each element of `array` to compute + * their sort ranking. The iteratee is invoked with one argument; (value). + * + * @private + * @param {Array} array The sorted array to inspect. + * @param {*} value The value to evaluate. + * @param {Function} iteratee The iteratee invoked per element. + * @param {boolean} [retHighest] Specify returning the highest qualified index. + * @returns {number} Returns the index at which `value` should be inserted + * into `array`. + */ + function baseSortedIndexBy(array, value, iteratee, retHighest) { + var low = 0, + high = array == null ? 0 : array.length; + if (high === 0) { + return 0; + } + + value = iteratee(value); + var valIsNaN = value !== value, + valIsNull = value === null, + valIsSymbol = isSymbol(value), + valIsUndefined = value === undefined; + + while (low < high) { + var mid = nativeFloor((low + high) / 2), + computed = iteratee(array[mid]), + othIsDefined = computed !== undefined, + othIsNull = computed === null, + othIsReflexive = computed === computed, + othIsSymbol = isSymbol(computed); + + if (valIsNaN) { + var setLow = retHighest || othIsReflexive; + } else if (valIsUndefined) { + setLow = othIsReflexive && (retHighest || othIsDefined); + } else if (valIsNull) { + setLow = othIsReflexive && othIsDefined && (retHighest || !othIsNull); + } else if (valIsSymbol) { + setLow = othIsReflexive && othIsDefined && !othIsNull && (retHighest || !othIsSymbol); + } else if (othIsNull || othIsSymbol) { + setLow = false; + } else { + setLow = retHighest ? (computed <= value) : (computed < value); + } + if (setLow) { + low = mid + 1; + } else { + high = mid; + } + } + return nativeMin(high, MAX_ARRAY_INDEX); + } + + /** + * The base implementation of `_.sortedUniq` and `_.sortedUniqBy` without + * support for iteratee shorthands. + * + * @private + * @param {Array} array The array to inspect. + * @param {Function} [iteratee] The iteratee invoked per element. + * @returns {Array} Returns the new duplicate free array. + */ + function baseSortedUniq(array, iteratee) { + var index = -1, + length = array.length, + resIndex = 0, + result = []; + + while (++index < length) { + var value = array[index], + computed = iteratee ? iteratee(value) : value; + + if (!index || !eq(computed, seen)) { + var seen = computed; + result[resIndex++] = value === 0 ? 0 : value; + } + } + return result; + } + + /** + * The base implementation of `_.toNumber` which doesn't ensure correct + * conversions of binary, hexadecimal, or octal string values. + * + * @private + * @param {*} value The value to process. + * @returns {number} Returns the number. + */ + function baseToNumber(value) { + if (typeof value == 'number') { + return value; + } + if (isSymbol(value)) { + return NAN; + } + return +value; + } + + /** + * The base implementation of `_.toString` which doesn't convert nullish + * values to empty strings. + * + * @private + * @param {*} value The value to process. + * @returns {string} Returns the string. + */ + function baseToString(value) { + // Exit early for strings to avoid a performance hit in some environments. + if (typeof value == 'string') { + return value; + } + if (isArray(value)) { + // Recursively convert values (susceptible to call stack limits). + return arrayMap(value, baseToString) + ''; + } + if (isSymbol(value)) { + return symbolToString ? symbolToString.call(value) : ''; + } + var result = (value + ''); + return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result; + } + + /** + * The base implementation of `_.uniqBy` without support for iteratee shorthands. + * + * @private + * @param {Array} array The array to inspect. + * @param {Function} [iteratee] The iteratee invoked per element. + * @param {Function} [comparator] The comparator invoked per element. + * @returns {Array} Returns the new duplicate free array. + */ + function baseUniq(array, iteratee, comparator) { + var index = -1, + includes = arrayIncludes, + length = array.length, + isCommon = true, + result = [], + seen = result; + + if (comparator) { + isCommon = false; + includes = arrayIncludesWith; + } + else if (length >= LARGE_ARRAY_SIZE) { + var set = iteratee ? null : createSet(array); + if (set) { + return setToArray(set); + } + isCommon = false; + includes = cacheHas; + seen = new SetCache; + } + else { + seen = iteratee ? [] : result; + } + outer: + while (++index < length) { + var value = array[index], + computed = iteratee ? iteratee(value) : value; + + value = (comparator || value !== 0) ? value : 0; + if (isCommon && computed === computed) { + var seenIndex = seen.length; + while (seenIndex--) { + if (seen[seenIndex] === computed) { + continue outer; + } + } + if (iteratee) { + seen.push(computed); + } + result.push(value); + } + else if (!includes(seen, computed, comparator)) { + if (seen !== result) { + seen.push(computed); + } + result.push(value); + } + } + return result; + } + + /** + * The base implementation of `_.unset`. + * + * @private + * @param {Object} object The object to modify. + * @param {Array|string} path The property path to unset. + * @returns {boolean} Returns `true` if the property is deleted, else `false`. + */ + function baseUnset(object, path) { + path = castPath(path, object); + object = parent(object, path); + return object == null || delete object[toKey(last(path))]; + } + + /** + * The base implementation of `_.update`. + * + * @private + * @param {Object} object The object to modify. + * @param {Array|string} path The path of the property to update. + * @param {Function} updater The function to produce the updated value. + * @param {Function} [customizer] The function to customize path creation. + * @returns {Object} Returns `object`. + */ + function baseUpdate(object, path, updater, customizer) { + return baseSet(object, path, updater(baseGet(object, path)), customizer); + } + + /** + * The base implementation of methods like `_.dropWhile` and `_.takeWhile` + * without support for iteratee shorthands. + * + * @private + * @param {Array} array The array to query. + * @param {Function} predicate The function invoked per iteration. + * @param {boolean} [isDrop] Specify dropping elements instead of taking them. + * @param {boolean} [fromRight] Specify iterating from right to left. + * @returns {Array} Returns the slice of `array`. + */ + function baseWhile(array, predicate, isDrop, fromRight) { + var length = array.length, + index = fromRight ? length : -1; + + while ((fromRight ? index-- : ++index < length) && + predicate(array[index], index, array)) {} + + return isDrop + ? baseSlice(array, (fromRight ? 0 : index), (fromRight ? index + 1 : length)) + : baseSlice(array, (fromRight ? index + 1 : 0), (fromRight ? length : index)); + } + + /** + * The base implementation of `wrapperValue` which returns the result of + * performing a sequence of actions on the unwrapped `value`, where each + * successive action is supplied the return value of the previous. + * + * @private + * @param {*} value The unwrapped value. + * @param {Array} actions Actions to perform to resolve the unwrapped value. + * @returns {*} Returns the resolved value. + */ + function baseWrapperValue(value, actions) { + var result = value; + if (result instanceof LazyWrapper) { + result = result.value(); + } + return arrayReduce(actions, function(result, action) { + return action.func.apply(action.thisArg, arrayPush([result], action.args)); + }, result); + } + + /** + * The base implementation of methods like `_.xor`, without support for + * iteratee shorthands, that accepts an array of arrays to inspect. + * + * @private + * @param {Array} arrays The arrays to inspect. + * @param {Function} [iteratee] The iteratee invoked per element. + * @param {Function} [comparator] The comparator invoked per element. + * @returns {Array} Returns the new array of values. + */ + function baseXor(arrays, iteratee, comparator) { + var length = arrays.length; + if (length < 2) { + return length ? baseUniq(arrays[0]) : []; + } + var index = -1, + result = Array(length); + + while (++index < length) { + var array = arrays[index], + othIndex = -1; + + while (++othIndex < length) { + if (othIndex != index) { + result[index] = baseDifference(result[index] || array, arrays[othIndex], iteratee, comparator); + } + } + } + return baseUniq(baseFlatten(result, 1), iteratee, comparator); + } + + /** + * This base implementation of `_.zipObject` which assigns values using `assignFunc`. + * + * @private + * @param {Array} props The property identifiers. + * @param {Array} values The property values. + * @param {Function} assignFunc The function to assign values. + * @returns {Object} Returns the new object. + */ + function baseZipObject(props, values, assignFunc) { + var index = -1, + length = props.length, + valsLength = values.length, + result = {}; + + while (++index < length) { + var value = index < valsLength ? values[index] : undefined; + assignFunc(result, props[index], value); + } + return result; + } + + /** + * Casts `value` to an empty array if it's not an array like object. + * + * @private + * @param {*} value The value to inspect. + * @returns {Array|Object} Returns the cast array-like object. + */ + function castArrayLikeObject(value) { + return isArrayLikeObject(value) ? value : []; + } + + /** + * Casts `value` to `identity` if it's not a function. + * + * @private + * @param {*} value The value to inspect. + * @returns {Function} Returns cast function. + */ + function castFunction(value) { + return typeof value == 'function' ? value : identity; + } + + /** + * Casts `value` to a path array if it's not one. + * + * @private + * @param {*} value The value to inspect. + * @param {Object} [object] The object to query keys on. + * @returns {Array} Returns the cast property path array. + */ + function castPath(value, object) { + if (isArray(value)) { + return value; + } + return isKey(value, object) ? [value] : stringToPath(toString(value)); + } + + /** + * A `baseRest` alias which can be replaced with `identity` by module + * replacement plugins. + * + * @private + * @type {Function} + * @param {Function} func The function to apply a rest parameter to. + * @returns {Function} Returns the new function. + */ + var castRest = baseRest; + + /** + * Casts `array` to a slice if it's needed. + * + * @private + * @param {Array} array The array to inspect. + * @param {number} start The start position. + * @param {number} [end=array.length] The end position. + * @returns {Array} Returns the cast slice. + */ + function castSlice(array, start, end) { + var length = array.length; + end = end === undefined ? length : end; + return (!start && end >= length) ? array : baseSlice(array, start, end); + } + + /** + * A simple wrapper around the global [`clearTimeout`](https://mdn.io/clearTimeout). + * + * @private + * @param {number|Object} id The timer id or timeout object of the timer to clear. + */ + var clearTimeout = ctxClearTimeout || function(id) { + return root.clearTimeout(id); + }; + + /** + * Creates a clone of `buffer`. + * + * @private + * @param {Buffer} buffer The buffer to clone. + * @param {boolean} [isDeep] Specify a deep clone. + * @returns {Buffer} Returns the cloned buffer. + */ + function cloneBuffer(buffer, isDeep) { + if (isDeep) { + return buffer.slice(); + } + var length = buffer.length, + result = allocUnsafe ? allocUnsafe(length) : new buffer.constructor(length); + + buffer.copy(result); + return result; + } + + /** + * Creates a clone of `arrayBuffer`. + * + * @private + * @param {ArrayBuffer} arrayBuffer The array buffer to clone. + * @returns {ArrayBuffer} Returns the cloned array buffer. + */ + function cloneArrayBuffer(arrayBuffer) { + var result = new arrayBuffer.constructor(arrayBuffer.byteLength); + new Uint8Array(result).set(new Uint8Array(arrayBuffer)); + return result; + } + + /** + * Creates a clone of `dataView`. + * + * @private + * @param {Object} dataView The data view to clone. + * @param {boolean} [isDeep] Specify a deep clone. + * @returns {Object} Returns the cloned data view. + */ + function cloneDataView(dataView, isDeep) { + var buffer = isDeep ? cloneArrayBuffer(dataView.buffer) : dataView.buffer; + return new dataView.constructor(buffer, dataView.byteOffset, dataView.byteLength); + } + + /** + * Creates a clone of `regexp`. + * + * @private + * @param {Object} regexp The regexp to clone. + * @returns {Object} Returns the cloned regexp. + */ + function cloneRegExp(regexp) { + var result = new regexp.constructor(regexp.source, reFlags.exec(regexp)); + result.lastIndex = regexp.lastIndex; + return result; + } + + /** + * Creates a clone of the `symbol` object. + * + * @private + * @param {Object} symbol The symbol object to clone. + * @returns {Object} Returns the cloned symbol object. + */ + function cloneSymbol(symbol) { + return symbolValueOf ? Object(symbolValueOf.call(symbol)) : {}; + } + + /** + * Creates a clone of `typedArray`. + * + * @private + * @param {Object} typedArray The typed array to clone. + * @param {boolean} [isDeep] Specify a deep clone. + * @returns {Object} Returns the cloned typed array. + */ + function cloneTypedArray(typedArray, isDeep) { + var buffer = isDeep ? cloneArrayBuffer(typedArray.buffer) : typedArray.buffer; + return new typedArray.constructor(buffer, typedArray.byteOffset, typedArray.length); + } + + /** + * Compares values to sort them in ascending order. + * + * @private + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @returns {number} Returns the sort order indicator for `value`. + */ + function compareAscending(value, other) { + if (value !== other) { + var valIsDefined = value !== undefined, + valIsNull = value === null, + valIsReflexive = value === value, + valIsSymbol = isSymbol(value); + + var othIsDefined = other !== undefined, + othIsNull = other === null, + othIsReflexive = other === other, + othIsSymbol = isSymbol(other); + + if ((!othIsNull && !othIsSymbol && !valIsSymbol && value > other) || + (valIsSymbol && othIsDefined && othIsReflexive && !othIsNull && !othIsSymbol) || + (valIsNull && othIsDefined && othIsReflexive) || + (!valIsDefined && othIsReflexive) || + !valIsReflexive) { + return 1; + } + if ((!valIsNull && !valIsSymbol && !othIsSymbol && value < other) || + (othIsSymbol && valIsDefined && valIsReflexive && !valIsNull && !valIsSymbol) || + (othIsNull && valIsDefined && valIsReflexive) || + (!othIsDefined && valIsReflexive) || + !othIsReflexive) { + return -1; + } + } + return 0; + } + + /** + * Used by `_.orderBy` to compare multiple properties of a value to another + * and stable sort them. + * + * If `orders` is unspecified, all values are sorted in ascending order. Otherwise, + * specify an order of "desc" for descending or "asc" for ascending sort order + * of corresponding values. + * + * @private + * @param {Object} object The object to compare. + * @param {Object} other The other object to compare. + * @param {boolean[]|string[]} orders The order to sort by for each property. + * @returns {number} Returns the sort order indicator for `object`. + */ + function compareMultiple(object, other, orders) { + var index = -1, + objCriteria = object.criteria, + othCriteria = other.criteria, + length = objCriteria.length, + ordersLength = orders.length; + + while (++index < length) { + var result = compareAscending(objCriteria[index], othCriteria[index]); + if (result) { + if (index >= ordersLength) { + return result; + } + var order = orders[index]; + return result * (order == 'desc' ? -1 : 1); + } + } + // Fixes an `Array#sort` bug in the JS engine embedded in Adobe applications + // that causes it, under certain circumstances, to provide the same value for + // `object` and `other`. See https://github.com/jashkenas/underscore/pull/1247 + // for more details. + // + // This also ensures a stable sort in V8 and other engines. + // See https://bugs.chromium.org/p/v8/issues/detail?id=90 for more details. + return object.index - other.index; + } + + /** + * Creates an array that is the composition of partially applied arguments, + * placeholders, and provided arguments into a single array of arguments. + * + * @private + * @param {Array} args The provided arguments. + * @param {Array} partials The arguments to prepend to those provided. + * @param {Array} holders The `partials` placeholder indexes. + * @params {boolean} [isCurried] Specify composing for a curried function. + * @returns {Array} Returns the new array of composed arguments. + */ + function composeArgs(args, partials, holders, isCurried) { + var argsIndex = -1, + argsLength = args.length, + holdersLength = holders.length, + leftIndex = -1, + leftLength = partials.length, + rangeLength = nativeMax(argsLength - holdersLength, 0), + result = Array(leftLength + rangeLength), + isUncurried = !isCurried; + + while (++leftIndex < leftLength) { + result[leftIndex] = partials[leftIndex]; + } + while (++argsIndex < holdersLength) { + if (isUncurried || argsIndex < argsLength) { + result[holders[argsIndex]] = args[argsIndex]; + } + } + while (rangeLength--) { + result[leftIndex++] = args[argsIndex++]; + } + return result; + } + + /** + * This function is like `composeArgs` except that the arguments composition + * is tailored for `_.partialRight`. + * + * @private + * @param {Array} args The provided arguments. + * @param {Array} partials The arguments to append to those provided. + * @param {Array} holders The `partials` placeholder indexes. + * @params {boolean} [isCurried] Specify composing for a curried function. + * @returns {Array} Returns the new array of composed arguments. + */ + function composeArgsRight(args, partials, holders, isCurried) { + var argsIndex = -1, + argsLength = args.length, + holdersIndex = -1, + holdersLength = holders.length, + rightIndex = -1, + rightLength = partials.length, + rangeLength = nativeMax(argsLength - holdersLength, 0), + result = Array(rangeLength + rightLength), + isUncurried = !isCurried; + + while (++argsIndex < rangeLength) { + result[argsIndex] = args[argsIndex]; + } + var offset = argsIndex; + while (++rightIndex < rightLength) { + result[offset + rightIndex] = partials[rightIndex]; + } + while (++holdersIndex < holdersLength) { + if (isUncurried || argsIndex < argsLength) { + result[offset + holders[holdersIndex]] = args[argsIndex++]; + } + } + return result; + } + + /** + * Copies the values of `source` to `array`. + * + * @private + * @param {Array} source The array to copy values from. + * @param {Array} [array=[]] The array to copy values to. + * @returns {Array} Returns `array`. + */ + function copyArray(source, array) { + var index = -1, + length = source.length; + + array || (array = Array(length)); + while (++index < length) { + array[index] = source[index]; + } + return array; + } + + /** + * Copies properties of `source` to `object`. + * + * @private + * @param {Object} source The object to copy properties from. + * @param {Array} props The property identifiers to copy. + * @param {Object} [object={}] The object to copy properties to. + * @param {Function} [customizer] The function to customize copied values. + * @returns {Object} Returns `object`. + */ + function copyObject(source, props, object, customizer) { + var isNew = !object; + object || (object = {}); + + var index = -1, + length = props.length; + + while (++index < length) { + var key = props[index]; + + var newValue = customizer + ? customizer(object[key], source[key], key, object, source) + : undefined; + + if (newValue === undefined) { + newValue = source[key]; + } + if (isNew) { + baseAssignValue(object, key, newValue); + } else { + assignValue(object, key, newValue); + } + } + return object; + } + + /** + * Copies own symbols of `source` to `object`. + * + * @private + * @param {Object} source The object to copy symbols from. + * @param {Object} [object={}] The object to copy symbols to. + * @returns {Object} Returns `object`. + */ + function copySymbols(source, object) { + return copyObject(source, getSymbols(source), object); + } + + /** + * Copies own and inherited symbols of `source` to `object`. + * + * @private + * @param {Object} source The object to copy symbols from. + * @param {Object} [object={}] The object to copy symbols to. + * @returns {Object} Returns `object`. + */ + function copySymbolsIn(source, object) { + return copyObject(source, getSymbolsIn(source), object); + } + + /** + * Creates a function like `_.groupBy`. + * + * @private + * @param {Function} setter The function to set accumulator values. + * @param {Function} [initializer] The accumulator object initializer. + * @returns {Function} Returns the new aggregator function. + */ + function createAggregator(setter, initializer) { + return function(collection, iteratee) { + var func = isArray(collection) ? arrayAggregator : baseAggregator, + accumulator = initializer ? initializer() : {}; + + return func(collection, setter, getIteratee(iteratee, 2), accumulator); + }; + } + + /** + * Creates a function like `_.assign`. + * + * @private + * @param {Function} assigner The function to assign values. + * @returns {Function} Returns the new assigner function. + */ + function createAssigner(assigner) { + return baseRest(function(object, sources) { + var index = -1, + length = sources.length, + customizer = length > 1 ? sources[length - 1] : undefined, + guard = length > 2 ? sources[2] : undefined; + + customizer = (assigner.length > 3 && typeof customizer == 'function') + ? (length--, customizer) + : undefined; + + if (guard && isIterateeCall(sources[0], sources[1], guard)) { + customizer = length < 3 ? undefined : customizer; + length = 1; + } + object = Object(object); + while (++index < length) { + var source = sources[index]; + if (source) { + assigner(object, source, index, customizer); + } + } + return object; + }); + } + + /** + * Creates a `baseEach` or `baseEachRight` function. + * + * @private + * @param {Function} eachFunc The function to iterate over a collection. + * @param {boolean} [fromRight] Specify iterating from right to left. + * @returns {Function} Returns the new base function. + */ + function createBaseEach(eachFunc, fromRight) { + return function(collection, iteratee) { + if (collection == null) { + return collection; + } + if (!isArrayLike(collection)) { + return eachFunc(collection, iteratee); + } + var length = collection.length, + index = fromRight ? length : -1, + iterable = Object(collection); + + while ((fromRight ? index-- : ++index < length)) { + if (iteratee(iterable[index], index, iterable) === false) { + break; + } + } + return collection; + }; + } + + /** + * Creates a base function for methods like `_.forIn` and `_.forOwn`. + * + * @private + * @param {boolean} [fromRight] Specify iterating from right to left. + * @returns {Function} Returns the new base function. + */ + function createBaseFor(fromRight) { + return function(object, iteratee, keysFunc) { + var index = -1, + iterable = Object(object), + props = keysFunc(object), + length = props.length; + + while (length--) { + var key = props[fromRight ? length : ++index]; + if (iteratee(iterable[key], key, iterable) === false) { + break; + } + } + return object; + }; + } + + /** + * Creates a function that wraps `func` to invoke it with the optional `this` + * binding of `thisArg`. + * + * @private + * @param {Function} func The function to wrap. + * @param {number} bitmask The bitmask flags. See `createWrap` for more details. + * @param {*} [thisArg] The `this` binding of `func`. + * @returns {Function} Returns the new wrapped function. + */ + function createBind(func, bitmask, thisArg) { + var isBind = bitmask & WRAP_BIND_FLAG, + Ctor = createCtor(func); + + function wrapper() { + var fn = (this && this !== root && this instanceof wrapper) ? Ctor : func; + return fn.apply(isBind ? thisArg : this, arguments); + } + return wrapper; + } + + /** + * Creates a function like `_.lowerFirst`. + * + * @private + * @param {string} methodName The name of the `String` case method to use. + * @returns {Function} Returns the new case function. + */ + function createCaseFirst(methodName) { + return function(string) { + string = toString(string); + + var strSymbols = hasUnicode(string) + ? stringToArray(string) + : undefined; + + var chr = strSymbols + ? strSymbols[0] + : string.charAt(0); + + var trailing = strSymbols + ? castSlice(strSymbols, 1).join('') + : string.slice(1); + + return chr[methodName]() + trailing; + }; + } + + /** + * Creates a function like `_.camelCase`. + * + * @private + * @param {Function} callback The function to combine each word. + * @returns {Function} Returns the new compounder function. + */ + function createCompounder(callback) { + return function(string) { + return arrayReduce(words(deburr(string).replace(reApos, '')), callback, ''); + }; + } + + /** + * Creates a function that produces an instance of `Ctor` regardless of + * whether it was invoked as part of a `new` expression or by `call` or `apply`. + * + * @private + * @param {Function} Ctor The constructor to wrap. + * @returns {Function} Returns the new wrapped function. + */ + function createCtor(Ctor) { + return function() { + // Use a `switch` statement to work with class constructors. See + // http://ecma-international.org/ecma-262/7.0/#sec-ecmascript-function-objects-call-thisargument-argumentslist + // for more details. + var args = arguments; + switch (args.length) { + case 0: return new Ctor; + case 1: return new Ctor(args[0]); + case 2: return new Ctor(args[0], args[1]); + case 3: return new Ctor(args[0], args[1], args[2]); + case 4: return new Ctor(args[0], args[1], args[2], args[3]); + case 5: return new Ctor(args[0], args[1], args[2], args[3], args[4]); + case 6: return new Ctor(args[0], args[1], args[2], args[3], args[4], args[5]); + case 7: return new Ctor(args[0], args[1], args[2], args[3], args[4], args[5], args[6]); + } + var thisBinding = baseCreate(Ctor.prototype), + result = Ctor.apply(thisBinding, args); + + // Mimic the constructor's `return` behavior. + // See https://es5.github.io/#x13.2.2 for more details. + return isObject(result) ? result : thisBinding; + }; + } + + /** + * Creates a function that wraps `func` to enable currying. + * + * @private + * @param {Function} func The function to wrap. + * @param {number} bitmask The bitmask flags. See `createWrap` for more details. + * @param {number} arity The arity of `func`. + * @returns {Function} Returns the new wrapped function. + */ + function createCurry(func, bitmask, arity) { + var Ctor = createCtor(func); + + function wrapper() { + var length = arguments.length, + args = Array(length), + index = length, + placeholder = getHolder(wrapper); + + while (index--) { + args[index] = arguments[index]; + } + var holders = (length < 3 && args[0] !== placeholder && args[length - 1] !== placeholder) + ? [] + : replaceHolders(args, placeholder); + + length -= holders.length; + if (length < arity) { + return createRecurry( + func, bitmask, createHybrid, wrapper.placeholder, undefined, + args, holders, undefined, undefined, arity - length); + } + var fn = (this && this !== root && this instanceof wrapper) ? Ctor : func; + return apply(fn, this, args); + } + return wrapper; + } + + /** + * Creates a `_.find` or `_.findLast` function. + * + * @private + * @param {Function} findIndexFunc The function to find the collection index. + * @returns {Function} Returns the new find function. + */ + function createFind(findIndexFunc) { + return function(collection, predicate, fromIndex) { + var iterable = Object(collection); + if (!isArrayLike(collection)) { + var iteratee = getIteratee(predicate, 3); + collection = keys(collection); + predicate = function(key) { return iteratee(iterable[key], key, iterable); }; + } + var index = findIndexFunc(collection, predicate, fromIndex); + return index > -1 ? iterable[iteratee ? collection[index] : index] : undefined; + }; + } + + /** + * Creates a `_.flow` or `_.flowRight` function. + * + * @private + * @param {boolean} [fromRight] Specify iterating from right to left. + * @returns {Function} Returns the new flow function. + */ + function createFlow(fromRight) { + return flatRest(function(funcs) { + var length = funcs.length, + index = length, + prereq = LodashWrapper.prototype.thru; + + if (fromRight) { + funcs.reverse(); + } + while (index--) { + var func = funcs[index]; + if (typeof func != 'function') { + throw new TypeError(FUNC_ERROR_TEXT); + } + if (prereq && !wrapper && getFuncName(func) == 'wrapper') { + var wrapper = new LodashWrapper([], true); + } + } + index = wrapper ? index : length; + while (++index < length) { + func = funcs[index]; + + var funcName = getFuncName(func), + data = funcName == 'wrapper' ? getData(func) : undefined; + + if (data && isLaziable(data[0]) && + data[1] == (WRAP_ARY_FLAG | WRAP_CURRY_FLAG | WRAP_PARTIAL_FLAG | WRAP_REARG_FLAG) && + !data[4].length && data[9] == 1 + ) { + wrapper = wrapper[getFuncName(data[0])].apply(wrapper, data[3]); + } else { + wrapper = (func.length == 1 && isLaziable(func)) + ? wrapper[funcName]() + : wrapper.thru(func); + } + } + return function() { + var args = arguments, + value = args[0]; + + if (wrapper && args.length == 1 && isArray(value)) { + return wrapper.plant(value).value(); + } + var index = 0, + result = length ? funcs[index].apply(this, args) : value; + + while (++index < length) { + result = funcs[index].call(this, result); + } + return result; + }; + }); + } + + /** + * Creates a function that wraps `func` to invoke it with optional `this` + * binding of `thisArg`, partial application, and currying. + * + * @private + * @param {Function|string} func The function or method name to wrap. + * @param {number} bitmask The bitmask flags. See `createWrap` for more details. + * @param {*} [thisArg] The `this` binding of `func`. + * @param {Array} [partials] The arguments to prepend to those provided to + * the new function. + * @param {Array} [holders] The `partials` placeholder indexes. + * @param {Array} [partialsRight] The arguments to append to those provided + * to the new function. + * @param {Array} [holdersRight] The `partialsRight` placeholder indexes. + * @param {Array} [argPos] The argument positions of the new function. + * @param {number} [ary] The arity cap of `func`. + * @param {number} [arity] The arity of `func`. + * @returns {Function} Returns the new wrapped function. + */ + function createHybrid(func, bitmask, thisArg, partials, holders, partialsRight, holdersRight, argPos, ary, arity) { + var isAry = bitmask & WRAP_ARY_FLAG, + isBind = bitmask & WRAP_BIND_FLAG, + isBindKey = bitmask & WRAP_BIND_KEY_FLAG, + isCurried = bitmask & (WRAP_CURRY_FLAG | WRAP_CURRY_RIGHT_FLAG), + isFlip = bitmask & WRAP_FLIP_FLAG, + Ctor = isBindKey ? undefined : createCtor(func); + + function wrapper() { + var length = arguments.length, + args = Array(length), + index = length; + + while (index--) { + args[index] = arguments[index]; + } + if (isCurried) { + var placeholder = getHolder(wrapper), + holdersCount = countHolders(args, placeholder); + } + if (partials) { + args = composeArgs(args, partials, holders, isCurried); + } + if (partialsRight) { + args = composeArgsRight(args, partialsRight, holdersRight, isCurried); + } + length -= holdersCount; + if (isCurried && length < arity) { + var newHolders = replaceHolders(args, placeholder); + return createRecurry( + func, bitmask, createHybrid, wrapper.placeholder, thisArg, + args, newHolders, argPos, ary, arity - length + ); + } + var thisBinding = isBind ? thisArg : this, + fn = isBindKey ? thisBinding[func] : func; + + length = args.length; + if (argPos) { + args = reorder(args, argPos); + } else if (isFlip && length > 1) { + args.reverse(); + } + if (isAry && ary < length) { + args.length = ary; + } + if (this && this !== root && this instanceof wrapper) { + fn = Ctor || createCtor(fn); + } + return fn.apply(thisBinding, args); + } + return wrapper; + } + + /** + * Creates a function like `_.invertBy`. + * + * @private + * @param {Function} setter The function to set accumulator values. + * @param {Function} toIteratee The function to resolve iteratees. + * @returns {Function} Returns the new inverter function. + */ + function createInverter(setter, toIteratee) { + return function(object, iteratee) { + return baseInverter(object, setter, toIteratee(iteratee), {}); + }; + } + + /** + * Creates a function that performs a mathematical operation on two values. + * + * @private + * @param {Function} operator The function to perform the operation. + * @param {number} [defaultValue] The value used for `undefined` arguments. + * @returns {Function} Returns the new mathematical operation function. + */ + function createMathOperation(operator, defaultValue) { + return function(value, other) { + var result; + if (value === undefined && other === undefined) { + return defaultValue; + } + if (value !== undefined) { + result = value; + } + if (other !== undefined) { + if (result === undefined) { + return other; + } + if (typeof value == 'string' || typeof other == 'string') { + value = baseToString(value); + other = baseToString(other); + } else { + value = baseToNumber(value); + other = baseToNumber(other); + } + result = operator(value, other); + } + return result; + }; + } + + /** + * Creates a function like `_.over`. + * + * @private + * @param {Function} arrayFunc The function to iterate over iteratees. + * @returns {Function} Returns the new over function. + */ + function createOver(arrayFunc) { + return flatRest(function(iteratees) { + iteratees = arrayMap(iteratees, baseUnary(getIteratee())); + return baseRest(function(args) { + var thisArg = this; + return arrayFunc(iteratees, function(iteratee) { + return apply(iteratee, thisArg, args); + }); + }); + }); + } + + /** + * Creates the padding for `string` based on `length`. The `chars` string + * is truncated if the number of characters exceeds `length`. + * + * @private + * @param {number} length The padding length. + * @param {string} [chars=' '] The string used as padding. + * @returns {string} Returns the padding for `string`. + */ + function createPadding(length, chars) { + chars = chars === undefined ? ' ' : baseToString(chars); + + var charsLength = chars.length; + if (charsLength < 2) { + return charsLength ? baseRepeat(chars, length) : chars; + } + var result = baseRepeat(chars, nativeCeil(length / stringSize(chars))); + return hasUnicode(chars) + ? castSlice(stringToArray(result), 0, length).join('') + : result.slice(0, length); + } + + /** + * Creates a function that wraps `func` to invoke it with the `this` binding + * of `thisArg` and `partials` prepended to the arguments it receives. + * + * @private + * @param {Function} func The function to wrap. + * @param {number} bitmask The bitmask flags. See `createWrap` for more details. + * @param {*} thisArg The `this` binding of `func`. + * @param {Array} partials The arguments to prepend to those provided to + * the new function. + * @returns {Function} Returns the new wrapped function. + */ + function createPartial(func, bitmask, thisArg, partials) { + var isBind = bitmask & WRAP_BIND_FLAG, + Ctor = createCtor(func); + + function wrapper() { + var argsIndex = -1, + argsLength = arguments.length, + leftIndex = -1, + leftLength = partials.length, + args = Array(leftLength + argsLength), + fn = (this && this !== root && this instanceof wrapper) ? Ctor : func; + + while (++leftIndex < leftLength) { + args[leftIndex] = partials[leftIndex]; + } + while (argsLength--) { + args[leftIndex++] = arguments[++argsIndex]; + } + return apply(fn, isBind ? thisArg : this, args); + } + return wrapper; + } + + /** + * Creates a `_.range` or `_.rangeRight` function. + * + * @private + * @param {boolean} [fromRight] Specify iterating from right to left. + * @returns {Function} Returns the new range function. + */ + function createRange(fromRight) { + return function(start, end, step) { + if (step && typeof step != 'number' && isIterateeCall(start, end, step)) { + end = step = undefined; + } + // Ensure the sign of `-0` is preserved. + start = toFinite(start); + if (end === undefined) { + end = start; + start = 0; + } else { + end = toFinite(end); + } + step = step === undefined ? (start < end ? 1 : -1) : toFinite(step); + return baseRange(start, end, step, fromRight); + }; + } + + /** + * Creates a function that performs a relational operation on two values. + * + * @private + * @param {Function} operator The function to perform the operation. + * @returns {Function} Returns the new relational operation function. + */ + function createRelationalOperation(operator) { + return function(value, other) { + if (!(typeof value == 'string' && typeof other == 'string')) { + value = toNumber(value); + other = toNumber(other); + } + return operator(value, other); + }; + } + + /** + * Creates a function that wraps `func` to continue currying. + * + * @private + * @param {Function} func The function to wrap. + * @param {number} bitmask The bitmask flags. See `createWrap` for more details. + * @param {Function} wrapFunc The function to create the `func` wrapper. + * @param {*} placeholder The placeholder value. + * @param {*} [thisArg] The `this` binding of `func`. + * @param {Array} [partials] The arguments to prepend to those provided to + * the new function. + * @param {Array} [holders] The `partials` placeholder indexes. + * @param {Array} [argPos] The argument positions of the new function. + * @param {number} [ary] The arity cap of `func`. + * @param {number} [arity] The arity of `func`. + * @returns {Function} Returns the new wrapped function. + */ + function createRecurry(func, bitmask, wrapFunc, placeholder, thisArg, partials, holders, argPos, ary, arity) { + var isCurry = bitmask & WRAP_CURRY_FLAG, + newHolders = isCurry ? holders : undefined, + newHoldersRight = isCurry ? undefined : holders, + newPartials = isCurry ? partials : undefined, + newPartialsRight = isCurry ? undefined : partials; + + bitmask |= (isCurry ? WRAP_PARTIAL_FLAG : WRAP_PARTIAL_RIGHT_FLAG); + bitmask &= ~(isCurry ? WRAP_PARTIAL_RIGHT_FLAG : WRAP_PARTIAL_FLAG); + + if (!(bitmask & WRAP_CURRY_BOUND_FLAG)) { + bitmask &= ~(WRAP_BIND_FLAG | WRAP_BIND_KEY_FLAG); + } + var newData = [ + func, bitmask, thisArg, newPartials, newHolders, newPartialsRight, + newHoldersRight, argPos, ary, arity + ]; + + var result = wrapFunc.apply(undefined, newData); + if (isLaziable(func)) { + setData(result, newData); + } + result.placeholder = placeholder; + return setWrapToString(result, func, bitmask); + } + + /** + * Creates a function like `_.round`. + * + * @private + * @param {string} methodName The name of the `Math` method to use when rounding. + * @returns {Function} Returns the new round function. + */ + function createRound(methodName) { + var func = Math[methodName]; + return function(number, precision) { + number = toNumber(number); + precision = precision == null ? 0 : nativeMin(toInteger(precision), 292); + if (precision && nativeIsFinite(number)) { + // Shift with exponential notation to avoid floating-point issues. + // See [MDN](https://mdn.io/round#Examples) for more details. + var pair = (toString(number) + 'e').split('e'), + value = func(pair[0] + 'e' + (+pair[1] + precision)); + + pair = (toString(value) + 'e').split('e'); + return +(pair[0] + 'e' + (+pair[1] - precision)); + } + return func(number); + }; + } + + /** + * Creates a set object of `values`. + * + * @private + * @param {Array} values The values to add to the set. + * @returns {Object} Returns the new set. + */ + var createSet = !(Set && (1 / setToArray(new Set([,-0]))[1]) == INFINITY) ? noop : function(values) { + return new Set(values); + }; + + /** + * Creates a `_.toPairs` or `_.toPairsIn` function. + * + * @private + * @param {Function} keysFunc The function to get the keys of a given object. + * @returns {Function} Returns the new pairs function. + */ + function createToPairs(keysFunc) { + return function(object) { + var tag = getTag(object); + if (tag == mapTag) { + return mapToArray(object); + } + if (tag == setTag) { + return setToPairs(object); + } + return baseToPairs(object, keysFunc(object)); + }; + } + + /** + * Creates a function that either curries or invokes `func` with optional + * `this` binding and partially applied arguments. + * + * @private + * @param {Function|string} func The function or method name to wrap. + * @param {number} bitmask The bitmask flags. + * 1 - `_.bind` + * 2 - `_.bindKey` + * 4 - `_.curry` or `_.curryRight` of a bound function + * 8 - `_.curry` + * 16 - `_.curryRight` + * 32 - `_.partial` + * 64 - `_.partialRight` + * 128 - `_.rearg` + * 256 - `_.ary` + * 512 - `_.flip` + * @param {*} [thisArg] The `this` binding of `func`. + * @param {Array} [partials] The arguments to be partially applied. + * @param {Array} [holders] The `partials` placeholder indexes. + * @param {Array} [argPos] The argument positions of the new function. + * @param {number} [ary] The arity cap of `func`. + * @param {number} [arity] The arity of `func`. + * @returns {Function} Returns the new wrapped function. + */ + function createWrap(func, bitmask, thisArg, partials, holders, argPos, ary, arity) { + var isBindKey = bitmask & WRAP_BIND_KEY_FLAG; + if (!isBindKey && typeof func != 'function') { + throw new TypeError(FUNC_ERROR_TEXT); + } + var length = partials ? partials.length : 0; + if (!length) { + bitmask &= ~(WRAP_PARTIAL_FLAG | WRAP_PARTIAL_RIGHT_FLAG); + partials = holders = undefined; + } + ary = ary === undefined ? ary : nativeMax(toInteger(ary), 0); + arity = arity === undefined ? arity : toInteger(arity); + length -= holders ? holders.length : 0; + + if (bitmask & WRAP_PARTIAL_RIGHT_FLAG) { + var partialsRight = partials, + holdersRight = holders; + + partials = holders = undefined; + } + var data = isBindKey ? undefined : getData(func); + + var newData = [ + func, bitmask, thisArg, partials, holders, partialsRight, holdersRight, + argPos, ary, arity + ]; + + if (data) { + mergeData(newData, data); + } + func = newData[0]; + bitmask = newData[1]; + thisArg = newData[2]; + partials = newData[3]; + holders = newData[4]; + arity = newData[9] = newData[9] === undefined + ? (isBindKey ? 0 : func.length) + : nativeMax(newData[9] - length, 0); + + if (!arity && bitmask & (WRAP_CURRY_FLAG | WRAP_CURRY_RIGHT_FLAG)) { + bitmask &= ~(WRAP_CURRY_FLAG | WRAP_CURRY_RIGHT_FLAG); + } + if (!bitmask || bitmask == WRAP_BIND_FLAG) { + var result = createBind(func, bitmask, thisArg); + } else if (bitmask == WRAP_CURRY_FLAG || bitmask == WRAP_CURRY_RIGHT_FLAG) { + result = createCurry(func, bitmask, arity); + } else if ((bitmask == WRAP_PARTIAL_FLAG || bitmask == (WRAP_BIND_FLAG | WRAP_PARTIAL_FLAG)) && !holders.length) { + result = createPartial(func, bitmask, thisArg, partials); + } else { + result = createHybrid.apply(undefined, newData); + } + var setter = data ? baseSetData : setData; + return setWrapToString(setter(result, newData), func, bitmask); + } + + /** + * Used by `_.defaults` to customize its `_.assignIn` use to assign properties + * of source objects to the destination object for all destination properties + * that resolve to `undefined`. + * + * @private + * @param {*} objValue The destination value. + * @param {*} srcValue The source value. + * @param {string} key The key of the property to assign. + * @param {Object} object The parent object of `objValue`. + * @returns {*} Returns the value to assign. + */ + function customDefaultsAssignIn(objValue, srcValue, key, object) { + if (objValue === undefined || + (eq(objValue, objectProto[key]) && !hasOwnProperty.call(object, key))) { + return srcValue; + } + return objValue; + } + + /** + * Used by `_.defaultsDeep` to customize its `_.merge` use to merge source + * objects into destination objects that are passed thru. + * + * @private + * @param {*} objValue The destination value. + * @param {*} srcValue The source value. + * @param {string} key The key of the property to merge. + * @param {Object} object The parent object of `objValue`. + * @param {Object} source The parent object of `srcValue`. + * @param {Object} [stack] Tracks traversed source values and their merged + * counterparts. + * @returns {*} Returns the value to assign. + */ + function customDefaultsMerge(objValue, srcValue, key, object, source, stack) { + if (isObject(objValue) && isObject(srcValue)) { + // Recursively merge objects and arrays (susceptible to call stack limits). + stack.set(srcValue, objValue); + baseMerge(objValue, srcValue, undefined, customDefaultsMerge, stack); + stack['delete'](srcValue); + } + return objValue; + } + + /** + * Used by `_.omit` to customize its `_.cloneDeep` use to only clone plain + * objects. + * + * @private + * @param {*} value The value to inspect. + * @param {string} key The key of the property to inspect. + * @returns {*} Returns the uncloned value or `undefined` to defer cloning to `_.cloneDeep`. + */ + function customOmitClone(value) { + return isPlainObject(value) ? undefined : value; + } + + /** + * A specialized version of `baseIsEqualDeep` for arrays with support for + * partial deep comparisons. + * + * @private + * @param {Array} array The array to compare. + * @param {Array} other The other array to compare. + * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details. + * @param {Function} customizer The function to customize comparisons. + * @param {Function} equalFunc The function to determine equivalents of values. + * @param {Object} stack Tracks traversed `array` and `other` objects. + * @returns {boolean} Returns `true` if the arrays are equivalent, else `false`. + */ + function equalArrays(array, other, bitmask, customizer, equalFunc, stack) { + var isPartial = bitmask & COMPARE_PARTIAL_FLAG, + arrLength = array.length, + othLength = other.length; + + if (arrLength != othLength && !(isPartial && othLength > arrLength)) { + return false; + } + // Check that cyclic values are equal. + var arrStacked = stack.get(array); + var othStacked = stack.get(other); + if (arrStacked && othStacked) { + return arrStacked == other && othStacked == array; + } + var index = -1, + result = true, + seen = (bitmask & COMPARE_UNORDERED_FLAG) ? new SetCache : undefined; + + stack.set(array, other); + stack.set(other, array); + + // Ignore non-index properties. + while (++index < arrLength) { + var arrValue = array[index], + othValue = other[index]; + + if (customizer) { + var compared = isPartial + ? customizer(othValue, arrValue, index, other, array, stack) + : customizer(arrValue, othValue, index, array, other, stack); + } + if (compared !== undefined) { + if (compared) { + continue; + } + result = false; + break; + } + // Recursively compare arrays (susceptible to call stack limits). + if (seen) { + if (!arraySome(other, function(othValue, othIndex) { + if (!cacheHas(seen, othIndex) && + (arrValue === othValue || equalFunc(arrValue, othValue, bitmask, customizer, stack))) { + return seen.push(othIndex); + } + })) { + result = false; + break; + } + } else if (!( + arrValue === othValue || + equalFunc(arrValue, othValue, bitmask, customizer, stack) + )) { + result = false; + break; + } + } + stack['delete'](array); + stack['delete'](other); + return result; + } + + /** + * A specialized version of `baseIsEqualDeep` for comparing objects of + * the same `toStringTag`. + * + * **Note:** This function only supports comparing values with tags of + * `Boolean`, `Date`, `Error`, `Number`, `RegExp`, or `String`. + * + * @private + * @param {Object} object The object to compare. + * @param {Object} other The other object to compare. + * @param {string} tag The `toStringTag` of the objects to compare. + * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details. + * @param {Function} customizer The function to customize comparisons. + * @param {Function} equalFunc The function to determine equivalents of values. + * @param {Object} stack Tracks traversed `object` and `other` objects. + * @returns {boolean} Returns `true` if the objects are equivalent, else `false`. + */ + function equalByTag(object, other, tag, bitmask, customizer, equalFunc, stack) { + switch (tag) { + case dataViewTag: + if ((object.byteLength != other.byteLength) || + (object.byteOffset != other.byteOffset)) { + return false; + } + object = object.buffer; + other = other.buffer; + + case arrayBufferTag: + if ((object.byteLength != other.byteLength) || + !equalFunc(new Uint8Array(object), new Uint8Array(other))) { + return false; + } + return true; + + case boolTag: + case dateTag: + case numberTag: + // Coerce booleans to `1` or `0` and dates to milliseconds. + // Invalid dates are coerced to `NaN`. + return eq(+object, +other); + + case errorTag: + return object.name == other.name && object.message == other.message; + + case regexpTag: + case stringTag: + // Coerce regexes to strings and treat strings, primitives and objects, + // as equal. See http://www.ecma-international.org/ecma-262/7.0/#sec-regexp.prototype.tostring + // for more details. + return object == (other + ''); + + case mapTag: + var convert = mapToArray; + + case setTag: + var isPartial = bitmask & COMPARE_PARTIAL_FLAG; + convert || (convert = setToArray); + + if (object.size != other.size && !isPartial) { + return false; + } + // Assume cyclic values are equal. + var stacked = stack.get(object); + if (stacked) { + return stacked == other; + } + bitmask |= COMPARE_UNORDERED_FLAG; + + // Recursively compare objects (susceptible to call stack limits). + stack.set(object, other); + var result = equalArrays(convert(object), convert(other), bitmask, customizer, equalFunc, stack); + stack['delete'](object); + return result; + + case symbolTag: + if (symbolValueOf) { + return symbolValueOf.call(object) == symbolValueOf.call(other); + } + } + return false; + } + + /** + * A specialized version of `baseIsEqualDeep` for objects with support for + * partial deep comparisons. + * + * @private + * @param {Object} object The object to compare. + * @param {Object} other The other object to compare. + * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details. + * @param {Function} customizer The function to customize comparisons. + * @param {Function} equalFunc The function to determine equivalents of values. + * @param {Object} stack Tracks traversed `object` and `other` objects. + * @returns {boolean} Returns `true` if the objects are equivalent, else `false`. + */ + function equalObjects(object, other, bitmask, customizer, equalFunc, stack) { + var isPartial = bitmask & COMPARE_PARTIAL_FLAG, + objProps = getAllKeys(object), + objLength = objProps.length, + othProps = getAllKeys(other), + othLength = othProps.length; + + if (objLength != othLength && !isPartial) { + return false; + } + var index = objLength; + while (index--) { + var key = objProps[index]; + if (!(isPartial ? key in other : hasOwnProperty.call(other, key))) { + return false; + } + } + // Check that cyclic values are equal. + var objStacked = stack.get(object); + var othStacked = stack.get(other); + if (objStacked && othStacked) { + return objStacked == other && othStacked == object; + } + var result = true; + stack.set(object, other); + stack.set(other, object); + + var skipCtor = isPartial; + while (++index < objLength) { + key = objProps[index]; + var objValue = object[key], + othValue = other[key]; + + if (customizer) { + var compared = isPartial + ? customizer(othValue, objValue, key, other, object, stack) + : customizer(objValue, othValue, key, object, other, stack); + } + // Recursively compare objects (susceptible to call stack limits). + if (!(compared === undefined + ? (objValue === othValue || equalFunc(objValue, othValue, bitmask, customizer, stack)) + : compared + )) { + result = false; + break; + } + skipCtor || (skipCtor = key == 'constructor'); + } + if (result && !skipCtor) { + var objCtor = object.constructor, + othCtor = other.constructor; + + // Non `Object` object instances with different constructors are not equal. + if (objCtor != othCtor && + ('constructor' in object && 'constructor' in other) && + !(typeof objCtor == 'function' && objCtor instanceof objCtor && + typeof othCtor == 'function' && othCtor instanceof othCtor)) { + result = false; + } + } + stack['delete'](object); + stack['delete'](other); + return result; + } + + /** + * A specialized version of `baseRest` which flattens the rest array. + * + * @private + * @param {Function} func The function to apply a rest parameter to. + * @returns {Function} Returns the new function. + */ + function flatRest(func) { + return setToString(overRest(func, undefined, flatten), func + ''); + } + + /** + * Creates an array of own enumerable property names and symbols of `object`. + * + * @private + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property names and symbols. + */ + function getAllKeys(object) { + return baseGetAllKeys(object, keys, getSymbols); + } + + /** + * Creates an array of own and inherited enumerable property names and + * symbols of `object`. + * + * @private + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property names and symbols. + */ + function getAllKeysIn(object) { + return baseGetAllKeys(object, keysIn, getSymbolsIn); + } + + /** + * Gets metadata for `func`. + * + * @private + * @param {Function} func The function to query. + * @returns {*} Returns the metadata for `func`. + */ + var getData = !metaMap ? noop : function(func) { + return metaMap.get(func); + }; + + /** + * Gets the name of `func`. + * + * @private + * @param {Function} func The function to query. + * @returns {string} Returns the function name. + */ + function getFuncName(func) { + var result = (func.name + ''), + array = realNames[result], + length = hasOwnProperty.call(realNames, result) ? array.length : 0; + + while (length--) { + var data = array[length], + otherFunc = data.func; + if (otherFunc == null || otherFunc == func) { + return data.name; + } + } + return result; + } + + /** + * Gets the argument placeholder value for `func`. + * + * @private + * @param {Function} func The function to inspect. + * @returns {*} Returns the placeholder value. + */ + function getHolder(func) { + var object = hasOwnProperty.call(lodash, 'placeholder') ? lodash : func; + return object.placeholder; + } + + /** + * Gets the appropriate "iteratee" function. If `_.iteratee` is customized, + * this function returns the custom method, otherwise it returns `baseIteratee`. + * If arguments are provided, the chosen function is invoked with them and + * its result is returned. + * + * @private + * @param {*} [value] The value to convert to an iteratee. + * @param {number} [arity] The arity of the created iteratee. + * @returns {Function} Returns the chosen function or its result. + */ + function getIteratee() { + var result = lodash.iteratee || iteratee; + result = result === iteratee ? baseIteratee : result; + return arguments.length ? result(arguments[0], arguments[1]) : result; + } + + /** + * Gets the data for `map`. + * + * @private + * @param {Object} map The map to query. + * @param {string} key The reference key. + * @returns {*} Returns the map data. + */ + function getMapData(map, key) { + var data = map.__data__; + return isKeyable(key) + ? data[typeof key == 'string' ? 'string' : 'hash'] + : data.map; + } + + /** + * Gets the property names, values, and compare flags of `object`. + * + * @private + * @param {Object} object The object to query. + * @returns {Array} Returns the match data of `object`. + */ + function getMatchData(object) { + var result = keys(object), + length = result.length; + + while (length--) { + var key = result[length], + value = object[key]; + + result[length] = [key, value, isStrictComparable(value)]; + } + return result; + } + + /** + * Gets the native function at `key` of `object`. + * + * @private + * @param {Object} object The object to query. + * @param {string} key The key of the method to get. + * @returns {*} Returns the function if it's native, else `undefined`. + */ + function getNative(object, key) { + var value = getValue(object, key); + return baseIsNative(value) ? value : undefined; + } + + /** + * A specialized version of `baseGetTag` which ignores `Symbol.toStringTag` values. + * + * @private + * @param {*} value The value to query. + * @returns {string} Returns the raw `toStringTag`. + */ + function getRawTag(value) { + var isOwn = hasOwnProperty.call(value, symToStringTag), + tag = value[symToStringTag]; + + try { + value[symToStringTag] = undefined; + var unmasked = true; + } catch (e) {} + + var result = nativeObjectToString.call(value); + if (unmasked) { + if (isOwn) { + value[symToStringTag] = tag; + } else { + delete value[symToStringTag]; + } + } + return result; + } + + /** + * Creates an array of the own enumerable symbols of `object`. + * + * @private + * @param {Object} object The object to query. + * @returns {Array} Returns the array of symbols. + */ + var getSymbols = !nativeGetSymbols ? stubArray : function(object) { + if (object == null) { + return []; + } + object = Object(object); + return arrayFilter(nativeGetSymbols(object), function(symbol) { + return propertyIsEnumerable.call(object, symbol); + }); + }; + + /** + * Creates an array of the own and inherited enumerable symbols of `object`. + * + * @private + * @param {Object} object The object to query. + * @returns {Array} Returns the array of symbols. + */ + var getSymbolsIn = !nativeGetSymbols ? stubArray : function(object) { + var result = []; + while (object) { + arrayPush(result, getSymbols(object)); + object = getPrototype(object); + } + return result; + }; + + /** + * Gets the `toStringTag` of `value`. + * + * @private + * @param {*} value The value to query. + * @returns {string} Returns the `toStringTag`. + */ + var getTag = baseGetTag; + + // Fallback for data views, maps, sets, and weak maps in IE 11 and promises in Node.js < 6. + if ((DataView && getTag(new DataView(new ArrayBuffer(1))) != dataViewTag) || + (Map && getTag(new Map) != mapTag) || + (Promise && getTag(Promise.resolve()) != promiseTag) || + (Set && getTag(new Set) != setTag) || + (WeakMap && getTag(new WeakMap) != weakMapTag)) { + getTag = function(value) { + var result = baseGetTag(value), + Ctor = result == objectTag ? value.constructor : undefined, + ctorString = Ctor ? toSource(Ctor) : ''; + + if (ctorString) { + switch (ctorString) { + case dataViewCtorString: return dataViewTag; + case mapCtorString: return mapTag; + case promiseCtorString: return promiseTag; + case setCtorString: return setTag; + case weakMapCtorString: return weakMapTag; + } + } + return result; + }; + } + + /** + * Gets the view, applying any `transforms` to the `start` and `end` positions. + * + * @private + * @param {number} start The start of the view. + * @param {number} end The end of the view. + * @param {Array} transforms The transformations to apply to the view. + * @returns {Object} Returns an object containing the `start` and `end` + * positions of the view. + */ + function getView(start, end, transforms) { + var index = -1, + length = transforms.length; + + while (++index < length) { + var data = transforms[index], + size = data.size; + + switch (data.type) { + case 'drop': start += size; break; + case 'dropRight': end -= size; break; + case 'take': end = nativeMin(end, start + size); break; + case 'takeRight': start = nativeMax(start, end - size); break; + } + } + return { 'start': start, 'end': end }; + } + + /** + * Extracts wrapper details from the `source` body comment. + * + * @private + * @param {string} source The source to inspect. + * @returns {Array} Returns the wrapper details. + */ + function getWrapDetails(source) { + var match = source.match(reWrapDetails); + return match ? match[1].split(reSplitDetails) : []; + } + + /** + * Checks if `path` exists on `object`. + * + * @private + * @param {Object} object The object to query. + * @param {Array|string} path The path to check. + * @param {Function} hasFunc The function to check properties. + * @returns {boolean} Returns `true` if `path` exists, else `false`. + */ + function hasPath(object, path, hasFunc) { + path = castPath(path, object); + + var index = -1, + length = path.length, + result = false; + + while (++index < length) { + var key = toKey(path[index]); + if (!(result = object != null && hasFunc(object, key))) { + break; + } + object = object[key]; + } + if (result || ++index != length) { + return result; + } + length = object == null ? 0 : object.length; + return !!length && isLength(length) && isIndex(key, length) && + (isArray(object) || isArguments(object)); + } + + /** + * Initializes an array clone. + * + * @private + * @param {Array} array The array to clone. + * @returns {Array} Returns the initialized clone. + */ + function initCloneArray(array) { + var length = array.length, + result = new array.constructor(length); + + // Add properties assigned by `RegExp#exec`. + if (length && typeof array[0] == 'string' && hasOwnProperty.call(array, 'index')) { + result.index = array.index; + result.input = array.input; + } + return result; + } + + /** + * Initializes an object clone. + * + * @private + * @param {Object} object The object to clone. + * @returns {Object} Returns the initialized clone. + */ + function initCloneObject(object) { + return (typeof object.constructor == 'function' && !isPrototype(object)) + ? baseCreate(getPrototype(object)) + : {}; + } + + /** + * Initializes an object clone based on its `toStringTag`. + * + * **Note:** This function only supports cloning values with tags of + * `Boolean`, `Date`, `Error`, `Map`, `Number`, `RegExp`, `Set`, or `String`. + * + * @private + * @param {Object} object The object to clone. + * @param {string} tag The `toStringTag` of the object to clone. + * @param {boolean} [isDeep] Specify a deep clone. + * @returns {Object} Returns the initialized clone. + */ + function initCloneByTag(object, tag, isDeep) { + var Ctor = object.constructor; + switch (tag) { + case arrayBufferTag: + return cloneArrayBuffer(object); + + case boolTag: + case dateTag: + return new Ctor(+object); + + case dataViewTag: + return cloneDataView(object, isDeep); + + case float32Tag: case float64Tag: + case int8Tag: case int16Tag: case int32Tag: + case uint8Tag: case uint8ClampedTag: case uint16Tag: case uint32Tag: + return cloneTypedArray(object, isDeep); + + case mapTag: + return new Ctor; + + case numberTag: + case stringTag: + return new Ctor(object); + + case regexpTag: + return cloneRegExp(object); + + case setTag: + return new Ctor; + + case symbolTag: + return cloneSymbol(object); + } + } + + /** + * Inserts wrapper `details` in a comment at the top of the `source` body. + * + * @private + * @param {string} source The source to modify. + * @returns {Array} details The details to insert. + * @returns {string} Returns the modified source. + */ + function insertWrapDetails(source, details) { + var length = details.length; + if (!length) { + return source; + } + var lastIndex = length - 1; + details[lastIndex] = (length > 1 ? '& ' : '') + details[lastIndex]; + details = details.join(length > 2 ? ', ' : ' '); + return source.replace(reWrapComment, '{\n/* [wrapped with ' + details + '] */\n'); + } + + /** + * Checks if `value` is a flattenable `arguments` object or array. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is flattenable, else `false`. + */ + function isFlattenable(value) { + return isArray(value) || isArguments(value) || + !!(spreadableSymbol && value && value[spreadableSymbol]); + } + + /** + * Checks if `value` is a valid array-like index. + * + * @private + * @param {*} value The value to check. + * @param {number} [length=MAX_SAFE_INTEGER] The upper bounds of a valid index. + * @returns {boolean} Returns `true` if `value` is a valid index, else `false`. + */ + function isIndex(value, length) { + var type = typeof value; + length = length == null ? MAX_SAFE_INTEGER : length; + + return !!length && + (type == 'number' || + (type != 'symbol' && reIsUint.test(value))) && + (value > -1 && value % 1 == 0 && value < length); + } + + /** + * Checks if the given arguments are from an iteratee call. + * + * @private + * @param {*} value The potential iteratee value argument. + * @param {*} index The potential iteratee index or key argument. + * @param {*} object The potential iteratee object argument. + * @returns {boolean} Returns `true` if the arguments are from an iteratee call, + * else `false`. + */ + function isIterateeCall(value, index, object) { + if (!isObject(object)) { + return false; + } + var type = typeof index; + if (type == 'number' + ? (isArrayLike(object) && isIndex(index, object.length)) + : (type == 'string' && index in object) + ) { + return eq(object[index], value); + } + return false; + } + + /** + * Checks if `value` is a property name and not a property path. + * + * @private + * @param {*} value The value to check. + * @param {Object} [object] The object to query keys on. + * @returns {boolean} Returns `true` if `value` is a property name, else `false`. + */ + function isKey(value, object) { + if (isArray(value)) { + return false; + } + var type = typeof value; + if (type == 'number' || type == 'symbol' || type == 'boolean' || + value == null || isSymbol(value)) { + return true; + } + return reIsPlainProp.test(value) || !reIsDeepProp.test(value) || + (object != null && value in Object(object)); + } + + /** + * Checks if `value` is suitable for use as unique object key. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is suitable, else `false`. + */ + function isKeyable(value) { + var type = typeof value; + return (type == 'string' || type == 'number' || type == 'symbol' || type == 'boolean') + ? (value !== '__proto__') + : (value === null); + } + + /** + * Checks if `func` has a lazy counterpart. + * + * @private + * @param {Function} func The function to check. + * @returns {boolean} Returns `true` if `func` has a lazy counterpart, + * else `false`. + */ + function isLaziable(func) { + var funcName = getFuncName(func), + other = lodash[funcName]; + + if (typeof other != 'function' || !(funcName in LazyWrapper.prototype)) { + return false; + } + if (func === other) { + return true; + } + var data = getData(other); + return !!data && func === data[0]; + } + + /** + * Checks if `func` has its source masked. + * + * @private + * @param {Function} func The function to check. + * @returns {boolean} Returns `true` if `func` is masked, else `false`. + */ + function isMasked(func) { + return !!maskSrcKey && (maskSrcKey in func); + } + + /** + * Checks if `func` is capable of being masked. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `func` is maskable, else `false`. + */ + var isMaskable = coreJsData ? isFunction : stubFalse; + + /** + * Checks if `value` is likely a prototype object. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a prototype, else `false`. + */ + function isPrototype(value) { + var Ctor = value && value.constructor, + proto = (typeof Ctor == 'function' && Ctor.prototype) || objectProto; + + return value === proto; + } + + /** + * Checks if `value` is suitable for strict equality comparisons, i.e. `===`. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` if suitable for strict + * equality comparisons, else `false`. + */ + function isStrictComparable(value) { + return value === value && !isObject(value); + } + + /** + * A specialized version of `matchesProperty` for source values suitable + * for strict equality comparisons, i.e. `===`. + * + * @private + * @param {string} key The key of the property to get. + * @param {*} srcValue The value to match. + * @returns {Function} Returns the new spec function. + */ + function matchesStrictComparable(key, srcValue) { + return function(object) { + if (object == null) { + return false; + } + return object[key] === srcValue && + (srcValue !== undefined || (key in Object(object))); + }; + } + + /** + * A specialized version of `_.memoize` which clears the memoized function's + * cache when it exceeds `MAX_MEMOIZE_SIZE`. + * + * @private + * @param {Function} func The function to have its output memoized. + * @returns {Function} Returns the new memoized function. + */ + function memoizeCapped(func) { + var result = memoize(func, function(key) { + if (cache.size === MAX_MEMOIZE_SIZE) { + cache.clear(); + } + return key; + }); + + var cache = result.cache; + return result; + } + + /** + * Merges the function metadata of `source` into `data`. + * + * Merging metadata reduces the number of wrappers used to invoke a function. + * This is possible because methods like `_.bind`, `_.curry`, and `_.partial` + * may be applied regardless of execution order. Methods like `_.ary` and + * `_.rearg` modify function arguments, making the order in which they are + * executed important, preventing the merging of metadata. However, we make + * an exception for a safe combined case where curried functions have `_.ary` + * and or `_.rearg` applied. + * + * @private + * @param {Array} data The destination metadata. + * @param {Array} source The source metadata. + * @returns {Array} Returns `data`. + */ + function mergeData(data, source) { + var bitmask = data[1], + srcBitmask = source[1], + newBitmask = bitmask | srcBitmask, + isCommon = newBitmask < (WRAP_BIND_FLAG | WRAP_BIND_KEY_FLAG | WRAP_ARY_FLAG); + + var isCombo = + ((srcBitmask == WRAP_ARY_FLAG) && (bitmask == WRAP_CURRY_FLAG)) || + ((srcBitmask == WRAP_ARY_FLAG) && (bitmask == WRAP_REARG_FLAG) && (data[7].length <= source[8])) || + ((srcBitmask == (WRAP_ARY_FLAG | WRAP_REARG_FLAG)) && (source[7].length <= source[8]) && (bitmask == WRAP_CURRY_FLAG)); + + // Exit early if metadata can't be merged. + if (!(isCommon || isCombo)) { + return data; + } + // Use source `thisArg` if available. + if (srcBitmask & WRAP_BIND_FLAG) { + data[2] = source[2]; + // Set when currying a bound function. + newBitmask |= bitmask & WRAP_BIND_FLAG ? 0 : WRAP_CURRY_BOUND_FLAG; + } + // Compose partial arguments. + var value = source[3]; + if (value) { + var partials = data[3]; + data[3] = partials ? composeArgs(partials, value, source[4]) : value; + data[4] = partials ? replaceHolders(data[3], PLACEHOLDER) : source[4]; + } + // Compose partial right arguments. + value = source[5]; + if (value) { + partials = data[5]; + data[5] = partials ? composeArgsRight(partials, value, source[6]) : value; + data[6] = partials ? replaceHolders(data[5], PLACEHOLDER) : source[6]; + } + // Use source `argPos` if available. + value = source[7]; + if (value) { + data[7] = value; + } + // Use source `ary` if it's smaller. + if (srcBitmask & WRAP_ARY_FLAG) { + data[8] = data[8] == null ? source[8] : nativeMin(data[8], source[8]); + } + // Use source `arity` if one is not provided. + if (data[9] == null) { + data[9] = source[9]; + } + // Use source `func` and merge bitmasks. + data[0] = source[0]; + data[1] = newBitmask; + + return data; + } + + /** + * This function is like + * [`Object.keys`](http://ecma-international.org/ecma-262/7.0/#sec-object.keys) + * except that it includes inherited enumerable properties. + * + * @private + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property names. + */ + function nativeKeysIn(object) { + var result = []; + if (object != null) { + for (var key in Object(object)) { + result.push(key); + } + } + return result; + } + + /** + * Converts `value` to a string using `Object.prototype.toString`. + * + * @private + * @param {*} value The value to convert. + * @returns {string} Returns the converted string. + */ + function objectToString(value) { + return nativeObjectToString.call(value); + } + + /** + * A specialized version of `baseRest` which transforms the rest array. + * + * @private + * @param {Function} func The function to apply a rest parameter to. + * @param {number} [start=func.length-1] The start position of the rest parameter. + * @param {Function} transform The rest array transform. + * @returns {Function} Returns the new function. + */ + function overRest(func, start, transform) { + start = nativeMax(start === undefined ? (func.length - 1) : start, 0); + return function() { + var args = arguments, + index = -1, + length = nativeMax(args.length - start, 0), + array = Array(length); + + while (++index < length) { + array[index] = args[start + index]; + } + index = -1; + var otherArgs = Array(start + 1); + while (++index < start) { + otherArgs[index] = args[index]; + } + otherArgs[start] = transform(array); + return apply(func, this, otherArgs); + }; + } + + /** + * Gets the parent value at `path` of `object`. + * + * @private + * @param {Object} object The object to query. + * @param {Array} path The path to get the parent value of. + * @returns {*} Returns the parent value. + */ + function parent(object, path) { + return path.length < 2 ? object : baseGet(object, baseSlice(path, 0, -1)); + } + + /** + * Reorder `array` according to the specified indexes where the element at + * the first index is assigned as the first element, the element at + * the second index is assigned as the second element, and so on. + * + * @private + * @param {Array} array The array to reorder. + * @param {Array} indexes The arranged array indexes. + * @returns {Array} Returns `array`. + */ + function reorder(array, indexes) { + var arrLength = array.length, + length = nativeMin(indexes.length, arrLength), + oldArray = copyArray(array); + + while (length--) { + var index = indexes[length]; + array[length] = isIndex(index, arrLength) ? oldArray[index] : undefined; + } + return array; + } + + /** + * Gets the value at `key`, unless `key` is "__proto__" or "constructor". + * + * @private + * @param {Object} object The object to query. + * @param {string} key The key of the property to get. + * @returns {*} Returns the property value. + */ + function safeGet(object, key) { + if (key === 'constructor' && typeof object[key] === 'function') { + return; + } + + if (key == '__proto__') { + return; + } + + return object[key]; + } + + /** + * Sets metadata for `func`. + * + * **Note:** If this function becomes hot, i.e. is invoked a lot in a short + * period of time, it will trip its breaker and transition to an identity + * function to avoid garbage collection pauses in V8. See + * [V8 issue 2070](https://bugs.chromium.org/p/v8/issues/detail?id=2070) + * for more details. + * + * @private + * @param {Function} func The function to associate metadata with. + * @param {*} data The metadata. + * @returns {Function} Returns `func`. + */ + var setData = shortOut(baseSetData); + + /** + * A simple wrapper around the global [`setTimeout`](https://mdn.io/setTimeout). + * + * @private + * @param {Function} func The function to delay. + * @param {number} wait The number of milliseconds to delay invocation. + * @returns {number|Object} Returns the timer id or timeout object. + */ + var setTimeout = ctxSetTimeout || function(func, wait) { + return root.setTimeout(func, wait); + }; + + /** + * Sets the `toString` method of `func` to return `string`. + * + * @private + * @param {Function} func The function to modify. + * @param {Function} string The `toString` result. + * @returns {Function} Returns `func`. + */ + var setToString = shortOut(baseSetToString); + + /** + * Sets the `toString` method of `wrapper` to mimic the source of `reference` + * with wrapper details in a comment at the top of the source body. + * + * @private + * @param {Function} wrapper The function to modify. + * @param {Function} reference The reference function. + * @param {number} bitmask The bitmask flags. See `createWrap` for more details. + * @returns {Function} Returns `wrapper`. + */ + function setWrapToString(wrapper, reference, bitmask) { + var source = (reference + ''); + return setToString(wrapper, insertWrapDetails(source, updateWrapDetails(getWrapDetails(source), bitmask))); + } + + /** + * Creates a function that'll short out and invoke `identity` instead + * of `func` when it's called `HOT_COUNT` or more times in `HOT_SPAN` + * milliseconds. + * + * @private + * @param {Function} func The function to restrict. + * @returns {Function} Returns the new shortable function. + */ + function shortOut(func) { + var count = 0, + lastCalled = 0; + + return function() { + var stamp = nativeNow(), + remaining = HOT_SPAN - (stamp - lastCalled); + + lastCalled = stamp; + if (remaining > 0) { + if (++count >= HOT_COUNT) { + return arguments[0]; + } + } else { + count = 0; + } + return func.apply(undefined, arguments); + }; + } + + /** + * A specialized version of `_.shuffle` which mutates and sets the size of `array`. + * + * @private + * @param {Array} array The array to shuffle. + * @param {number} [size=array.length] The size of `array`. + * @returns {Array} Returns `array`. + */ + function shuffleSelf(array, size) { + var index = -1, + length = array.length, + lastIndex = length - 1; + + size = size === undefined ? length : size; + while (++index < size) { + var rand = baseRandom(index, lastIndex), + value = array[rand]; + + array[rand] = array[index]; + array[index] = value; + } + array.length = size; + return array; + } + + /** + * Converts `string` to a property path array. + * + * @private + * @param {string} string The string to convert. + * @returns {Array} Returns the property path array. + */ + var stringToPath = memoizeCapped(function(string) { + var result = []; + if (string.charCodeAt(0) === 46 /* . */) { + result.push(''); + } + string.replace(rePropName, function(match, number, quote, subString) { + result.push(quote ? subString.replace(reEscapeChar, '$1') : (number || match)); + }); + return result; + }); + + /** + * Converts `value` to a string key if it's not a string or symbol. + * + * @private + * @param {*} value The value to inspect. + * @returns {string|symbol} Returns the key. + */ + function toKey(value) { + if (typeof value == 'string' || isSymbol(value)) { + return value; + } + var result = (value + ''); + return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result; + } + + /** + * Converts `func` to its source code. + * + * @private + * @param {Function} func The function to convert. + * @returns {string} Returns the source code. + */ + function toSource(func) { + if (func != null) { + try { + return funcToString.call(func); + } catch (e) {} + try { + return (func + ''); + } catch (e) {} + } + return ''; + } + + /** + * Updates wrapper `details` based on `bitmask` flags. + * + * @private + * @returns {Array} details The details to modify. + * @param {number} bitmask The bitmask flags. See `createWrap` for more details. + * @returns {Array} Returns `details`. + */ + function updateWrapDetails(details, bitmask) { + arrayEach(wrapFlags, function(pair) { + var value = '_.' + pair[0]; + if ((bitmask & pair[1]) && !arrayIncludes(details, value)) { + details.push(value); + } + }); + return details.sort(); + } + + /** + * Creates a clone of `wrapper`. + * + * @private + * @param {Object} wrapper The wrapper to clone. + * @returns {Object} Returns the cloned wrapper. + */ + function wrapperClone(wrapper) { + if (wrapper instanceof LazyWrapper) { + return wrapper.clone(); + } + var result = new LodashWrapper(wrapper.__wrapped__, wrapper.__chain__); + result.__actions__ = copyArray(wrapper.__actions__); + result.__index__ = wrapper.__index__; + result.__values__ = wrapper.__values__; + return result; + } + + /*------------------------------------------------------------------------*/ + + /** + * Creates an array of elements split into groups the length of `size`. + * If `array` can't be split evenly, the final chunk will be the remaining + * elements. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Array + * @param {Array} array The array to process. + * @param {number} [size=1] The length of each chunk + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. + * @returns {Array} Returns the new array of chunks. + * @example + * + * _.chunk(['a', 'b', 'c', 'd'], 2); + * // => [['a', 'b'], ['c', 'd']] + * + * _.chunk(['a', 'b', 'c', 'd'], 3); + * // => [['a', 'b', 'c'], ['d']] + */ + function chunk(array, size, guard) { + if ((guard ? isIterateeCall(array, size, guard) : size === undefined)) { + size = 1; + } else { + size = nativeMax(toInteger(size), 0); + } + var length = array == null ? 0 : array.length; + if (!length || size < 1) { + return []; + } + var index = 0, + resIndex = 0, + result = Array(nativeCeil(length / size)); + + while (index < length) { + result[resIndex++] = baseSlice(array, index, (index += size)); + } + return result; + } + + /** + * Creates an array with all falsey values removed. The values `false`, `null`, + * `0`, `""`, `undefined`, and `NaN` are falsey. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Array + * @param {Array} array The array to compact. + * @returns {Array} Returns the new array of filtered values. + * @example + * + * _.compact([0, 1, false, 2, '', 3]); + * // => [1, 2, 3] + */ + function compact(array) { + var index = -1, + length = array == null ? 0 : array.length, + resIndex = 0, + result = []; + + while (++index < length) { + var value = array[index]; + if (value) { + result[resIndex++] = value; + } + } + return result; + } + + /** + * Creates a new array concatenating `array` with any additional arrays + * and/or values. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {Array} array The array to concatenate. + * @param {...*} [values] The values to concatenate. + * @returns {Array} Returns the new concatenated array. + * @example + * + * var array = [1]; + * var other = _.concat(array, 2, [3], [[4]]); + * + * console.log(other); + * // => [1, 2, 3, [4]] + * + * console.log(array); + * // => [1] + */ + function concat() { + var length = arguments.length; + if (!length) { + return []; + } + var args = Array(length - 1), + array = arguments[0], + index = length; + + while (index--) { + args[index - 1] = arguments[index]; + } + return arrayPush(isArray(array) ? copyArray(array) : [array], baseFlatten(args, 1)); + } + + /** + * Creates an array of `array` values not included in the other given arrays + * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) + * for equality comparisons. The order and references of result values are + * determined by the first array. + * + * **Note:** Unlike `_.pullAll`, this method returns a new array. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Array + * @param {Array} array The array to inspect. + * @param {...Array} [values] The values to exclude. + * @returns {Array} Returns the new array of filtered values. + * @see _.without, _.xor + * @example + * + * _.difference([2, 1], [2, 3]); + * // => [1] + */ + var difference = baseRest(function(array, values) { + return isArrayLikeObject(array) + ? baseDifference(array, baseFlatten(values, 1, isArrayLikeObject, true)) + : []; + }); + + /** + * This method is like `_.difference` except that it accepts `iteratee` which + * is invoked for each element of `array` and `values` to generate the criterion + * by which they're compared. The order and references of result values are + * determined by the first array. The iteratee is invoked with one argument: + * (value). + * + * **Note:** Unlike `_.pullAllBy`, this method returns a new array. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {Array} array The array to inspect. + * @param {...Array} [values] The values to exclude. + * @param {Function} [iteratee=_.identity] The iteratee invoked per element. + * @returns {Array} Returns the new array of filtered values. + * @example + * + * _.differenceBy([2.1, 1.2], [2.3, 3.4], Math.floor); + * // => [1.2] + * + * // The `_.property` iteratee shorthand. + * _.differenceBy([{ 'x': 2 }, { 'x': 1 }], [{ 'x': 1 }], 'x'); + * // => [{ 'x': 2 }] + */ + var differenceBy = baseRest(function(array, values) { + var iteratee = last(values); + if (isArrayLikeObject(iteratee)) { + iteratee = undefined; + } + return isArrayLikeObject(array) + ? baseDifference(array, baseFlatten(values, 1, isArrayLikeObject, true), getIteratee(iteratee, 2)) + : []; + }); + + /** + * This method is like `_.difference` except that it accepts `comparator` + * which is invoked to compare elements of `array` to `values`. The order and + * references of result values are determined by the first array. The comparator + * is invoked with two arguments: (arrVal, othVal). + * + * **Note:** Unlike `_.pullAllWith`, this method returns a new array. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {Array} array The array to inspect. + * @param {...Array} [values] The values to exclude. + * @param {Function} [comparator] The comparator invoked per element. + * @returns {Array} Returns the new array of filtered values. + * @example + * + * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }]; + * + * _.differenceWith(objects, [{ 'x': 1, 'y': 2 }], _.isEqual); + * // => [{ 'x': 2, 'y': 1 }] + */ + var differenceWith = baseRest(function(array, values) { + var comparator = last(values); + if (isArrayLikeObject(comparator)) { + comparator = undefined; + } + return isArrayLikeObject(array) + ? baseDifference(array, baseFlatten(values, 1, isArrayLikeObject, true), undefined, comparator) + : []; + }); + + /** + * Creates a slice of `array` with `n` elements dropped from the beginning. + * + * @static + * @memberOf _ + * @since 0.5.0 + * @category Array + * @param {Array} array The array to query. + * @param {number} [n=1] The number of elements to drop. + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. + * @returns {Array} Returns the slice of `array`. + * @example + * + * _.drop([1, 2, 3]); + * // => [2, 3] + * + * _.drop([1, 2, 3], 2); + * // => [3] + * + * _.drop([1, 2, 3], 5); + * // => [] + * + * _.drop([1, 2, 3], 0); + * // => [1, 2, 3] + */ + function drop(array, n, guard) { + var length = array == null ? 0 : array.length; + if (!length) { + return []; + } + n = (guard || n === undefined) ? 1 : toInteger(n); + return baseSlice(array, n < 0 ? 0 : n, length); + } + + /** + * Creates a slice of `array` with `n` elements dropped from the end. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Array + * @param {Array} array The array to query. + * @param {number} [n=1] The number of elements to drop. + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. + * @returns {Array} Returns the slice of `array`. + * @example + * + * _.dropRight([1, 2, 3]); + * // => [1, 2] + * + * _.dropRight([1, 2, 3], 2); + * // => [1] + * + * _.dropRight([1, 2, 3], 5); + * // => [] + * + * _.dropRight([1, 2, 3], 0); + * // => [1, 2, 3] + */ + function dropRight(array, n, guard) { + var length = array == null ? 0 : array.length; + if (!length) { + return []; + } + n = (guard || n === undefined) ? 1 : toInteger(n); + n = length - n; + return baseSlice(array, 0, n < 0 ? 0 : n); + } + + /** + * Creates a slice of `array` excluding elements dropped from the end. + * Elements are dropped until `predicate` returns falsey. The predicate is + * invoked with three arguments: (value, index, array). + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Array + * @param {Array} array The array to query. + * @param {Function} [predicate=_.identity] The function invoked per iteration. + * @returns {Array} Returns the slice of `array`. + * @example + * + * var users = [ + * { 'user': 'barney', 'active': true }, + * { 'user': 'fred', 'active': false }, + * { 'user': 'pebbles', 'active': false } + * ]; + * + * _.dropRightWhile(users, function(o) { return !o.active; }); + * // => objects for ['barney'] + * + * // The `_.matches` iteratee shorthand. + * _.dropRightWhile(users, { 'user': 'pebbles', 'active': false }); + * // => objects for ['barney', 'fred'] + * + * // The `_.matchesProperty` iteratee shorthand. + * _.dropRightWhile(users, ['active', false]); + * // => objects for ['barney'] + * + * // The `_.property` iteratee shorthand. + * _.dropRightWhile(users, 'active'); + * // => objects for ['barney', 'fred', 'pebbles'] + */ + function dropRightWhile(array, predicate) { + return (array && array.length) + ? baseWhile(array, getIteratee(predicate, 3), true, true) + : []; + } + + /** + * Creates a slice of `array` excluding elements dropped from the beginning. + * Elements are dropped until `predicate` returns falsey. The predicate is + * invoked with three arguments: (value, index, array). + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Array + * @param {Array} array The array to query. + * @param {Function} [predicate=_.identity] The function invoked per iteration. + * @returns {Array} Returns the slice of `array`. + * @example + * + * var users = [ + * { 'user': 'barney', 'active': false }, + * { 'user': 'fred', 'active': false }, + * { 'user': 'pebbles', 'active': true } + * ]; + * + * _.dropWhile(users, function(o) { return !o.active; }); + * // => objects for ['pebbles'] + * + * // The `_.matches` iteratee shorthand. + * _.dropWhile(users, { 'user': 'barney', 'active': false }); + * // => objects for ['fred', 'pebbles'] + * + * // The `_.matchesProperty` iteratee shorthand. + * _.dropWhile(users, ['active', false]); + * // => objects for ['pebbles'] + * + * // The `_.property` iteratee shorthand. + * _.dropWhile(users, 'active'); + * // => objects for ['barney', 'fred', 'pebbles'] + */ + function dropWhile(array, predicate) { + return (array && array.length) + ? baseWhile(array, getIteratee(predicate, 3), true) + : []; + } + + /** + * Fills elements of `array` with `value` from `start` up to, but not + * including, `end`. + * + * **Note:** This method mutates `array`. + * + * @static + * @memberOf _ + * @since 3.2.0 + * @category Array + * @param {Array} array The array to fill. + * @param {*} value The value to fill `array` with. + * @param {number} [start=0] The start position. + * @param {number} [end=array.length] The end position. + * @returns {Array} Returns `array`. + * @example + * + * var array = [1, 2, 3]; + * + * _.fill(array, 'a'); + * console.log(array); + * // => ['a', 'a', 'a'] + * + * _.fill(Array(3), 2); + * // => [2, 2, 2] + * + * _.fill([4, 6, 8, 10], '*', 1, 3); + * // => [4, '*', '*', 10] + */ + function fill(array, value, start, end) { + var length = array == null ? 0 : array.length; + if (!length) { + return []; + } + if (start && typeof start != 'number' && isIterateeCall(array, value, start)) { + start = 0; + end = length; + } + return baseFill(array, value, start, end); + } + + /** + * This method is like `_.find` except that it returns the index of the first + * element `predicate` returns truthy for instead of the element itself. + * + * @static + * @memberOf _ + * @since 1.1.0 + * @category Array + * @param {Array} array The array to inspect. + * @param {Function} [predicate=_.identity] The function invoked per iteration. + * @param {number} [fromIndex=0] The index to search from. + * @returns {number} Returns the index of the found element, else `-1`. + * @example + * + * var users = [ + * { 'user': 'barney', 'active': false }, + * { 'user': 'fred', 'active': false }, + * { 'user': 'pebbles', 'active': true } + * ]; + * + * _.findIndex(users, function(o) { return o.user == 'barney'; }); + * // => 0 + * + * // The `_.matches` iteratee shorthand. + * _.findIndex(users, { 'user': 'fred', 'active': false }); + * // => 1 + * + * // The `_.matchesProperty` iteratee shorthand. + * _.findIndex(users, ['active', false]); + * // => 0 + * + * // The `_.property` iteratee shorthand. + * _.findIndex(users, 'active'); + * // => 2 + */ + function findIndex(array, predicate, fromIndex) { + var length = array == null ? 0 : array.length; + if (!length) { + return -1; + } + var index = fromIndex == null ? 0 : toInteger(fromIndex); + if (index < 0) { + index = nativeMax(length + index, 0); + } + return baseFindIndex(array, getIteratee(predicate, 3), index); + } + + /** + * This method is like `_.findIndex` except that it iterates over elements + * of `collection` from right to left. + * + * @static + * @memberOf _ + * @since 2.0.0 + * @category Array + * @param {Array} array The array to inspect. + * @param {Function} [predicate=_.identity] The function invoked per iteration. + * @param {number} [fromIndex=array.length-1] The index to search from. + * @returns {number} Returns the index of the found element, else `-1`. + * @example + * + * var users = [ + * { 'user': 'barney', 'active': true }, + * { 'user': 'fred', 'active': false }, + * { 'user': 'pebbles', 'active': false } + * ]; + * + * _.findLastIndex(users, function(o) { return o.user == 'pebbles'; }); + * // => 2 + * + * // The `_.matches` iteratee shorthand. + * _.findLastIndex(users, { 'user': 'barney', 'active': true }); + * // => 0 + * + * // The `_.matchesProperty` iteratee shorthand. + * _.findLastIndex(users, ['active', false]); + * // => 2 + * + * // The `_.property` iteratee shorthand. + * _.findLastIndex(users, 'active'); + * // => 0 + */ + function findLastIndex(array, predicate, fromIndex) { + var length = array == null ? 0 : array.length; + if (!length) { + return -1; + } + var index = length - 1; + if (fromIndex !== undefined) { + index = toInteger(fromIndex); + index = fromIndex < 0 + ? nativeMax(length + index, 0) + : nativeMin(index, length - 1); + } + return baseFindIndex(array, getIteratee(predicate, 3), index, true); + } + + /** + * Flattens `array` a single level deep. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Array + * @param {Array} array The array to flatten. + * @returns {Array} Returns the new flattened array. + * @example + * + * _.flatten([1, [2, [3, [4]], 5]]); + * // => [1, 2, [3, [4]], 5] + */ + function flatten(array) { + var length = array == null ? 0 : array.length; + return length ? baseFlatten(array, 1) : []; + } + + /** + * Recursively flattens `array`. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Array + * @param {Array} array The array to flatten. + * @returns {Array} Returns the new flattened array. + * @example + * + * _.flattenDeep([1, [2, [3, [4]], 5]]); + * // => [1, 2, 3, 4, 5] + */ + function flattenDeep(array) { + var length = array == null ? 0 : array.length; + return length ? baseFlatten(array, INFINITY) : []; + } + + /** + * Recursively flatten `array` up to `depth` times. + * + * @static + * @memberOf _ + * @since 4.4.0 + * @category Array + * @param {Array} array The array to flatten. + * @param {number} [depth=1] The maximum recursion depth. + * @returns {Array} Returns the new flattened array. + * @example + * + * var array = [1, [2, [3, [4]], 5]]; + * + * _.flattenDepth(array, 1); + * // => [1, 2, [3, [4]], 5] + * + * _.flattenDepth(array, 2); + * // => [1, 2, 3, [4], 5] + */ + function flattenDepth(array, depth) { + var length = array == null ? 0 : array.length; + if (!length) { + return []; + } + depth = depth === undefined ? 1 : toInteger(depth); + return baseFlatten(array, depth); + } + + /** + * The inverse of `_.toPairs`; this method returns an object composed + * from key-value `pairs`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {Array} pairs The key-value pairs. + * @returns {Object} Returns the new object. + * @example + * + * _.fromPairs([['a', 1], ['b', 2]]); + * // => { 'a': 1, 'b': 2 } + */ + function fromPairs(pairs) { + var index = -1, + length = pairs == null ? 0 : pairs.length, + result = {}; + + while (++index < length) { + var pair = pairs[index]; + result[pair[0]] = pair[1]; + } + return result; + } + + /** + * Gets the first element of `array`. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @alias first + * @category Array + * @param {Array} array The array to query. + * @returns {*} Returns the first element of `array`. + * @example + * + * _.head([1, 2, 3]); + * // => 1 + * + * _.head([]); + * // => undefined + */ + function head(array) { + return (array && array.length) ? array[0] : undefined; + } + + /** + * Gets the index at which the first occurrence of `value` is found in `array` + * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) + * for equality comparisons. If `fromIndex` is negative, it's used as the + * offset from the end of `array`. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Array + * @param {Array} array The array to inspect. + * @param {*} value The value to search for. + * @param {number} [fromIndex=0] The index to search from. + * @returns {number} Returns the index of the matched value, else `-1`. + * @example + * + * _.indexOf([1, 2, 1, 2], 2); + * // => 1 + * + * // Search from the `fromIndex`. + * _.indexOf([1, 2, 1, 2], 2, 2); + * // => 3 + */ + function indexOf(array, value, fromIndex) { + var length = array == null ? 0 : array.length; + if (!length) { + return -1; + } + var index = fromIndex == null ? 0 : toInteger(fromIndex); + if (index < 0) { + index = nativeMax(length + index, 0); + } + return baseIndexOf(array, value, index); + } + + /** + * Gets all but the last element of `array`. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Array + * @param {Array} array The array to query. + * @returns {Array} Returns the slice of `array`. + * @example + * + * _.initial([1, 2, 3]); + * // => [1, 2] + */ + function initial(array) { + var length = array == null ? 0 : array.length; + return length ? baseSlice(array, 0, -1) : []; + } + + /** + * Creates an array of unique values that are included in all given arrays + * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) + * for equality comparisons. The order and references of result values are + * determined by the first array. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Array + * @param {...Array} [arrays] The arrays to inspect. + * @returns {Array} Returns the new array of intersecting values. + * @example + * + * _.intersection([2, 1], [2, 3]); + * // => [2] + */ + var intersection = baseRest(function(arrays) { + var mapped = arrayMap(arrays, castArrayLikeObject); + return (mapped.length && mapped[0] === arrays[0]) + ? baseIntersection(mapped) + : []; + }); + + /** + * This method is like `_.intersection` except that it accepts `iteratee` + * which is invoked for each element of each `arrays` to generate the criterion + * by which they're compared. The order and references of result values are + * determined by the first array. The iteratee is invoked with one argument: + * (value). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {...Array} [arrays] The arrays to inspect. + * @param {Function} [iteratee=_.identity] The iteratee invoked per element. + * @returns {Array} Returns the new array of intersecting values. + * @example + * + * _.intersectionBy([2.1, 1.2], [2.3, 3.4], Math.floor); + * // => [2.1] + * + * // The `_.property` iteratee shorthand. + * _.intersectionBy([{ 'x': 1 }], [{ 'x': 2 }, { 'x': 1 }], 'x'); + * // => [{ 'x': 1 }] + */ + var intersectionBy = baseRest(function(arrays) { + var iteratee = last(arrays), + mapped = arrayMap(arrays, castArrayLikeObject); + + if (iteratee === last(mapped)) { + iteratee = undefined; + } else { + mapped.pop(); + } + return (mapped.length && mapped[0] === arrays[0]) + ? baseIntersection(mapped, getIteratee(iteratee, 2)) + : []; + }); + + /** + * This method is like `_.intersection` except that it accepts `comparator` + * which is invoked to compare elements of `arrays`. The order and references + * of result values are determined by the first array. The comparator is + * invoked with two arguments: (arrVal, othVal). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {...Array} [arrays] The arrays to inspect. + * @param {Function} [comparator] The comparator invoked per element. + * @returns {Array} Returns the new array of intersecting values. + * @example + * + * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }]; + * var others = [{ 'x': 1, 'y': 1 }, { 'x': 1, 'y': 2 }]; + * + * _.intersectionWith(objects, others, _.isEqual); + * // => [{ 'x': 1, 'y': 2 }] + */ + var intersectionWith = baseRest(function(arrays) { + var comparator = last(arrays), + mapped = arrayMap(arrays, castArrayLikeObject); + + comparator = typeof comparator == 'function' ? comparator : undefined; + if (comparator) { + mapped.pop(); + } + return (mapped.length && mapped[0] === arrays[0]) + ? baseIntersection(mapped, undefined, comparator) + : []; + }); + + /** + * Converts all elements in `array` into a string separated by `separator`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {Array} array The array to convert. + * @param {string} [separator=','] The element separator. + * @returns {string} Returns the joined string. + * @example + * + * _.join(['a', 'b', 'c'], '~'); + * // => 'a~b~c' + */ + function join(array, separator) { + return array == null ? '' : nativeJoin.call(array, separator); + } + + /** + * Gets the last element of `array`. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Array + * @param {Array} array The array to query. + * @returns {*} Returns the last element of `array`. + * @example + * + * _.last([1, 2, 3]); + * // => 3 + */ + function last(array) { + var length = array == null ? 0 : array.length; + return length ? array[length - 1] : undefined; + } + + /** + * This method is like `_.indexOf` except that it iterates over elements of + * `array` from right to left. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Array + * @param {Array} array The array to inspect. + * @param {*} value The value to search for. + * @param {number} [fromIndex=array.length-1] The index to search from. + * @returns {number} Returns the index of the matched value, else `-1`. + * @example + * + * _.lastIndexOf([1, 2, 1, 2], 2); + * // => 3 + * + * // Search from the `fromIndex`. + * _.lastIndexOf([1, 2, 1, 2], 2, 2); + * // => 1 + */ + function lastIndexOf(array, value, fromIndex) { + var length = array == null ? 0 : array.length; + if (!length) { + return -1; + } + var index = length; + if (fromIndex !== undefined) { + index = toInteger(fromIndex); + index = index < 0 ? nativeMax(length + index, 0) : nativeMin(index, length - 1); + } + return value === value + ? strictLastIndexOf(array, value, index) + : baseFindIndex(array, baseIsNaN, index, true); + } + + /** + * Gets the element at index `n` of `array`. If `n` is negative, the nth + * element from the end is returned. + * + * @static + * @memberOf _ + * @since 4.11.0 + * @category Array + * @param {Array} array The array to query. + * @param {number} [n=0] The index of the element to return. + * @returns {*} Returns the nth element of `array`. + * @example + * + * var array = ['a', 'b', 'c', 'd']; + * + * _.nth(array, 1); + * // => 'b' + * + * _.nth(array, -2); + * // => 'c'; + */ + function nth(array, n) { + return (array && array.length) ? baseNth(array, toInteger(n)) : undefined; + } + + /** + * Removes all given values from `array` using + * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) + * for equality comparisons. + * + * **Note:** Unlike `_.without`, this method mutates `array`. Use `_.remove` + * to remove elements from an array by predicate. + * + * @static + * @memberOf _ + * @since 2.0.0 + * @category Array + * @param {Array} array The array to modify. + * @param {...*} [values] The values to remove. + * @returns {Array} Returns `array`. + * @example + * + * var array = ['a', 'b', 'c', 'a', 'b', 'c']; + * + * _.pull(array, 'a', 'c'); + * console.log(array); + * // => ['b', 'b'] + */ + var pull = baseRest(pullAll); + + /** + * This method is like `_.pull` except that it accepts an array of values to remove. + * + * **Note:** Unlike `_.difference`, this method mutates `array`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {Array} array The array to modify. + * @param {Array} values The values to remove. + * @returns {Array} Returns `array`. + * @example + * + * var array = ['a', 'b', 'c', 'a', 'b', 'c']; + * + * _.pullAll(array, ['a', 'c']); + * console.log(array); + * // => ['b', 'b'] + */ + function pullAll(array, values) { + return (array && array.length && values && values.length) + ? basePullAll(array, values) + : array; + } + + /** + * This method is like `_.pullAll` except that it accepts `iteratee` which is + * invoked for each element of `array` and `values` to generate the criterion + * by which they're compared. The iteratee is invoked with one argument: (value). + * + * **Note:** Unlike `_.differenceBy`, this method mutates `array`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {Array} array The array to modify. + * @param {Array} values The values to remove. + * @param {Function} [iteratee=_.identity] The iteratee invoked per element. + * @returns {Array} Returns `array`. + * @example + * + * var array = [{ 'x': 1 }, { 'x': 2 }, { 'x': 3 }, { 'x': 1 }]; + * + * _.pullAllBy(array, [{ 'x': 1 }, { 'x': 3 }], 'x'); + * console.log(array); + * // => [{ 'x': 2 }] + */ + function pullAllBy(array, values, iteratee) { + return (array && array.length && values && values.length) + ? basePullAll(array, values, getIteratee(iteratee, 2)) + : array; + } + + /** + * This method is like `_.pullAll` except that it accepts `comparator` which + * is invoked to compare elements of `array` to `values`. The comparator is + * invoked with two arguments: (arrVal, othVal). + * + * **Note:** Unlike `_.differenceWith`, this method mutates `array`. + * + * @static + * @memberOf _ + * @since 4.6.0 + * @category Array + * @param {Array} array The array to modify. + * @param {Array} values The values to remove. + * @param {Function} [comparator] The comparator invoked per element. + * @returns {Array} Returns `array`. + * @example + * + * var array = [{ 'x': 1, 'y': 2 }, { 'x': 3, 'y': 4 }, { 'x': 5, 'y': 6 }]; + * + * _.pullAllWith(array, [{ 'x': 3, 'y': 4 }], _.isEqual); + * console.log(array); + * // => [{ 'x': 1, 'y': 2 }, { 'x': 5, 'y': 6 }] + */ + function pullAllWith(array, values, comparator) { + return (array && array.length && values && values.length) + ? basePullAll(array, values, undefined, comparator) + : array; + } + + /** + * Removes elements from `array` corresponding to `indexes` and returns an + * array of removed elements. + * + * **Note:** Unlike `_.at`, this method mutates `array`. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Array + * @param {Array} array The array to modify. + * @param {...(number|number[])} [indexes] The indexes of elements to remove. + * @returns {Array} Returns the new array of removed elements. + * @example + * + * var array = ['a', 'b', 'c', 'd']; + * var pulled = _.pullAt(array, [1, 3]); + * + * console.log(array); + * // => ['a', 'c'] + * + * console.log(pulled); + * // => ['b', 'd'] + */ + var pullAt = flatRest(function(array, indexes) { + var length = array == null ? 0 : array.length, + result = baseAt(array, indexes); + + basePullAt(array, arrayMap(indexes, function(index) { + return isIndex(index, length) ? +index : index; + }).sort(compareAscending)); + + return result; + }); + + /** + * Removes all elements from `array` that `predicate` returns truthy for + * and returns an array of the removed elements. The predicate is invoked + * with three arguments: (value, index, array). + * + * **Note:** Unlike `_.filter`, this method mutates `array`. Use `_.pull` + * to pull elements from an array by value. + * + * @static + * @memberOf _ + * @since 2.0.0 + * @category Array + * @param {Array} array The array to modify. + * @param {Function} [predicate=_.identity] The function invoked per iteration. + * @returns {Array} Returns the new array of removed elements. + * @example + * + * var array = [1, 2, 3, 4]; + * var evens = _.remove(array, function(n) { + * return n % 2 == 0; + * }); + * + * console.log(array); + * // => [1, 3] + * + * console.log(evens); + * // => [2, 4] + */ + function remove(array, predicate) { + var result = []; + if (!(array && array.length)) { + return result; + } + var index = -1, + indexes = [], + length = array.length; + + predicate = getIteratee(predicate, 3); + while (++index < length) { + var value = array[index]; + if (predicate(value, index, array)) { + result.push(value); + indexes.push(index); + } + } + basePullAt(array, indexes); + return result; + } + + /** + * Reverses `array` so that the first element becomes the last, the second + * element becomes the second to last, and so on. + * + * **Note:** This method mutates `array` and is based on + * [`Array#reverse`](https://mdn.io/Array/reverse). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {Array} array The array to modify. + * @returns {Array} Returns `array`. + * @example + * + * var array = [1, 2, 3]; + * + * _.reverse(array); + * // => [3, 2, 1] + * + * console.log(array); + * // => [3, 2, 1] + */ + function reverse(array) { + return array == null ? array : nativeReverse.call(array); + } + + /** + * Creates a slice of `array` from `start` up to, but not including, `end`. + * + * **Note:** This method is used instead of + * [`Array#slice`](https://mdn.io/Array/slice) to ensure dense arrays are + * returned. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Array + * @param {Array} array The array to slice. + * @param {number} [start=0] The start position. + * @param {number} [end=array.length] The end position. + * @returns {Array} Returns the slice of `array`. + */ + function slice(array, start, end) { + var length = array == null ? 0 : array.length; + if (!length) { + return []; + } + if (end && typeof end != 'number' && isIterateeCall(array, start, end)) { + start = 0; + end = length; + } + else { + start = start == null ? 0 : toInteger(start); + end = end === undefined ? length : toInteger(end); + } + return baseSlice(array, start, end); + } + + /** + * Uses a binary search to determine the lowest index at which `value` + * should be inserted into `array` in order to maintain its sort order. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Array + * @param {Array} array The sorted array to inspect. + * @param {*} value The value to evaluate. + * @returns {number} Returns the index at which `value` should be inserted + * into `array`. + * @example + * + * _.sortedIndex([30, 50], 40); + * // => 1 + */ + function sortedIndex(array, value) { + return baseSortedIndex(array, value); + } + + /** + * This method is like `_.sortedIndex` except that it accepts `iteratee` + * which is invoked for `value` and each element of `array` to compute their + * sort ranking. The iteratee is invoked with one argument: (value). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {Array} array The sorted array to inspect. + * @param {*} value The value to evaluate. + * @param {Function} [iteratee=_.identity] The iteratee invoked per element. + * @returns {number} Returns the index at which `value` should be inserted + * into `array`. + * @example + * + * var objects = [{ 'x': 4 }, { 'x': 5 }]; + * + * _.sortedIndexBy(objects, { 'x': 4 }, function(o) { return o.x; }); + * // => 0 + * + * // The `_.property` iteratee shorthand. + * _.sortedIndexBy(objects, { 'x': 4 }, 'x'); + * // => 0 + */ + function sortedIndexBy(array, value, iteratee) { + return baseSortedIndexBy(array, value, getIteratee(iteratee, 2)); + } + + /** + * This method is like `_.indexOf` except that it performs a binary + * search on a sorted `array`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {Array} array The array to inspect. + * @param {*} value The value to search for. + * @returns {number} Returns the index of the matched value, else `-1`. + * @example + * + * _.sortedIndexOf([4, 5, 5, 5, 6], 5); + * // => 1 + */ + function sortedIndexOf(array, value) { + var length = array == null ? 0 : array.length; + if (length) { + var index = baseSortedIndex(array, value); + if (index < length && eq(array[index], value)) { + return index; + } + } + return -1; + } + + /** + * This method is like `_.sortedIndex` except that it returns the highest + * index at which `value` should be inserted into `array` in order to + * maintain its sort order. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Array + * @param {Array} array The sorted array to inspect. + * @param {*} value The value to evaluate. + * @returns {number} Returns the index at which `value` should be inserted + * into `array`. + * @example + * + * _.sortedLastIndex([4, 5, 5, 5, 6], 5); + * // => 4 + */ + function sortedLastIndex(array, value) { + return baseSortedIndex(array, value, true); + } + + /** + * This method is like `_.sortedLastIndex` except that it accepts `iteratee` + * which is invoked for `value` and each element of `array` to compute their + * sort ranking. The iteratee is invoked with one argument: (value). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {Array} array The sorted array to inspect. + * @param {*} value The value to evaluate. + * @param {Function} [iteratee=_.identity] The iteratee invoked per element. + * @returns {number} Returns the index at which `value` should be inserted + * into `array`. + * @example + * + * var objects = [{ 'x': 4 }, { 'x': 5 }]; + * + * _.sortedLastIndexBy(objects, { 'x': 4 }, function(o) { return o.x; }); + * // => 1 + * + * // The `_.property` iteratee shorthand. + * _.sortedLastIndexBy(objects, { 'x': 4 }, 'x'); + * // => 1 + */ + function sortedLastIndexBy(array, value, iteratee) { + return baseSortedIndexBy(array, value, getIteratee(iteratee, 2), true); + } + + /** + * This method is like `_.lastIndexOf` except that it performs a binary + * search on a sorted `array`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {Array} array The array to inspect. + * @param {*} value The value to search for. + * @returns {number} Returns the index of the matched value, else `-1`. + * @example + * + * _.sortedLastIndexOf([4, 5, 5, 5, 6], 5); + * // => 3 + */ + function sortedLastIndexOf(array, value) { + var length = array == null ? 0 : array.length; + if (length) { + var index = baseSortedIndex(array, value, true) - 1; + if (eq(array[index], value)) { + return index; + } + } + return -1; + } + + /** + * This method is like `_.uniq` except that it's designed and optimized + * for sorted arrays. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {Array} array The array to inspect. + * @returns {Array} Returns the new duplicate free array. + * @example + * + * _.sortedUniq([1, 1, 2]); + * // => [1, 2] + */ + function sortedUniq(array) { + return (array && array.length) + ? baseSortedUniq(array) + : []; + } + + /** + * This method is like `_.uniqBy` except that it's designed and optimized + * for sorted arrays. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {Array} array The array to inspect. + * @param {Function} [iteratee] The iteratee invoked per element. + * @returns {Array} Returns the new duplicate free array. + * @example + * + * _.sortedUniqBy([1.1, 1.2, 2.3, 2.4], Math.floor); + * // => [1.1, 2.3] + */ + function sortedUniqBy(array, iteratee) { + return (array && array.length) + ? baseSortedUniq(array, getIteratee(iteratee, 2)) + : []; + } + + /** + * Gets all but the first element of `array`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {Array} array The array to query. + * @returns {Array} Returns the slice of `array`. + * @example + * + * _.tail([1, 2, 3]); + * // => [2, 3] + */ + function tail(array) { + var length = array == null ? 0 : array.length; + return length ? baseSlice(array, 1, length) : []; + } + + /** + * Creates a slice of `array` with `n` elements taken from the beginning. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Array + * @param {Array} array The array to query. + * @param {number} [n=1] The number of elements to take. + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. + * @returns {Array} Returns the slice of `array`. + * @example + * + * _.take([1, 2, 3]); + * // => [1] + * + * _.take([1, 2, 3], 2); + * // => [1, 2] + * + * _.take([1, 2, 3], 5); + * // => [1, 2, 3] + * + * _.take([1, 2, 3], 0); + * // => [] + */ + function take(array, n, guard) { + if (!(array && array.length)) { + return []; + } + n = (guard || n === undefined) ? 1 : toInteger(n); + return baseSlice(array, 0, n < 0 ? 0 : n); + } + + /** + * Creates a slice of `array` with `n` elements taken from the end. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Array + * @param {Array} array The array to query. + * @param {number} [n=1] The number of elements to take. + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. + * @returns {Array} Returns the slice of `array`. + * @example + * + * _.takeRight([1, 2, 3]); + * // => [3] + * + * _.takeRight([1, 2, 3], 2); + * // => [2, 3] + * + * _.takeRight([1, 2, 3], 5); + * // => [1, 2, 3] + * + * _.takeRight([1, 2, 3], 0); + * // => [] + */ + function takeRight(array, n, guard) { + var length = array == null ? 0 : array.length; + if (!length) { + return []; + } + n = (guard || n === undefined) ? 1 : toInteger(n); + n = length - n; + return baseSlice(array, n < 0 ? 0 : n, length); + } + + /** + * Creates a slice of `array` with elements taken from the end. Elements are + * taken until `predicate` returns falsey. The predicate is invoked with + * three arguments: (value, index, array). + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Array + * @param {Array} array The array to query. + * @param {Function} [predicate=_.identity] The function invoked per iteration. + * @returns {Array} Returns the slice of `array`. + * @example + * + * var users = [ + * { 'user': 'barney', 'active': true }, + * { 'user': 'fred', 'active': false }, + * { 'user': 'pebbles', 'active': false } + * ]; + * + * _.takeRightWhile(users, function(o) { return !o.active; }); + * // => objects for ['fred', 'pebbles'] + * + * // The `_.matches` iteratee shorthand. + * _.takeRightWhile(users, { 'user': 'pebbles', 'active': false }); + * // => objects for ['pebbles'] + * + * // The `_.matchesProperty` iteratee shorthand. + * _.takeRightWhile(users, ['active', false]); + * // => objects for ['fred', 'pebbles'] + * + * // The `_.property` iteratee shorthand. + * _.takeRightWhile(users, 'active'); + * // => [] + */ + function takeRightWhile(array, predicate) { + return (array && array.length) + ? baseWhile(array, getIteratee(predicate, 3), false, true) + : []; + } + + /** + * Creates a slice of `array` with elements taken from the beginning. Elements + * are taken until `predicate` returns falsey. The predicate is invoked with + * three arguments: (value, index, array). + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Array + * @param {Array} array The array to query. + * @param {Function} [predicate=_.identity] The function invoked per iteration. + * @returns {Array} Returns the slice of `array`. + * @example + * + * var users = [ + * { 'user': 'barney', 'active': false }, + * { 'user': 'fred', 'active': false }, + * { 'user': 'pebbles', 'active': true } + * ]; + * + * _.takeWhile(users, function(o) { return !o.active; }); + * // => objects for ['barney', 'fred'] + * + * // The `_.matches` iteratee shorthand. + * _.takeWhile(users, { 'user': 'barney', 'active': false }); + * // => objects for ['barney'] + * + * // The `_.matchesProperty` iteratee shorthand. + * _.takeWhile(users, ['active', false]); + * // => objects for ['barney', 'fred'] + * + * // The `_.property` iteratee shorthand. + * _.takeWhile(users, 'active'); + * // => [] + */ + function takeWhile(array, predicate) { + return (array && array.length) + ? baseWhile(array, getIteratee(predicate, 3)) + : []; + } + + /** + * Creates an array of unique values, in order, from all given arrays using + * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) + * for equality comparisons. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Array + * @param {...Array} [arrays] The arrays to inspect. + * @returns {Array} Returns the new array of combined values. + * @example + * + * _.union([2], [1, 2]); + * // => [2, 1] + */ + var union = baseRest(function(arrays) { + return baseUniq(baseFlatten(arrays, 1, isArrayLikeObject, true)); + }); + + /** + * This method is like `_.union` except that it accepts `iteratee` which is + * invoked for each element of each `arrays` to generate the criterion by + * which uniqueness is computed. Result values are chosen from the first + * array in which the value occurs. The iteratee is invoked with one argument: + * (value). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {...Array} [arrays] The arrays to inspect. + * @param {Function} [iteratee=_.identity] The iteratee invoked per element. + * @returns {Array} Returns the new array of combined values. + * @example + * + * _.unionBy([2.1], [1.2, 2.3], Math.floor); + * // => [2.1, 1.2] + * + * // The `_.property` iteratee shorthand. + * _.unionBy([{ 'x': 1 }], [{ 'x': 2 }, { 'x': 1 }], 'x'); + * // => [{ 'x': 1 }, { 'x': 2 }] + */ + var unionBy = baseRest(function(arrays) { + var iteratee = last(arrays); + if (isArrayLikeObject(iteratee)) { + iteratee = undefined; + } + return baseUniq(baseFlatten(arrays, 1, isArrayLikeObject, true), getIteratee(iteratee, 2)); + }); + + /** + * This method is like `_.union` except that it accepts `comparator` which + * is invoked to compare elements of `arrays`. Result values are chosen from + * the first array in which the value occurs. The comparator is invoked + * with two arguments: (arrVal, othVal). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {...Array} [arrays] The arrays to inspect. + * @param {Function} [comparator] The comparator invoked per element. + * @returns {Array} Returns the new array of combined values. + * @example + * + * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }]; + * var others = [{ 'x': 1, 'y': 1 }, { 'x': 1, 'y': 2 }]; + * + * _.unionWith(objects, others, _.isEqual); + * // => [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }, { 'x': 1, 'y': 1 }] + */ + var unionWith = baseRest(function(arrays) { + var comparator = last(arrays); + comparator = typeof comparator == 'function' ? comparator : undefined; + return baseUniq(baseFlatten(arrays, 1, isArrayLikeObject, true), undefined, comparator); + }); + + /** + * Creates a duplicate-free version of an array, using + * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) + * for equality comparisons, in which only the first occurrence of each element + * is kept. The order of result values is determined by the order they occur + * in the array. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Array + * @param {Array} array The array to inspect. + * @returns {Array} Returns the new duplicate free array. + * @example + * + * _.uniq([2, 1, 2]); + * // => [2, 1] + */ + function uniq(array) { + return (array && array.length) ? baseUniq(array) : []; + } + + /** + * This method is like `_.uniq` except that it accepts `iteratee` which is + * invoked for each element in `array` to generate the criterion by which + * uniqueness is computed. The order of result values is determined by the + * order they occur in the array. The iteratee is invoked with one argument: + * (value). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {Array} array The array to inspect. + * @param {Function} [iteratee=_.identity] The iteratee invoked per element. + * @returns {Array} Returns the new duplicate free array. + * @example + * + * _.uniqBy([2.1, 1.2, 2.3], Math.floor); + * // => [2.1, 1.2] + * + * // The `_.property` iteratee shorthand. + * _.uniqBy([{ 'x': 1 }, { 'x': 2 }, { 'x': 1 }], 'x'); + * // => [{ 'x': 1 }, { 'x': 2 }] + */ + function uniqBy(array, iteratee) { + return (array && array.length) ? baseUniq(array, getIteratee(iteratee, 2)) : []; + } + + /** + * This method is like `_.uniq` except that it accepts `comparator` which + * is invoked to compare elements of `array`. The order of result values is + * determined by the order they occur in the array.The comparator is invoked + * with two arguments: (arrVal, othVal). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {Array} array The array to inspect. + * @param {Function} [comparator] The comparator invoked per element. + * @returns {Array} Returns the new duplicate free array. + * @example + * + * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }, { 'x': 1, 'y': 2 }]; + * + * _.uniqWith(objects, _.isEqual); + * // => [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }] + */ + function uniqWith(array, comparator) { + comparator = typeof comparator == 'function' ? comparator : undefined; + return (array && array.length) ? baseUniq(array, undefined, comparator) : []; + } + + /** + * This method is like `_.zip` except that it accepts an array of grouped + * elements and creates an array regrouping the elements to their pre-zip + * configuration. + * + * @static + * @memberOf _ + * @since 1.2.0 + * @category Array + * @param {Array} array The array of grouped elements to process. + * @returns {Array} Returns the new array of regrouped elements. + * @example + * + * var zipped = _.zip(['a', 'b'], [1, 2], [true, false]); + * // => [['a', 1, true], ['b', 2, false]] + * + * _.unzip(zipped); + * // => [['a', 'b'], [1, 2], [true, false]] + */ + function unzip(array) { + if (!(array && array.length)) { + return []; + } + var length = 0; + array = arrayFilter(array, function(group) { + if (isArrayLikeObject(group)) { + length = nativeMax(group.length, length); + return true; + } + }); + return baseTimes(length, function(index) { + return arrayMap(array, baseProperty(index)); + }); + } + + /** + * This method is like `_.unzip` except that it accepts `iteratee` to specify + * how regrouped values should be combined. The iteratee is invoked with the + * elements of each group: (...group). + * + * @static + * @memberOf _ + * @since 3.8.0 + * @category Array + * @param {Array} array The array of grouped elements to process. + * @param {Function} [iteratee=_.identity] The function to combine + * regrouped values. + * @returns {Array} Returns the new array of regrouped elements. + * @example + * + * var zipped = _.zip([1, 2], [10, 20], [100, 200]); + * // => [[1, 10, 100], [2, 20, 200]] + * + * _.unzipWith(zipped, _.add); + * // => [3, 30, 300] + */ + function unzipWith(array, iteratee) { + if (!(array && array.length)) { + return []; + } + var result = unzip(array); + if (iteratee == null) { + return result; + } + return arrayMap(result, function(group) { + return apply(iteratee, undefined, group); + }); + } + + /** + * Creates an array excluding all given values using + * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) + * for equality comparisons. + * + * **Note:** Unlike `_.pull`, this method returns a new array. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Array + * @param {Array} array The array to inspect. + * @param {...*} [values] The values to exclude. + * @returns {Array} Returns the new array of filtered values. + * @see _.difference, _.xor + * @example + * + * _.without([2, 1, 2, 3], 1, 2); + * // => [3] + */ + var without = baseRest(function(array, values) { + return isArrayLikeObject(array) + ? baseDifference(array, values) + : []; + }); + + /** + * Creates an array of unique values that is the + * [symmetric difference](https://en.wikipedia.org/wiki/Symmetric_difference) + * of the given arrays. The order of result values is determined by the order + * they occur in the arrays. + * + * @static + * @memberOf _ + * @since 2.4.0 + * @category Array + * @param {...Array} [arrays] The arrays to inspect. + * @returns {Array} Returns the new array of filtered values. + * @see _.difference, _.without + * @example + * + * _.xor([2, 1], [2, 3]); + * // => [1, 3] + */ + var xor = baseRest(function(arrays) { + return baseXor(arrayFilter(arrays, isArrayLikeObject)); + }); + + /** + * This method is like `_.xor` except that it accepts `iteratee` which is + * invoked for each element of each `arrays` to generate the criterion by + * which by which they're compared. The order of result values is determined + * by the order they occur in the arrays. The iteratee is invoked with one + * argument: (value). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {...Array} [arrays] The arrays to inspect. + * @param {Function} [iteratee=_.identity] The iteratee invoked per element. + * @returns {Array} Returns the new array of filtered values. + * @example + * + * _.xorBy([2.1, 1.2], [2.3, 3.4], Math.floor); + * // => [1.2, 3.4] + * + * // The `_.property` iteratee shorthand. + * _.xorBy([{ 'x': 1 }], [{ 'x': 2 }, { 'x': 1 }], 'x'); + * // => [{ 'x': 2 }] + */ + var xorBy = baseRest(function(arrays) { + var iteratee = last(arrays); + if (isArrayLikeObject(iteratee)) { + iteratee = undefined; + } + return baseXor(arrayFilter(arrays, isArrayLikeObject), getIteratee(iteratee, 2)); + }); + + /** + * This method is like `_.xor` except that it accepts `comparator` which is + * invoked to compare elements of `arrays`. The order of result values is + * determined by the order they occur in the arrays. The comparator is invoked + * with two arguments: (arrVal, othVal). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {...Array} [arrays] The arrays to inspect. + * @param {Function} [comparator] The comparator invoked per element. + * @returns {Array} Returns the new array of filtered values. + * @example + * + * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }]; + * var others = [{ 'x': 1, 'y': 1 }, { 'x': 1, 'y': 2 }]; + * + * _.xorWith(objects, others, _.isEqual); + * // => [{ 'x': 2, 'y': 1 }, { 'x': 1, 'y': 1 }] + */ + var xorWith = baseRest(function(arrays) { + var comparator = last(arrays); + comparator = typeof comparator == 'function' ? comparator : undefined; + return baseXor(arrayFilter(arrays, isArrayLikeObject), undefined, comparator); + }); + + /** + * Creates an array of grouped elements, the first of which contains the + * first elements of the given arrays, the second of which contains the + * second elements of the given arrays, and so on. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Array + * @param {...Array} [arrays] The arrays to process. + * @returns {Array} Returns the new array of grouped elements. + * @example + * + * _.zip(['a', 'b'], [1, 2], [true, false]); + * // => [['a', 1, true], ['b', 2, false]] + */ + var zip = baseRest(unzip); + + /** + * This method is like `_.fromPairs` except that it accepts two arrays, + * one of property identifiers and one of corresponding values. + * + * @static + * @memberOf _ + * @since 0.4.0 + * @category Array + * @param {Array} [props=[]] The property identifiers. + * @param {Array} [values=[]] The property values. + * @returns {Object} Returns the new object. + * @example + * + * _.zipObject(['a', 'b'], [1, 2]); + * // => { 'a': 1, 'b': 2 } + */ + function zipObject(props, values) { + return baseZipObject(props || [], values || [], assignValue); + } + + /** + * This method is like `_.zipObject` except that it supports property paths. + * + * @static + * @memberOf _ + * @since 4.1.0 + * @category Array + * @param {Array} [props=[]] The property identifiers. + * @param {Array} [values=[]] The property values. + * @returns {Object} Returns the new object. + * @example + * + * _.zipObjectDeep(['a.b[0].c', 'a.b[1].d'], [1, 2]); + * // => { 'a': { 'b': [{ 'c': 1 }, { 'd': 2 }] } } + */ + function zipObjectDeep(props, values) { + return baseZipObject(props || [], values || [], baseSet); + } + + /** + * This method is like `_.zip` except that it accepts `iteratee` to specify + * how grouped values should be combined. The iteratee is invoked with the + * elements of each group: (...group). + * + * @static + * @memberOf _ + * @since 3.8.0 + * @category Array + * @param {...Array} [arrays] The arrays to process. + * @param {Function} [iteratee=_.identity] The function to combine + * grouped values. + * @returns {Array} Returns the new array of grouped elements. + * @example + * + * _.zipWith([1, 2], [10, 20], [100, 200], function(a, b, c) { + * return a + b + c; + * }); + * // => [111, 222] + */ + var zipWith = baseRest(function(arrays) { + var length = arrays.length, + iteratee = length > 1 ? arrays[length - 1] : undefined; + + iteratee = typeof iteratee == 'function' ? (arrays.pop(), iteratee) : undefined; + return unzipWith(arrays, iteratee); + }); + + /*------------------------------------------------------------------------*/ + + /** + * Creates a `lodash` wrapper instance that wraps `value` with explicit method + * chain sequences enabled. The result of such sequences must be unwrapped + * with `_#value`. + * + * @static + * @memberOf _ + * @since 1.3.0 + * @category Seq + * @param {*} value The value to wrap. + * @returns {Object} Returns the new `lodash` wrapper instance. + * @example + * + * var users = [ + * { 'user': 'barney', 'age': 36 }, + * { 'user': 'fred', 'age': 40 }, + * { 'user': 'pebbles', 'age': 1 } + * ]; + * + * var youngest = _ + * .chain(users) + * .sortBy('age') + * .map(function(o) { + * return o.user + ' is ' + o.age; + * }) + * .head() + * .value(); + * // => 'pebbles is 1' + */ + function chain(value) { + var result = lodash(value); + result.__chain__ = true; + return result; + } + + /** + * This method invokes `interceptor` and returns `value`. The interceptor + * is invoked with one argument; (value). The purpose of this method is to + * "tap into" a method chain sequence in order to modify intermediate results. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Seq + * @param {*} value The value to provide to `interceptor`. + * @param {Function} interceptor The function to invoke. + * @returns {*} Returns `value`. + * @example + * + * _([1, 2, 3]) + * .tap(function(array) { + * // Mutate input array. + * array.pop(); + * }) + * .reverse() + * .value(); + * // => [2, 1] + */ + function tap(value, interceptor) { + interceptor(value); + return value; + } + + /** + * This method is like `_.tap` except that it returns the result of `interceptor`. + * The purpose of this method is to "pass thru" values replacing intermediate + * results in a method chain sequence. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Seq + * @param {*} value The value to provide to `interceptor`. + * @param {Function} interceptor The function to invoke. + * @returns {*} Returns the result of `interceptor`. + * @example + * + * _(' abc ') + * .chain() + * .trim() + * .thru(function(value) { + * return [value]; + * }) + * .value(); + * // => ['abc'] + */ + function thru(value, interceptor) { + return interceptor(value); + } + + /** + * This method is the wrapper version of `_.at`. + * + * @name at + * @memberOf _ + * @since 1.0.0 + * @category Seq + * @param {...(string|string[])} [paths] The property paths to pick. + * @returns {Object} Returns the new `lodash` wrapper instance. + * @example + * + * var object = { 'a': [{ 'b': { 'c': 3 } }, 4] }; + * + * _(object).at(['a[0].b.c', 'a[1]']).value(); + * // => [3, 4] + */ + var wrapperAt = flatRest(function(paths) { + var length = paths.length, + start = length ? paths[0] : 0, + value = this.__wrapped__, + interceptor = function(object) { return baseAt(object, paths); }; + + if (length > 1 || this.__actions__.length || + !(value instanceof LazyWrapper) || !isIndex(start)) { + return this.thru(interceptor); + } + value = value.slice(start, +start + (length ? 1 : 0)); + value.__actions__.push({ + 'func': thru, + 'args': [interceptor], + 'thisArg': undefined + }); + return new LodashWrapper(value, this.__chain__).thru(function(array) { + if (length && !array.length) { + array.push(undefined); + } + return array; + }); + }); + + /** + * Creates a `lodash` wrapper instance with explicit method chain sequences enabled. + * + * @name chain + * @memberOf _ + * @since 0.1.0 + * @category Seq + * @returns {Object} Returns the new `lodash` wrapper instance. + * @example + * + * var users = [ + * { 'user': 'barney', 'age': 36 }, + * { 'user': 'fred', 'age': 40 } + * ]; + * + * // A sequence without explicit chaining. + * _(users).head(); + * // => { 'user': 'barney', 'age': 36 } + * + * // A sequence with explicit chaining. + * _(users) + * .chain() + * .head() + * .pick('user') + * .value(); + * // => { 'user': 'barney' } + */ + function wrapperChain() { + return chain(this); + } + + /** + * Executes the chain sequence and returns the wrapped result. + * + * @name commit + * @memberOf _ + * @since 3.2.0 + * @category Seq + * @returns {Object} Returns the new `lodash` wrapper instance. + * @example + * + * var array = [1, 2]; + * var wrapped = _(array).push(3); + * + * console.log(array); + * // => [1, 2] + * + * wrapped = wrapped.commit(); + * console.log(array); + * // => [1, 2, 3] + * + * wrapped.last(); + * // => 3 + * + * console.log(array); + * // => [1, 2, 3] + */ + function wrapperCommit() { + return new LodashWrapper(this.value(), this.__chain__); + } + + /** + * Gets the next value on a wrapped object following the + * [iterator protocol](https://mdn.io/iteration_protocols#iterator). + * + * @name next + * @memberOf _ + * @since 4.0.0 + * @category Seq + * @returns {Object} Returns the next iterator value. + * @example + * + * var wrapped = _([1, 2]); + * + * wrapped.next(); + * // => { 'done': false, 'value': 1 } + * + * wrapped.next(); + * // => { 'done': false, 'value': 2 } + * + * wrapped.next(); + * // => { 'done': true, 'value': undefined } + */ + function wrapperNext() { + if (this.__values__ === undefined) { + this.__values__ = toArray(this.value()); + } + var done = this.__index__ >= this.__values__.length, + value = done ? undefined : this.__values__[this.__index__++]; + + return { 'done': done, 'value': value }; + } + + /** + * Enables the wrapper to be iterable. + * + * @name Symbol.iterator + * @memberOf _ + * @since 4.0.0 + * @category Seq + * @returns {Object} Returns the wrapper object. + * @example + * + * var wrapped = _([1, 2]); + * + * wrapped[Symbol.iterator]() === wrapped; + * // => true + * + * Array.from(wrapped); + * // => [1, 2] + */ + function wrapperToIterator() { + return this; + } + + /** + * Creates a clone of the chain sequence planting `value` as the wrapped value. + * + * @name plant + * @memberOf _ + * @since 3.2.0 + * @category Seq + * @param {*} value The value to plant. + * @returns {Object} Returns the new `lodash` wrapper instance. + * @example + * + * function square(n) { + * return n * n; + * } + * + * var wrapped = _([1, 2]).map(square); + * var other = wrapped.plant([3, 4]); + * + * other.value(); + * // => [9, 16] + * + * wrapped.value(); + * // => [1, 4] + */ + function wrapperPlant(value) { + var result, + parent = this; + + while (parent instanceof baseLodash) { + var clone = wrapperClone(parent); + clone.__index__ = 0; + clone.__values__ = undefined; + if (result) { + previous.__wrapped__ = clone; + } else { + result = clone; + } + var previous = clone; + parent = parent.__wrapped__; + } + previous.__wrapped__ = value; + return result; + } + + /** + * This method is the wrapper version of `_.reverse`. + * + * **Note:** This method mutates the wrapped array. + * + * @name reverse + * @memberOf _ + * @since 0.1.0 + * @category Seq + * @returns {Object} Returns the new `lodash` wrapper instance. + * @example + * + * var array = [1, 2, 3]; + * + * _(array).reverse().value() + * // => [3, 2, 1] + * + * console.log(array); + * // => [3, 2, 1] + */ + function wrapperReverse() { + var value = this.__wrapped__; + if (value instanceof LazyWrapper) { + var wrapped = value; + if (this.__actions__.length) { + wrapped = new LazyWrapper(this); + } + wrapped = wrapped.reverse(); + wrapped.__actions__.push({ + 'func': thru, + 'args': [reverse], + 'thisArg': undefined + }); + return new LodashWrapper(wrapped, this.__chain__); + } + return this.thru(reverse); + } + + /** + * Executes the chain sequence to resolve the unwrapped value. + * + * @name value + * @memberOf _ + * @since 0.1.0 + * @alias toJSON, valueOf + * @category Seq + * @returns {*} Returns the resolved unwrapped value. + * @example + * + * _([1, 2, 3]).value(); + * // => [1, 2, 3] + */ + function wrapperValue() { + return baseWrapperValue(this.__wrapped__, this.__actions__); + } + + /*------------------------------------------------------------------------*/ + + /** + * Creates an object composed of keys generated from the results of running + * each element of `collection` thru `iteratee`. The corresponding value of + * each key is the number of times the key was returned by `iteratee`. The + * iteratee is invoked with one argument: (value). + * + * @static + * @memberOf _ + * @since 0.5.0 + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} [iteratee=_.identity] The iteratee to transform keys. + * @returns {Object} Returns the composed aggregate object. + * @example + * + * _.countBy([6.1, 4.2, 6.3], Math.floor); + * // => { '4': 1, '6': 2 } + * + * // The `_.property` iteratee shorthand. + * _.countBy(['one', 'two', 'three'], 'length'); + * // => { '3': 2, '5': 1 } + */ + var countBy = createAggregator(function(result, value, key) { + if (hasOwnProperty.call(result, key)) { + ++result[key]; + } else { + baseAssignValue(result, key, 1); + } + }); + + /** + * Checks if `predicate` returns truthy for **all** elements of `collection`. + * Iteration is stopped once `predicate` returns falsey. The predicate is + * invoked with three arguments: (value, index|key, collection). + * + * **Note:** This method returns `true` for + * [empty collections](https://en.wikipedia.org/wiki/Empty_set) because + * [everything is true](https://en.wikipedia.org/wiki/Vacuous_truth) of + * elements of empty collections. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} [predicate=_.identity] The function invoked per iteration. + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. + * @returns {boolean} Returns `true` if all elements pass the predicate check, + * else `false`. + * @example + * + * _.every([true, 1, null, 'yes'], Boolean); + * // => false + * + * var users = [ + * { 'user': 'barney', 'age': 36, 'active': false }, + * { 'user': 'fred', 'age': 40, 'active': false } + * ]; + * + * // The `_.matches` iteratee shorthand. + * _.every(users, { 'user': 'barney', 'active': false }); + * // => false + * + * // The `_.matchesProperty` iteratee shorthand. + * _.every(users, ['active', false]); + * // => true + * + * // The `_.property` iteratee shorthand. + * _.every(users, 'active'); + * // => false + */ + function every(collection, predicate, guard) { + var func = isArray(collection) ? arrayEvery : baseEvery; + if (guard && isIterateeCall(collection, predicate, guard)) { + predicate = undefined; + } + return func(collection, getIteratee(predicate, 3)); + } + + /** + * Iterates over elements of `collection`, returning an array of all elements + * `predicate` returns truthy for. The predicate is invoked with three + * arguments: (value, index|key, collection). + * + * **Note:** Unlike `_.remove`, this method returns a new array. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} [predicate=_.identity] The function invoked per iteration. + * @returns {Array} Returns the new filtered array. + * @see _.reject + * @example + * + * var users = [ + * { 'user': 'barney', 'age': 36, 'active': true }, + * { 'user': 'fred', 'age': 40, 'active': false } + * ]; + * + * _.filter(users, function(o) { return !o.active; }); + * // => objects for ['fred'] + * + * // The `_.matches` iteratee shorthand. + * _.filter(users, { 'age': 36, 'active': true }); + * // => objects for ['barney'] + * + * // The `_.matchesProperty` iteratee shorthand. + * _.filter(users, ['active', false]); + * // => objects for ['fred'] + * + * // The `_.property` iteratee shorthand. + * _.filter(users, 'active'); + * // => objects for ['barney'] + * + * // Combining several predicates using `_.overEvery` or `_.overSome`. + * _.filter(users, _.overSome([{ 'age': 36 }, ['age', 40]])); + * // => objects for ['fred', 'barney'] + */ + function filter(collection, predicate) { + var func = isArray(collection) ? arrayFilter : baseFilter; + return func(collection, getIteratee(predicate, 3)); + } + + /** + * Iterates over elements of `collection`, returning the first element + * `predicate` returns truthy for. The predicate is invoked with three + * arguments: (value, index|key, collection). + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Collection + * @param {Array|Object} collection The collection to inspect. + * @param {Function} [predicate=_.identity] The function invoked per iteration. + * @param {number} [fromIndex=0] The index to search from. + * @returns {*} Returns the matched element, else `undefined`. + * @example + * + * var users = [ + * { 'user': 'barney', 'age': 36, 'active': true }, + * { 'user': 'fred', 'age': 40, 'active': false }, + * { 'user': 'pebbles', 'age': 1, 'active': true } + * ]; + * + * _.find(users, function(o) { return o.age < 40; }); + * // => object for 'barney' + * + * // The `_.matches` iteratee shorthand. + * _.find(users, { 'age': 1, 'active': true }); + * // => object for 'pebbles' + * + * // The `_.matchesProperty` iteratee shorthand. + * _.find(users, ['active', false]); + * // => object for 'fred' + * + * // The `_.property` iteratee shorthand. + * _.find(users, 'active'); + * // => object for 'barney' + */ + var find = createFind(findIndex); + + /** + * This method is like `_.find` except that it iterates over elements of + * `collection` from right to left. + * + * @static + * @memberOf _ + * @since 2.0.0 + * @category Collection + * @param {Array|Object} collection The collection to inspect. + * @param {Function} [predicate=_.identity] The function invoked per iteration. + * @param {number} [fromIndex=collection.length-1] The index to search from. + * @returns {*} Returns the matched element, else `undefined`. + * @example + * + * _.findLast([1, 2, 3, 4], function(n) { + * return n % 2 == 1; + * }); + * // => 3 + */ + var findLast = createFind(findLastIndex); + + /** + * Creates a flattened array of values by running each element in `collection` + * thru `iteratee` and flattening the mapped results. The iteratee is invoked + * with three arguments: (value, index|key, collection). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. + * @returns {Array} Returns the new flattened array. + * @example + * + * function duplicate(n) { + * return [n, n]; + * } + * + * _.flatMap([1, 2], duplicate); + * // => [1, 1, 2, 2] + */ + function flatMap(collection, iteratee) { + return baseFlatten(map(collection, iteratee), 1); + } + + /** + * This method is like `_.flatMap` except that it recursively flattens the + * mapped results. + * + * @static + * @memberOf _ + * @since 4.7.0 + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. + * @returns {Array} Returns the new flattened array. + * @example + * + * function duplicate(n) { + * return [[[n, n]]]; + * } + * + * _.flatMapDeep([1, 2], duplicate); + * // => [1, 1, 2, 2] + */ + function flatMapDeep(collection, iteratee) { + return baseFlatten(map(collection, iteratee), INFINITY); + } + + /** + * This method is like `_.flatMap` except that it recursively flattens the + * mapped results up to `depth` times. + * + * @static + * @memberOf _ + * @since 4.7.0 + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. + * @param {number} [depth=1] The maximum recursion depth. + * @returns {Array} Returns the new flattened array. + * @example + * + * function duplicate(n) { + * return [[[n, n]]]; + * } + * + * _.flatMapDepth([1, 2], duplicate, 2); + * // => [[1, 1], [2, 2]] + */ + function flatMapDepth(collection, iteratee, depth) { + depth = depth === undefined ? 1 : toInteger(depth); + return baseFlatten(map(collection, iteratee), depth); + } + + /** + * Iterates over elements of `collection` and invokes `iteratee` for each element. + * The iteratee is invoked with three arguments: (value, index|key, collection). + * Iteratee functions may exit iteration early by explicitly returning `false`. + * + * **Note:** As with other "Collections" methods, objects with a "length" + * property are iterated like arrays. To avoid this behavior use `_.forIn` + * or `_.forOwn` for object iteration. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @alias each + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. + * @returns {Array|Object} Returns `collection`. + * @see _.forEachRight + * @example + * + * _.forEach([1, 2], function(value) { + * console.log(value); + * }); + * // => Logs `1` then `2`. + * + * _.forEach({ 'a': 1, 'b': 2 }, function(value, key) { + * console.log(key); + * }); + * // => Logs 'a' then 'b' (iteration order is not guaranteed). + */ + function forEach(collection, iteratee) { + var func = isArray(collection) ? arrayEach : baseEach; + return func(collection, getIteratee(iteratee, 3)); + } + + /** + * This method is like `_.forEach` except that it iterates over elements of + * `collection` from right to left. + * + * @static + * @memberOf _ + * @since 2.0.0 + * @alias eachRight + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. + * @returns {Array|Object} Returns `collection`. + * @see _.forEach + * @example + * + * _.forEachRight([1, 2], function(value) { + * console.log(value); + * }); + * // => Logs `2` then `1`. + */ + function forEachRight(collection, iteratee) { + var func = isArray(collection) ? arrayEachRight : baseEachRight; + return func(collection, getIteratee(iteratee, 3)); + } + + /** + * Creates an object composed of keys generated from the results of running + * each element of `collection` thru `iteratee`. The order of grouped values + * is determined by the order they occur in `collection`. The corresponding + * value of each key is an array of elements responsible for generating the + * key. The iteratee is invoked with one argument: (value). + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} [iteratee=_.identity] The iteratee to transform keys. + * @returns {Object} Returns the composed aggregate object. + * @example + * + * _.groupBy([6.1, 4.2, 6.3], Math.floor); + * // => { '4': [4.2], '6': [6.1, 6.3] } + * + * // The `_.property` iteratee shorthand. + * _.groupBy(['one', 'two', 'three'], 'length'); + * // => { '3': ['one', 'two'], '5': ['three'] } + */ + var groupBy = createAggregator(function(result, value, key) { + if (hasOwnProperty.call(result, key)) { + result[key].push(value); + } else { + baseAssignValue(result, key, [value]); + } + }); + + /** + * Checks if `value` is in `collection`. If `collection` is a string, it's + * checked for a substring of `value`, otherwise + * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) + * is used for equality comparisons. If `fromIndex` is negative, it's used as + * the offset from the end of `collection`. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Collection + * @param {Array|Object|string} collection The collection to inspect. + * @param {*} value The value to search for. + * @param {number} [fromIndex=0] The index to search from. + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.reduce`. + * @returns {boolean} Returns `true` if `value` is found, else `false`. + * @example + * + * _.includes([1, 2, 3], 1); + * // => true + * + * _.includes([1, 2, 3], 1, 2); + * // => false + * + * _.includes({ 'a': 1, 'b': 2 }, 1); + * // => true + * + * _.includes('abcd', 'bc'); + * // => true + */ + function includes(collection, value, fromIndex, guard) { + collection = isArrayLike(collection) ? collection : values(collection); + fromIndex = (fromIndex && !guard) ? toInteger(fromIndex) : 0; + + var length = collection.length; + if (fromIndex < 0) { + fromIndex = nativeMax(length + fromIndex, 0); + } + return isString(collection) + ? (fromIndex <= length && collection.indexOf(value, fromIndex) > -1) + : (!!length && baseIndexOf(collection, value, fromIndex) > -1); + } + + /** + * Invokes the method at `path` of each element in `collection`, returning + * an array of the results of each invoked method. Any additional arguments + * are provided to each invoked method. If `path` is a function, it's invoked + * for, and `this` bound to, each element in `collection`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Array|Function|string} path The path of the method to invoke or + * the function invoked per iteration. + * @param {...*} [args] The arguments to invoke each method with. + * @returns {Array} Returns the array of results. + * @example + * + * _.invokeMap([[5, 1, 7], [3, 2, 1]], 'sort'); + * // => [[1, 5, 7], [1, 2, 3]] + * + * _.invokeMap([123, 456], String.prototype.split, ''); + * // => [['1', '2', '3'], ['4', '5', '6']] + */ + var invokeMap = baseRest(function(collection, path, args) { + var index = -1, + isFunc = typeof path == 'function', + result = isArrayLike(collection) ? Array(collection.length) : []; + + baseEach(collection, function(value) { + result[++index] = isFunc ? apply(path, value, args) : baseInvoke(value, path, args); + }); + return result; + }); + + /** + * Creates an object composed of keys generated from the results of running + * each element of `collection` thru `iteratee`. The corresponding value of + * each key is the last element responsible for generating the key. The + * iteratee is invoked with one argument: (value). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} [iteratee=_.identity] The iteratee to transform keys. + * @returns {Object} Returns the composed aggregate object. + * @example + * + * var array = [ + * { 'dir': 'left', 'code': 97 }, + * { 'dir': 'right', 'code': 100 } + * ]; + * + * _.keyBy(array, function(o) { + * return String.fromCharCode(o.code); + * }); + * // => { 'a': { 'dir': 'left', 'code': 97 }, 'd': { 'dir': 'right', 'code': 100 } } + * + * _.keyBy(array, 'dir'); + * // => { 'left': { 'dir': 'left', 'code': 97 }, 'right': { 'dir': 'right', 'code': 100 } } + */ + var keyBy = createAggregator(function(result, value, key) { + baseAssignValue(result, key, value); + }); + + /** + * Creates an array of values by running each element in `collection` thru + * `iteratee`. The iteratee is invoked with three arguments: + * (value, index|key, collection). + * + * Many lodash methods are guarded to work as iteratees for methods like + * `_.every`, `_.filter`, `_.map`, `_.mapValues`, `_.reject`, and `_.some`. + * + * The guarded methods are: + * `ary`, `chunk`, `curry`, `curryRight`, `drop`, `dropRight`, `every`, + * `fill`, `invert`, `parseInt`, `random`, `range`, `rangeRight`, `repeat`, + * `sampleSize`, `slice`, `some`, `sortBy`, `split`, `take`, `takeRight`, + * `template`, `trim`, `trimEnd`, `trimStart`, and `words` + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. + * @returns {Array} Returns the new mapped array. + * @example + * + * function square(n) { + * return n * n; + * } + * + * _.map([4, 8], square); + * // => [16, 64] + * + * _.map({ 'a': 4, 'b': 8 }, square); + * // => [16, 64] (iteration order is not guaranteed) + * + * var users = [ + * { 'user': 'barney' }, + * { 'user': 'fred' } + * ]; + * + * // The `_.property` iteratee shorthand. + * _.map(users, 'user'); + * // => ['barney', 'fred'] + */ + function map(collection, iteratee) { + var func = isArray(collection) ? arrayMap : baseMap; + return func(collection, getIteratee(iteratee, 3)); + } + + /** + * This method is like `_.sortBy` except that it allows specifying the sort + * orders of the iteratees to sort by. If `orders` is unspecified, all values + * are sorted in ascending order. Otherwise, specify an order of "desc" for + * descending or "asc" for ascending sort order of corresponding values. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Array[]|Function[]|Object[]|string[]} [iteratees=[_.identity]] + * The iteratees to sort by. + * @param {string[]} [orders] The sort orders of `iteratees`. + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.reduce`. + * @returns {Array} Returns the new sorted array. + * @example + * + * var users = [ + * { 'user': 'fred', 'age': 48 }, + * { 'user': 'barney', 'age': 34 }, + * { 'user': 'fred', 'age': 40 }, + * { 'user': 'barney', 'age': 36 } + * ]; + * + * // Sort by `user` in ascending order and by `age` in descending order. + * _.orderBy(users, ['user', 'age'], ['asc', 'desc']); + * // => objects for [['barney', 36], ['barney', 34], ['fred', 48], ['fred', 40]] + */ + function orderBy(collection, iteratees, orders, guard) { + if (collection == null) { + return []; + } + if (!isArray(iteratees)) { + iteratees = iteratees == null ? [] : [iteratees]; + } + orders = guard ? undefined : orders; + if (!isArray(orders)) { + orders = orders == null ? [] : [orders]; + } + return baseOrderBy(collection, iteratees, orders); + } + + /** + * Creates an array of elements split into two groups, the first of which + * contains elements `predicate` returns truthy for, the second of which + * contains elements `predicate` returns falsey for. The predicate is + * invoked with one argument: (value). + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} [predicate=_.identity] The function invoked per iteration. + * @returns {Array} Returns the array of grouped elements. + * @example + * + * var users = [ + * { 'user': 'barney', 'age': 36, 'active': false }, + * { 'user': 'fred', 'age': 40, 'active': true }, + * { 'user': 'pebbles', 'age': 1, 'active': false } + * ]; + * + * _.partition(users, function(o) { return o.active; }); + * // => objects for [['fred'], ['barney', 'pebbles']] + * + * // The `_.matches` iteratee shorthand. + * _.partition(users, { 'age': 1, 'active': false }); + * // => objects for [['pebbles'], ['barney', 'fred']] + * + * // The `_.matchesProperty` iteratee shorthand. + * _.partition(users, ['active', false]); + * // => objects for [['barney', 'pebbles'], ['fred']] + * + * // The `_.property` iteratee shorthand. + * _.partition(users, 'active'); + * // => objects for [['fred'], ['barney', 'pebbles']] + */ + var partition = createAggregator(function(result, value, key) { + result[key ? 0 : 1].push(value); + }, function() { return [[], []]; }); + + /** + * Reduces `collection` to a value which is the accumulated result of running + * each element in `collection` thru `iteratee`, where each successive + * invocation is supplied the return value of the previous. If `accumulator` + * is not given, the first element of `collection` is used as the initial + * value. The iteratee is invoked with four arguments: + * (accumulator, value, index|key, collection). + * + * Many lodash methods are guarded to work as iteratees for methods like + * `_.reduce`, `_.reduceRight`, and `_.transform`. + * + * The guarded methods are: + * `assign`, `defaults`, `defaultsDeep`, `includes`, `merge`, `orderBy`, + * and `sortBy` + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. + * @param {*} [accumulator] The initial value. + * @returns {*} Returns the accumulated value. + * @see _.reduceRight + * @example + * + * _.reduce([1, 2], function(sum, n) { + * return sum + n; + * }, 0); + * // => 3 + * + * _.reduce({ 'a': 1, 'b': 2, 'c': 1 }, function(result, value, key) { + * (result[value] || (result[value] = [])).push(key); + * return result; + * }, {}); + * // => { '1': ['a', 'c'], '2': ['b'] } (iteration order is not guaranteed) + */ + function reduce(collection, iteratee, accumulator) { + var func = isArray(collection) ? arrayReduce : baseReduce, + initAccum = arguments.length < 3; + + return func(collection, getIteratee(iteratee, 4), accumulator, initAccum, baseEach); + } + + /** + * This method is like `_.reduce` except that it iterates over elements of + * `collection` from right to left. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. + * @param {*} [accumulator] The initial value. + * @returns {*} Returns the accumulated value. + * @see _.reduce + * @example + * + * var array = [[0, 1], [2, 3], [4, 5]]; + * + * _.reduceRight(array, function(flattened, other) { + * return flattened.concat(other); + * }, []); + * // => [4, 5, 2, 3, 0, 1] + */ + function reduceRight(collection, iteratee, accumulator) { + var func = isArray(collection) ? arrayReduceRight : baseReduce, + initAccum = arguments.length < 3; + + return func(collection, getIteratee(iteratee, 4), accumulator, initAccum, baseEachRight); + } + + /** + * The opposite of `_.filter`; this method returns the elements of `collection` + * that `predicate` does **not** return truthy for. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} [predicate=_.identity] The function invoked per iteration. + * @returns {Array} Returns the new filtered array. + * @see _.filter + * @example + * + * var users = [ + * { 'user': 'barney', 'age': 36, 'active': false }, + * { 'user': 'fred', 'age': 40, 'active': true } + * ]; + * + * _.reject(users, function(o) { return !o.active; }); + * // => objects for ['fred'] + * + * // The `_.matches` iteratee shorthand. + * _.reject(users, { 'age': 40, 'active': true }); + * // => objects for ['barney'] + * + * // The `_.matchesProperty` iteratee shorthand. + * _.reject(users, ['active', false]); + * // => objects for ['fred'] + * + * // The `_.property` iteratee shorthand. + * _.reject(users, 'active'); + * // => objects for ['barney'] + */ + function reject(collection, predicate) { + var func = isArray(collection) ? arrayFilter : baseFilter; + return func(collection, negate(getIteratee(predicate, 3))); + } + + /** + * Gets a random element from `collection`. + * + * @static + * @memberOf _ + * @since 2.0.0 + * @category Collection + * @param {Array|Object} collection The collection to sample. + * @returns {*} Returns the random element. + * @example + * + * _.sample([1, 2, 3, 4]); + * // => 2 + */ + function sample(collection) { + var func = isArray(collection) ? arraySample : baseSample; + return func(collection); + } + + /** + * Gets `n` random elements at unique keys from `collection` up to the + * size of `collection`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Collection + * @param {Array|Object} collection The collection to sample. + * @param {number} [n=1] The number of elements to sample. + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. + * @returns {Array} Returns the random elements. + * @example + * + * _.sampleSize([1, 2, 3], 2); + * // => [3, 1] + * + * _.sampleSize([1, 2, 3], 4); + * // => [2, 3, 1] + */ + function sampleSize(collection, n, guard) { + if ((guard ? isIterateeCall(collection, n, guard) : n === undefined)) { + n = 1; + } else { + n = toInteger(n); + } + var func = isArray(collection) ? arraySampleSize : baseSampleSize; + return func(collection, n); + } + + /** + * Creates an array of shuffled values, using a version of the + * [Fisher-Yates shuffle](https://en.wikipedia.org/wiki/Fisher-Yates_shuffle). + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Collection + * @param {Array|Object} collection The collection to shuffle. + * @returns {Array} Returns the new shuffled array. + * @example + * + * _.shuffle([1, 2, 3, 4]); + * // => [4, 1, 3, 2] + */ + function shuffle(collection) { + var func = isArray(collection) ? arrayShuffle : baseShuffle; + return func(collection); + } + + /** + * Gets the size of `collection` by returning its length for array-like + * values or the number of own enumerable string keyed properties for objects. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Collection + * @param {Array|Object|string} collection The collection to inspect. + * @returns {number} Returns the collection size. + * @example + * + * _.size([1, 2, 3]); + * // => 3 + * + * _.size({ 'a': 1, 'b': 2 }); + * // => 2 + * + * _.size('pebbles'); + * // => 7 + */ + function size(collection) { + if (collection == null) { + return 0; + } + if (isArrayLike(collection)) { + return isString(collection) ? stringSize(collection) : collection.length; + } + var tag = getTag(collection); + if (tag == mapTag || tag == setTag) { + return collection.size; + } + return baseKeys(collection).length; + } + + /** + * Checks if `predicate` returns truthy for **any** element of `collection`. + * Iteration is stopped once `predicate` returns truthy. The predicate is + * invoked with three arguments: (value, index|key, collection). + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} [predicate=_.identity] The function invoked per iteration. + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. + * @returns {boolean} Returns `true` if any element passes the predicate check, + * else `false`. + * @example + * + * _.some([null, 0, 'yes', false], Boolean); + * // => true + * + * var users = [ + * { 'user': 'barney', 'active': true }, + * { 'user': 'fred', 'active': false } + * ]; + * + * // The `_.matches` iteratee shorthand. + * _.some(users, { 'user': 'barney', 'active': false }); + * // => false + * + * // The `_.matchesProperty` iteratee shorthand. + * _.some(users, ['active', false]); + * // => true + * + * // The `_.property` iteratee shorthand. + * _.some(users, 'active'); + * // => true + */ + function some(collection, predicate, guard) { + var func = isArray(collection) ? arraySome : baseSome; + if (guard && isIterateeCall(collection, predicate, guard)) { + predicate = undefined; + } + return func(collection, getIteratee(predicate, 3)); + } + + /** + * Creates an array of elements, sorted in ascending order by the results of + * running each element in a collection thru each iteratee. This method + * performs a stable sort, that is, it preserves the original sort order of + * equal elements. The iteratees are invoked with one argument: (value). + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {...(Function|Function[])} [iteratees=[_.identity]] + * The iteratees to sort by. + * @returns {Array} Returns the new sorted array. + * @example + * + * var users = [ + * { 'user': 'fred', 'age': 48 }, + * { 'user': 'barney', 'age': 36 }, + * { 'user': 'fred', 'age': 30 }, + * { 'user': 'barney', 'age': 34 } + * ]; + * + * _.sortBy(users, [function(o) { return o.user; }]); + * // => objects for [['barney', 36], ['barney', 34], ['fred', 48], ['fred', 30]] + * + * _.sortBy(users, ['user', 'age']); + * // => objects for [['barney', 34], ['barney', 36], ['fred', 30], ['fred', 48]] + */ + var sortBy = baseRest(function(collection, iteratees) { + if (collection == null) { + return []; + } + var length = iteratees.length; + if (length > 1 && isIterateeCall(collection, iteratees[0], iteratees[1])) { + iteratees = []; + } else if (length > 2 && isIterateeCall(iteratees[0], iteratees[1], iteratees[2])) { + iteratees = [iteratees[0]]; + } + return baseOrderBy(collection, baseFlatten(iteratees, 1), []); + }); + + /*------------------------------------------------------------------------*/ + + /** + * Gets the timestamp of the number of milliseconds that have elapsed since + * the Unix epoch (1 January 1970 00:00:00 UTC). + * + * @static + * @memberOf _ + * @since 2.4.0 + * @category Date + * @returns {number} Returns the timestamp. + * @example + * + * _.defer(function(stamp) { + * console.log(_.now() - stamp); + * }, _.now()); + * // => Logs the number of milliseconds it took for the deferred invocation. + */ + var now = ctxNow || function() { + return root.Date.now(); + }; + + /*------------------------------------------------------------------------*/ + + /** + * The opposite of `_.before`; this method creates a function that invokes + * `func` once it's called `n` or more times. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Function + * @param {number} n The number of calls before `func` is invoked. + * @param {Function} func The function to restrict. + * @returns {Function} Returns the new restricted function. + * @example + * + * var saves = ['profile', 'settings']; + * + * var done = _.after(saves.length, function() { + * console.log('done saving!'); + * }); + * + * _.forEach(saves, function(type) { + * asyncSave({ 'type': type, 'complete': done }); + * }); + * // => Logs 'done saving!' after the two async saves have completed. + */ + function after(n, func) { + if (typeof func != 'function') { + throw new TypeError(FUNC_ERROR_TEXT); + } + n = toInteger(n); + return function() { + if (--n < 1) { + return func.apply(this, arguments); + } + }; + } + + /** + * Creates a function that invokes `func`, with up to `n` arguments, + * ignoring any additional arguments. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Function + * @param {Function} func The function to cap arguments for. + * @param {number} [n=func.length] The arity cap. + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. + * @returns {Function} Returns the new capped function. + * @example + * + * _.map(['6', '8', '10'], _.ary(parseInt, 1)); + * // => [6, 8, 10] + */ + function ary(func, n, guard) { + n = guard ? undefined : n; + n = (func && n == null) ? func.length : n; + return createWrap(func, WRAP_ARY_FLAG, undefined, undefined, undefined, undefined, n); + } + + /** + * Creates a function that invokes `func`, with the `this` binding and arguments + * of the created function, while it's called less than `n` times. Subsequent + * calls to the created function return the result of the last `func` invocation. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Function + * @param {number} n The number of calls at which `func` is no longer invoked. + * @param {Function} func The function to restrict. + * @returns {Function} Returns the new restricted function. + * @example + * + * jQuery(element).on('click', _.before(5, addContactToList)); + * // => Allows adding up to 4 contacts to the list. + */ + function before(n, func) { + var result; + if (typeof func != 'function') { + throw new TypeError(FUNC_ERROR_TEXT); + } + n = toInteger(n); + return function() { + if (--n > 0) { + result = func.apply(this, arguments); + } + if (n <= 1) { + func = undefined; + } + return result; + }; + } + + /** + * Creates a function that invokes `func` with the `this` binding of `thisArg` + * and `partials` prepended to the arguments it receives. + * + * The `_.bind.placeholder` value, which defaults to `_` in monolithic builds, + * may be used as a placeholder for partially applied arguments. + * + * **Note:** Unlike native `Function#bind`, this method doesn't set the "length" + * property of bound functions. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Function + * @param {Function} func The function to bind. + * @param {*} thisArg The `this` binding of `func`. + * @param {...*} [partials] The arguments to be partially applied. + * @returns {Function} Returns the new bound function. + * @example + * + * function greet(greeting, punctuation) { + * return greeting + ' ' + this.user + punctuation; + * } + * + * var object = { 'user': 'fred' }; + * + * var bound = _.bind(greet, object, 'hi'); + * bound('!'); + * // => 'hi fred!' + * + * // Bound with placeholders. + * var bound = _.bind(greet, object, _, '!'); + * bound('hi'); + * // => 'hi fred!' + */ + var bind = baseRest(function(func, thisArg, partials) { + var bitmask = WRAP_BIND_FLAG; + if (partials.length) { + var holders = replaceHolders(partials, getHolder(bind)); + bitmask |= WRAP_PARTIAL_FLAG; + } + return createWrap(func, bitmask, thisArg, partials, holders); + }); + + /** + * Creates a function that invokes the method at `object[key]` with `partials` + * prepended to the arguments it receives. + * + * This method differs from `_.bind` by allowing bound functions to reference + * methods that may be redefined or don't yet exist. See + * [Peter Michaux's article](http://peter.michaux.ca/articles/lazy-function-definition-pattern) + * for more details. + * + * The `_.bindKey.placeholder` value, which defaults to `_` in monolithic + * builds, may be used as a placeholder for partially applied arguments. + * + * @static + * @memberOf _ + * @since 0.10.0 + * @category Function + * @param {Object} object The object to invoke the method on. + * @param {string} key The key of the method. + * @param {...*} [partials] The arguments to be partially applied. + * @returns {Function} Returns the new bound function. + * @example + * + * var object = { + * 'user': 'fred', + * 'greet': function(greeting, punctuation) { + * return greeting + ' ' + this.user + punctuation; + * } + * }; + * + * var bound = _.bindKey(object, 'greet', 'hi'); + * bound('!'); + * // => 'hi fred!' + * + * object.greet = function(greeting, punctuation) { + * return greeting + 'ya ' + this.user + punctuation; + * }; + * + * bound('!'); + * // => 'hiya fred!' + * + * // Bound with placeholders. + * var bound = _.bindKey(object, 'greet', _, '!'); + * bound('hi'); + * // => 'hiya fred!' + */ + var bindKey = baseRest(function(object, key, partials) { + var bitmask = WRAP_BIND_FLAG | WRAP_BIND_KEY_FLAG; + if (partials.length) { + var holders = replaceHolders(partials, getHolder(bindKey)); + bitmask |= WRAP_PARTIAL_FLAG; + } + return createWrap(key, bitmask, object, partials, holders); + }); + + /** + * Creates a function that accepts arguments of `func` and either invokes + * `func` returning its result, if at least `arity` number of arguments have + * been provided, or returns a function that accepts the remaining `func` + * arguments, and so on. The arity of `func` may be specified if `func.length` + * is not sufficient. + * + * The `_.curry.placeholder` value, which defaults to `_` in monolithic builds, + * may be used as a placeholder for provided arguments. + * + * **Note:** This method doesn't set the "length" property of curried functions. + * + * @static + * @memberOf _ + * @since 2.0.0 + * @category Function + * @param {Function} func The function to curry. + * @param {number} [arity=func.length] The arity of `func`. + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. + * @returns {Function} Returns the new curried function. + * @example + * + * var abc = function(a, b, c) { + * return [a, b, c]; + * }; + * + * var curried = _.curry(abc); + * + * curried(1)(2)(3); + * // => [1, 2, 3] + * + * curried(1, 2)(3); + * // => [1, 2, 3] + * + * curried(1, 2, 3); + * // => [1, 2, 3] + * + * // Curried with placeholders. + * curried(1)(_, 3)(2); + * // => [1, 2, 3] + */ + function curry(func, arity, guard) { + arity = guard ? undefined : arity; + var result = createWrap(func, WRAP_CURRY_FLAG, undefined, undefined, undefined, undefined, undefined, arity); + result.placeholder = curry.placeholder; + return result; + } + + /** + * This method is like `_.curry` except that arguments are applied to `func` + * in the manner of `_.partialRight` instead of `_.partial`. + * + * The `_.curryRight.placeholder` value, which defaults to `_` in monolithic + * builds, may be used as a placeholder for provided arguments. + * + * **Note:** This method doesn't set the "length" property of curried functions. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Function + * @param {Function} func The function to curry. + * @param {number} [arity=func.length] The arity of `func`. + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. + * @returns {Function} Returns the new curried function. + * @example + * + * var abc = function(a, b, c) { + * return [a, b, c]; + * }; + * + * var curried = _.curryRight(abc); + * + * curried(3)(2)(1); + * // => [1, 2, 3] + * + * curried(2, 3)(1); + * // => [1, 2, 3] + * + * curried(1, 2, 3); + * // => [1, 2, 3] + * + * // Curried with placeholders. + * curried(3)(1, _)(2); + * // => [1, 2, 3] + */ + function curryRight(func, arity, guard) { + arity = guard ? undefined : arity; + var result = createWrap(func, WRAP_CURRY_RIGHT_FLAG, undefined, undefined, undefined, undefined, undefined, arity); + result.placeholder = curryRight.placeholder; + return result; + } + + /** + * Creates a debounced function that delays invoking `func` until after `wait` + * milliseconds have elapsed since the last time the debounced function was + * invoked. The debounced function comes with a `cancel` method to cancel + * delayed `func` invocations and a `flush` method to immediately invoke them. + * Provide `options` to indicate whether `func` should be invoked on the + * leading and/or trailing edge of the `wait` timeout. The `func` is invoked + * with the last arguments provided to the debounced function. Subsequent + * calls to the debounced function return the result of the last `func` + * invocation. + * + * **Note:** If `leading` and `trailing` options are `true`, `func` is + * invoked on the trailing edge of the timeout only if the debounced function + * is invoked more than once during the `wait` timeout. + * + * If `wait` is `0` and `leading` is `false`, `func` invocation is deferred + * until to the next tick, similar to `setTimeout` with a timeout of `0`. + * + * See [David Corbacho's article](https://css-tricks.com/debouncing-throttling-explained-examples/) + * for details over the differences between `_.debounce` and `_.throttle`. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Function + * @param {Function} func The function to debounce. + * @param {number} [wait=0] The number of milliseconds to delay. + * @param {Object} [options={}] The options object. + * @param {boolean} [options.leading=false] + * Specify invoking on the leading edge of the timeout. + * @param {number} [options.maxWait] + * The maximum time `func` is allowed to be delayed before it's invoked. + * @param {boolean} [options.trailing=true] + * Specify invoking on the trailing edge of the timeout. + * @returns {Function} Returns the new debounced function. + * @example + * + * // Avoid costly calculations while the window size is in flux. + * jQuery(window).on('resize', _.debounce(calculateLayout, 150)); + * + * // Invoke `sendMail` when clicked, debouncing subsequent calls. + * jQuery(element).on('click', _.debounce(sendMail, 300, { + * 'leading': true, + * 'trailing': false + * })); + * + * // Ensure `batchLog` is invoked once after 1 second of debounced calls. + * var debounced = _.debounce(batchLog, 250, { 'maxWait': 1000 }); + * var source = new EventSource('/stream'); + * jQuery(source).on('message', debounced); + * + * // Cancel the trailing debounced invocation. + * jQuery(window).on('popstate', debounced.cancel); + */ + function debounce(func, wait, options) { + var lastArgs, + lastThis, + maxWait, + result, + timerId, + lastCallTime, + lastInvokeTime = 0, + leading = false, + maxing = false, + trailing = true; + + if (typeof func != 'function') { + throw new TypeError(FUNC_ERROR_TEXT); + } + wait = toNumber(wait) || 0; + if (isObject(options)) { + leading = !!options.leading; + maxing = 'maxWait' in options; + maxWait = maxing ? nativeMax(toNumber(options.maxWait) || 0, wait) : maxWait; + trailing = 'trailing' in options ? !!options.trailing : trailing; + } + + function invokeFunc(time) { + var args = lastArgs, + thisArg = lastThis; + + lastArgs = lastThis = undefined; + lastInvokeTime = time; + result = func.apply(thisArg, args); + return result; + } + + function leadingEdge(time) { + // Reset any `maxWait` timer. + lastInvokeTime = time; + // Start the timer for the trailing edge. + timerId = setTimeout(timerExpired, wait); + // Invoke the leading edge. + return leading ? invokeFunc(time) : result; + } + + function remainingWait(time) { + var timeSinceLastCall = time - lastCallTime, + timeSinceLastInvoke = time - lastInvokeTime, + timeWaiting = wait - timeSinceLastCall; + + return maxing + ? nativeMin(timeWaiting, maxWait - timeSinceLastInvoke) + : timeWaiting; + } + + function shouldInvoke(time) { + var timeSinceLastCall = time - lastCallTime, + timeSinceLastInvoke = time - lastInvokeTime; + + // Either this is the first call, activity has stopped and we're at the + // trailing edge, the system time has gone backwards and we're treating + // it as the trailing edge, or we've hit the `maxWait` limit. + return (lastCallTime === undefined || (timeSinceLastCall >= wait) || + (timeSinceLastCall < 0) || (maxing && timeSinceLastInvoke >= maxWait)); + } + + function timerExpired() { + var time = now(); + if (shouldInvoke(time)) { + return trailingEdge(time); + } + // Restart the timer. + timerId = setTimeout(timerExpired, remainingWait(time)); + } + + function trailingEdge(time) { + timerId = undefined; + + // Only invoke if we have `lastArgs` which means `func` has been + // debounced at least once. + if (trailing && lastArgs) { + return invokeFunc(time); + } + lastArgs = lastThis = undefined; + return result; + } + + function cancel() { + if (timerId !== undefined) { + clearTimeout(timerId); + } + lastInvokeTime = 0; + lastArgs = lastCallTime = lastThis = timerId = undefined; + } + + function flush() { + return timerId === undefined ? result : trailingEdge(now()); + } + + function debounced() { + var time = now(), + isInvoking = shouldInvoke(time); + + lastArgs = arguments; + lastThis = this; + lastCallTime = time; + + if (isInvoking) { + if (timerId === undefined) { + return leadingEdge(lastCallTime); + } + if (maxing) { + // Handle invocations in a tight loop. + clearTimeout(timerId); + timerId = setTimeout(timerExpired, wait); + return invokeFunc(lastCallTime); + } + } + if (timerId === undefined) { + timerId = setTimeout(timerExpired, wait); + } + return result; + } + debounced.cancel = cancel; + debounced.flush = flush; + return debounced; + } + + /** + * Defers invoking the `func` until the current call stack has cleared. Any + * additional arguments are provided to `func` when it's invoked. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Function + * @param {Function} func The function to defer. + * @param {...*} [args] The arguments to invoke `func` with. + * @returns {number} Returns the timer id. + * @example + * + * _.defer(function(text) { + * console.log(text); + * }, 'deferred'); + * // => Logs 'deferred' after one millisecond. + */ + var defer = baseRest(function(func, args) { + return baseDelay(func, 1, args); + }); + + /** + * Invokes `func` after `wait` milliseconds. Any additional arguments are + * provided to `func` when it's invoked. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Function + * @param {Function} func The function to delay. + * @param {number} wait The number of milliseconds to delay invocation. + * @param {...*} [args] The arguments to invoke `func` with. + * @returns {number} Returns the timer id. + * @example + * + * _.delay(function(text) { + * console.log(text); + * }, 1000, 'later'); + * // => Logs 'later' after one second. + */ + var delay = baseRest(function(func, wait, args) { + return baseDelay(func, toNumber(wait) || 0, args); + }); + + /** + * Creates a function that invokes `func` with arguments reversed. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Function + * @param {Function} func The function to flip arguments for. + * @returns {Function} Returns the new flipped function. + * @example + * + * var flipped = _.flip(function() { + * return _.toArray(arguments); + * }); + * + * flipped('a', 'b', 'c', 'd'); + * // => ['d', 'c', 'b', 'a'] + */ + function flip(func) { + return createWrap(func, WRAP_FLIP_FLAG); + } + + /** + * Creates a function that memoizes the result of `func`. If `resolver` is + * provided, it determines the cache key for storing the result based on the + * arguments provided to the memoized function. By default, the first argument + * provided to the memoized function is used as the map cache key. The `func` + * is invoked with the `this` binding of the memoized function. + * + * **Note:** The cache is exposed as the `cache` property on the memoized + * function. Its creation may be customized by replacing the `_.memoize.Cache` + * constructor with one whose instances implement the + * [`Map`](http://ecma-international.org/ecma-262/7.0/#sec-properties-of-the-map-prototype-object) + * method interface of `clear`, `delete`, `get`, `has`, and `set`. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Function + * @param {Function} func The function to have its output memoized. + * @param {Function} [resolver] The function to resolve the cache key. + * @returns {Function} Returns the new memoized function. + * @example + * + * var object = { 'a': 1, 'b': 2 }; + * var other = { 'c': 3, 'd': 4 }; + * + * var values = _.memoize(_.values); + * values(object); + * // => [1, 2] + * + * values(other); + * // => [3, 4] + * + * object.a = 2; + * values(object); + * // => [1, 2] + * + * // Modify the result cache. + * values.cache.set(object, ['a', 'b']); + * values(object); + * // => ['a', 'b'] + * + * // Replace `_.memoize.Cache`. + * _.memoize.Cache = WeakMap; + */ + function memoize(func, resolver) { + if (typeof func != 'function' || (resolver != null && typeof resolver != 'function')) { + throw new TypeError(FUNC_ERROR_TEXT); + } + var memoized = function() { + var args = arguments, + key = resolver ? resolver.apply(this, args) : args[0], + cache = memoized.cache; + + if (cache.has(key)) { + return cache.get(key); + } + var result = func.apply(this, args); + memoized.cache = cache.set(key, result) || cache; + return result; + }; + memoized.cache = new (memoize.Cache || MapCache); + return memoized; + } + + // Expose `MapCache`. + memoize.Cache = MapCache; + + /** + * Creates a function that negates the result of the predicate `func`. The + * `func` predicate is invoked with the `this` binding and arguments of the + * created function. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Function + * @param {Function} predicate The predicate to negate. + * @returns {Function} Returns the new negated function. + * @example + * + * function isEven(n) { + * return n % 2 == 0; + * } + * + * _.filter([1, 2, 3, 4, 5, 6], _.negate(isEven)); + * // => [1, 3, 5] + */ + function negate(predicate) { + if (typeof predicate != 'function') { + throw new TypeError(FUNC_ERROR_TEXT); + } + return function() { + var args = arguments; + switch (args.length) { + case 0: return !predicate.call(this); + case 1: return !predicate.call(this, args[0]); + case 2: return !predicate.call(this, args[0], args[1]); + case 3: return !predicate.call(this, args[0], args[1], args[2]); + } + return !predicate.apply(this, args); + }; + } + + /** + * Creates a function that is restricted to invoking `func` once. Repeat calls + * to the function return the value of the first invocation. The `func` is + * invoked with the `this` binding and arguments of the created function. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Function + * @param {Function} func The function to restrict. + * @returns {Function} Returns the new restricted function. + * @example + * + * var initialize = _.once(createApplication); + * initialize(); + * initialize(); + * // => `createApplication` is invoked once + */ + function once(func) { + return before(2, func); + } + + /** + * Creates a function that invokes `func` with its arguments transformed. + * + * @static + * @since 4.0.0 + * @memberOf _ + * @category Function + * @param {Function} func The function to wrap. + * @param {...(Function|Function[])} [transforms=[_.identity]] + * The argument transforms. + * @returns {Function} Returns the new function. + * @example + * + * function doubled(n) { + * return n * 2; + * } + * + * function square(n) { + * return n * n; + * } + * + * var func = _.overArgs(function(x, y) { + * return [x, y]; + * }, [square, doubled]); + * + * func(9, 3); + * // => [81, 6] + * + * func(10, 5); + * // => [100, 10] + */ + var overArgs = castRest(function(func, transforms) { + transforms = (transforms.length == 1 && isArray(transforms[0])) + ? arrayMap(transforms[0], baseUnary(getIteratee())) + : arrayMap(baseFlatten(transforms, 1), baseUnary(getIteratee())); + + var funcsLength = transforms.length; + return baseRest(function(args) { + var index = -1, + length = nativeMin(args.length, funcsLength); + + while (++index < length) { + args[index] = transforms[index].call(this, args[index]); + } + return apply(func, this, args); + }); + }); + + /** + * Creates a function that invokes `func` with `partials` prepended to the + * arguments it receives. This method is like `_.bind` except it does **not** + * alter the `this` binding. + * + * The `_.partial.placeholder` value, which defaults to `_` in monolithic + * builds, may be used as a placeholder for partially applied arguments. + * + * **Note:** This method doesn't set the "length" property of partially + * applied functions. + * + * @static + * @memberOf _ + * @since 0.2.0 + * @category Function + * @param {Function} func The function to partially apply arguments to. + * @param {...*} [partials] The arguments to be partially applied. + * @returns {Function} Returns the new partially applied function. + * @example + * + * function greet(greeting, name) { + * return greeting + ' ' + name; + * } + * + * var sayHelloTo = _.partial(greet, 'hello'); + * sayHelloTo('fred'); + * // => 'hello fred' + * + * // Partially applied with placeholders. + * var greetFred = _.partial(greet, _, 'fred'); + * greetFred('hi'); + * // => 'hi fred' + */ + var partial = baseRest(function(func, partials) { + var holders = replaceHolders(partials, getHolder(partial)); + return createWrap(func, WRAP_PARTIAL_FLAG, undefined, partials, holders); + }); + + /** + * This method is like `_.partial` except that partially applied arguments + * are appended to the arguments it receives. + * + * The `_.partialRight.placeholder` value, which defaults to `_` in monolithic + * builds, may be used as a placeholder for partially applied arguments. + * + * **Note:** This method doesn't set the "length" property of partially + * applied functions. + * + * @static + * @memberOf _ + * @since 1.0.0 + * @category Function + * @param {Function} func The function to partially apply arguments to. + * @param {...*} [partials] The arguments to be partially applied. + * @returns {Function} Returns the new partially applied function. + * @example + * + * function greet(greeting, name) { + * return greeting + ' ' + name; + * } + * + * var greetFred = _.partialRight(greet, 'fred'); + * greetFred('hi'); + * // => 'hi fred' + * + * // Partially applied with placeholders. + * var sayHelloTo = _.partialRight(greet, 'hello', _); + * sayHelloTo('fred'); + * // => 'hello fred' + */ + var partialRight = baseRest(function(func, partials) { + var holders = replaceHolders(partials, getHolder(partialRight)); + return createWrap(func, WRAP_PARTIAL_RIGHT_FLAG, undefined, partials, holders); + }); + + /** + * Creates a function that invokes `func` with arguments arranged according + * to the specified `indexes` where the argument value at the first index is + * provided as the first argument, the argument value at the second index is + * provided as the second argument, and so on. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Function + * @param {Function} func The function to rearrange arguments for. + * @param {...(number|number[])} indexes The arranged argument indexes. + * @returns {Function} Returns the new function. + * @example + * + * var rearged = _.rearg(function(a, b, c) { + * return [a, b, c]; + * }, [2, 0, 1]); + * + * rearged('b', 'c', 'a') + * // => ['a', 'b', 'c'] + */ + var rearg = flatRest(function(func, indexes) { + return createWrap(func, WRAP_REARG_FLAG, undefined, undefined, undefined, indexes); + }); + + /** + * Creates a function that invokes `func` with the `this` binding of the + * created function and arguments from `start` and beyond provided as + * an array. + * + * **Note:** This method is based on the + * [rest parameter](https://mdn.io/rest_parameters). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Function + * @param {Function} func The function to apply a rest parameter to. + * @param {number} [start=func.length-1] The start position of the rest parameter. + * @returns {Function} Returns the new function. + * @example + * + * var say = _.rest(function(what, names) { + * return what + ' ' + _.initial(names).join(', ') + + * (_.size(names) > 1 ? ', & ' : '') + _.last(names); + * }); + * + * say('hello', 'fred', 'barney', 'pebbles'); + * // => 'hello fred, barney, & pebbles' + */ + function rest(func, start) { + if (typeof func != 'function') { + throw new TypeError(FUNC_ERROR_TEXT); + } + start = start === undefined ? start : toInteger(start); + return baseRest(func, start); + } + + /** + * Creates a function that invokes `func` with the `this` binding of the + * create function and an array of arguments much like + * [`Function#apply`](http://www.ecma-international.org/ecma-262/7.0/#sec-function.prototype.apply). + * + * **Note:** This method is based on the + * [spread operator](https://mdn.io/spread_operator). + * + * @static + * @memberOf _ + * @since 3.2.0 + * @category Function + * @param {Function} func The function to spread arguments over. + * @param {number} [start=0] The start position of the spread. + * @returns {Function} Returns the new function. + * @example + * + * var say = _.spread(function(who, what) { + * return who + ' says ' + what; + * }); + * + * say(['fred', 'hello']); + * // => 'fred says hello' + * + * var numbers = Promise.all([ + * Promise.resolve(40), + * Promise.resolve(36) + * ]); + * + * numbers.then(_.spread(function(x, y) { + * return x + y; + * })); + * // => a Promise of 76 + */ + function spread(func, start) { + if (typeof func != 'function') { + throw new TypeError(FUNC_ERROR_TEXT); + } + start = start == null ? 0 : nativeMax(toInteger(start), 0); + return baseRest(function(args) { + var array = args[start], + otherArgs = castSlice(args, 0, start); + + if (array) { + arrayPush(otherArgs, array); + } + return apply(func, this, otherArgs); + }); + } + + /** + * Creates a throttled function that only invokes `func` at most once per + * every `wait` milliseconds. The throttled function comes with a `cancel` + * method to cancel delayed `func` invocations and a `flush` method to + * immediately invoke them. Provide `options` to indicate whether `func` + * should be invoked on the leading and/or trailing edge of the `wait` + * timeout. The `func` is invoked with the last arguments provided to the + * throttled function. Subsequent calls to the throttled function return the + * result of the last `func` invocation. + * + * **Note:** If `leading` and `trailing` options are `true`, `func` is + * invoked on the trailing edge of the timeout only if the throttled function + * is invoked more than once during the `wait` timeout. + * + * If `wait` is `0` and `leading` is `false`, `func` invocation is deferred + * until to the next tick, similar to `setTimeout` with a timeout of `0`. + * + * See [David Corbacho's article](https://css-tricks.com/debouncing-throttling-explained-examples/) + * for details over the differences between `_.throttle` and `_.debounce`. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Function + * @param {Function} func The function to throttle. + * @param {number} [wait=0] The number of milliseconds to throttle invocations to. + * @param {Object} [options={}] The options object. + * @param {boolean} [options.leading=true] + * Specify invoking on the leading edge of the timeout. + * @param {boolean} [options.trailing=true] + * Specify invoking on the trailing edge of the timeout. + * @returns {Function} Returns the new throttled function. + * @example + * + * // Avoid excessively updating the position while scrolling. + * jQuery(window).on('scroll', _.throttle(updatePosition, 100)); + * + * // Invoke `renewToken` when the click event is fired, but not more than once every 5 minutes. + * var throttled = _.throttle(renewToken, 300000, { 'trailing': false }); + * jQuery(element).on('click', throttled); + * + * // Cancel the trailing throttled invocation. + * jQuery(window).on('popstate', throttled.cancel); + */ + function throttle(func, wait, options) { + var leading = true, + trailing = true; + + if (typeof func != 'function') { + throw new TypeError(FUNC_ERROR_TEXT); + } + if (isObject(options)) { + leading = 'leading' in options ? !!options.leading : leading; + trailing = 'trailing' in options ? !!options.trailing : trailing; + } + return debounce(func, wait, { + 'leading': leading, + 'maxWait': wait, + 'trailing': trailing + }); + } + + /** + * Creates a function that accepts up to one argument, ignoring any + * additional arguments. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Function + * @param {Function} func The function to cap arguments for. + * @returns {Function} Returns the new capped function. + * @example + * + * _.map(['6', '8', '10'], _.unary(parseInt)); + * // => [6, 8, 10] + */ + function unary(func) { + return ary(func, 1); + } + + /** + * Creates a function that provides `value` to `wrapper` as its first + * argument. Any additional arguments provided to the function are appended + * to those provided to the `wrapper`. The wrapper is invoked with the `this` + * binding of the created function. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Function + * @param {*} value The value to wrap. + * @param {Function} [wrapper=identity] The wrapper function. + * @returns {Function} Returns the new function. + * @example + * + * var p = _.wrap(_.escape, function(func, text) { + * return '

' + func(text) + '

'; + * }); + * + * p('fred, barney, & pebbles'); + * // => '

fred, barney, & pebbles

' + */ + function wrap(value, wrapper) { + return partial(castFunction(wrapper), value); + } + + /*------------------------------------------------------------------------*/ + + /** + * Casts `value` as an array if it's not one. + * + * @static + * @memberOf _ + * @since 4.4.0 + * @category Lang + * @param {*} value The value to inspect. + * @returns {Array} Returns the cast array. + * @example + * + * _.castArray(1); + * // => [1] + * + * _.castArray({ 'a': 1 }); + * // => [{ 'a': 1 }] + * + * _.castArray('abc'); + * // => ['abc'] + * + * _.castArray(null); + * // => [null] + * + * _.castArray(undefined); + * // => [undefined] + * + * _.castArray(); + * // => [] + * + * var array = [1, 2, 3]; + * console.log(_.castArray(array) === array); + * // => true + */ + function castArray() { + if (!arguments.length) { + return []; + } + var value = arguments[0]; + return isArray(value) ? value : [value]; + } + + /** + * Creates a shallow clone of `value`. + * + * **Note:** This method is loosely based on the + * [structured clone algorithm](https://mdn.io/Structured_clone_algorithm) + * and supports cloning arrays, array buffers, booleans, date objects, maps, + * numbers, `Object` objects, regexes, sets, strings, symbols, and typed + * arrays. The own enumerable properties of `arguments` objects are cloned + * as plain objects. An empty object is returned for uncloneable values such + * as error objects, functions, DOM nodes, and WeakMaps. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to clone. + * @returns {*} Returns the cloned value. + * @see _.cloneDeep + * @example + * + * var objects = [{ 'a': 1 }, { 'b': 2 }]; + * + * var shallow = _.clone(objects); + * console.log(shallow[0] === objects[0]); + * // => true + */ + function clone(value) { + return baseClone(value, CLONE_SYMBOLS_FLAG); + } + + /** + * This method is like `_.clone` except that it accepts `customizer` which + * is invoked to produce the cloned value. If `customizer` returns `undefined`, + * cloning is handled by the method instead. The `customizer` is invoked with + * up to four arguments; (value [, index|key, object, stack]). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to clone. + * @param {Function} [customizer] The function to customize cloning. + * @returns {*} Returns the cloned value. + * @see _.cloneDeepWith + * @example + * + * function customizer(value) { + * if (_.isElement(value)) { + * return value.cloneNode(false); + * } + * } + * + * var el = _.cloneWith(document.body, customizer); + * + * console.log(el === document.body); + * // => false + * console.log(el.nodeName); + * // => 'BODY' + * console.log(el.childNodes.length); + * // => 0 + */ + function cloneWith(value, customizer) { + customizer = typeof customizer == 'function' ? customizer : undefined; + return baseClone(value, CLONE_SYMBOLS_FLAG, customizer); + } + + /** + * This method is like `_.clone` except that it recursively clones `value`. + * + * @static + * @memberOf _ + * @since 1.0.0 + * @category Lang + * @param {*} value The value to recursively clone. + * @returns {*} Returns the deep cloned value. + * @see _.clone + * @example + * + * var objects = [{ 'a': 1 }, { 'b': 2 }]; + * + * var deep = _.cloneDeep(objects); + * console.log(deep[0] === objects[0]); + * // => false + */ + function cloneDeep(value) { + return baseClone(value, CLONE_DEEP_FLAG | CLONE_SYMBOLS_FLAG); + } + + /** + * This method is like `_.cloneWith` except that it recursively clones `value`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to recursively clone. + * @param {Function} [customizer] The function to customize cloning. + * @returns {*} Returns the deep cloned value. + * @see _.cloneWith + * @example + * + * function customizer(value) { + * if (_.isElement(value)) { + * return value.cloneNode(true); + * } + * } + * + * var el = _.cloneDeepWith(document.body, customizer); + * + * console.log(el === document.body); + * // => false + * console.log(el.nodeName); + * // => 'BODY' + * console.log(el.childNodes.length); + * // => 20 + */ + function cloneDeepWith(value, customizer) { + customizer = typeof customizer == 'function' ? customizer : undefined; + return baseClone(value, CLONE_DEEP_FLAG | CLONE_SYMBOLS_FLAG, customizer); + } + + /** + * Checks if `object` conforms to `source` by invoking the predicate + * properties of `source` with the corresponding property values of `object`. + * + * **Note:** This method is equivalent to `_.conforms` when `source` is + * partially applied. + * + * @static + * @memberOf _ + * @since 4.14.0 + * @category Lang + * @param {Object} object The object to inspect. + * @param {Object} source The object of property predicates to conform to. + * @returns {boolean} Returns `true` if `object` conforms, else `false`. + * @example + * + * var object = { 'a': 1, 'b': 2 }; + * + * _.conformsTo(object, { 'b': function(n) { return n > 1; } }); + * // => true + * + * _.conformsTo(object, { 'b': function(n) { return n > 2; } }); + * // => false + */ + function conformsTo(object, source) { + return source == null || baseConformsTo(object, source, keys(source)); + } + + /** + * Performs a + * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) + * comparison between two values to determine if they are equivalent. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @returns {boolean} Returns `true` if the values are equivalent, else `false`. + * @example + * + * var object = { 'a': 1 }; + * var other = { 'a': 1 }; + * + * _.eq(object, object); + * // => true + * + * _.eq(object, other); + * // => false + * + * _.eq('a', 'a'); + * // => true + * + * _.eq('a', Object('a')); + * // => false + * + * _.eq(NaN, NaN); + * // => true + */ + function eq(value, other) { + return value === other || (value !== value && other !== other); + } + + /** + * Checks if `value` is greater than `other`. + * + * @static + * @memberOf _ + * @since 3.9.0 + * @category Lang + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @returns {boolean} Returns `true` if `value` is greater than `other`, + * else `false`. + * @see _.lt + * @example + * + * _.gt(3, 1); + * // => true + * + * _.gt(3, 3); + * // => false + * + * _.gt(1, 3); + * // => false + */ + var gt = createRelationalOperation(baseGt); + + /** + * Checks if `value` is greater than or equal to `other`. + * + * @static + * @memberOf _ + * @since 3.9.0 + * @category Lang + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @returns {boolean} Returns `true` if `value` is greater than or equal to + * `other`, else `false`. + * @see _.lte + * @example + * + * _.gte(3, 1); + * // => true + * + * _.gte(3, 3); + * // => true + * + * _.gte(1, 3); + * // => false + */ + var gte = createRelationalOperation(function(value, other) { + return value >= other; + }); + + /** + * Checks if `value` is likely an `arguments` object. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an `arguments` object, + * else `false`. + * @example + * + * _.isArguments(function() { return arguments; }()); + * // => true + * + * _.isArguments([1, 2, 3]); + * // => false + */ + var isArguments = baseIsArguments(function() { return arguments; }()) ? baseIsArguments : function(value) { + return isObjectLike(value) && hasOwnProperty.call(value, 'callee') && + !propertyIsEnumerable.call(value, 'callee'); + }; + + /** + * Checks if `value` is classified as an `Array` object. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an array, else `false`. + * @example + * + * _.isArray([1, 2, 3]); + * // => true + * + * _.isArray(document.body.children); + * // => false + * + * _.isArray('abc'); + * // => false + * + * _.isArray(_.noop); + * // => false + */ + var isArray = Array.isArray; + + /** + * Checks if `value` is classified as an `ArrayBuffer` object. + * + * @static + * @memberOf _ + * @since 4.3.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an array buffer, else `false`. + * @example + * + * _.isArrayBuffer(new ArrayBuffer(2)); + * // => true + * + * _.isArrayBuffer(new Array(2)); + * // => false + */ + var isArrayBuffer = nodeIsArrayBuffer ? baseUnary(nodeIsArrayBuffer) : baseIsArrayBuffer; + + /** + * Checks if `value` is array-like. A value is considered array-like if it's + * not a function and has a `value.length` that's an integer greater than or + * equal to `0` and less than or equal to `Number.MAX_SAFE_INTEGER`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is array-like, else `false`. + * @example + * + * _.isArrayLike([1, 2, 3]); + * // => true + * + * _.isArrayLike(document.body.children); + * // => true + * + * _.isArrayLike('abc'); + * // => true + * + * _.isArrayLike(_.noop); + * // => false + */ + function isArrayLike(value) { + return value != null && isLength(value.length) && !isFunction(value); + } + + /** + * This method is like `_.isArrayLike` except that it also checks if `value` + * is an object. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an array-like object, + * else `false`. + * @example + * + * _.isArrayLikeObject([1, 2, 3]); + * // => true + * + * _.isArrayLikeObject(document.body.children); + * // => true + * + * _.isArrayLikeObject('abc'); + * // => false + * + * _.isArrayLikeObject(_.noop); + * // => false + */ + function isArrayLikeObject(value) { + return isObjectLike(value) && isArrayLike(value); + } + + /** + * Checks if `value` is classified as a boolean primitive or object. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a boolean, else `false`. + * @example + * + * _.isBoolean(false); + * // => true + * + * _.isBoolean(null); + * // => false + */ + function isBoolean(value) { + return value === true || value === false || + (isObjectLike(value) && baseGetTag(value) == boolTag); + } + + /** + * Checks if `value` is a buffer. + * + * @static + * @memberOf _ + * @since 4.3.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a buffer, else `false`. + * @example + * + * _.isBuffer(new Buffer(2)); + * // => true + * + * _.isBuffer(new Uint8Array(2)); + * // => false + */ + var isBuffer = nativeIsBuffer || stubFalse; + + /** + * Checks if `value` is classified as a `Date` object. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a date object, else `false`. + * @example + * + * _.isDate(new Date); + * // => true + * + * _.isDate('Mon April 23 2012'); + * // => false + */ + var isDate = nodeIsDate ? baseUnary(nodeIsDate) : baseIsDate; + + /** + * Checks if `value` is likely a DOM element. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a DOM element, else `false`. + * @example + * + * _.isElement(document.body); + * // => true + * + * _.isElement(''); + * // => false + */ + function isElement(value) { + return isObjectLike(value) && value.nodeType === 1 && !isPlainObject(value); + } + + /** + * Checks if `value` is an empty object, collection, map, or set. + * + * Objects are considered empty if they have no own enumerable string keyed + * properties. + * + * Array-like values such as `arguments` objects, arrays, buffers, strings, or + * jQuery-like collections are considered empty if they have a `length` of `0`. + * Similarly, maps and sets are considered empty if they have a `size` of `0`. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is empty, else `false`. + * @example + * + * _.isEmpty(null); + * // => true + * + * _.isEmpty(true); + * // => true + * + * _.isEmpty(1); + * // => true + * + * _.isEmpty([1, 2, 3]); + * // => false + * + * _.isEmpty({ 'a': 1 }); + * // => false + */ + function isEmpty(value) { + if (value == null) { + return true; + } + if (isArrayLike(value) && + (isArray(value) || typeof value == 'string' || typeof value.splice == 'function' || + isBuffer(value) || isTypedArray(value) || isArguments(value))) { + return !value.length; + } + var tag = getTag(value); + if (tag == mapTag || tag == setTag) { + return !value.size; + } + if (isPrototype(value)) { + return !baseKeys(value).length; + } + for (var key in value) { + if (hasOwnProperty.call(value, key)) { + return false; + } + } + return true; + } + + /** + * Performs a deep comparison between two values to determine if they are + * equivalent. + * + * **Note:** This method supports comparing arrays, array buffers, booleans, + * date objects, error objects, maps, numbers, `Object` objects, regexes, + * sets, strings, symbols, and typed arrays. `Object` objects are compared + * by their own, not inherited, enumerable properties. Functions and DOM + * nodes are compared by strict equality, i.e. `===`. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @returns {boolean} Returns `true` if the values are equivalent, else `false`. + * @example + * + * var object = { 'a': 1 }; + * var other = { 'a': 1 }; + * + * _.isEqual(object, other); + * // => true + * + * object === other; + * // => false + */ + function isEqual(value, other) { + return baseIsEqual(value, other); + } + + /** + * This method is like `_.isEqual` except that it accepts `customizer` which + * is invoked to compare values. If `customizer` returns `undefined`, comparisons + * are handled by the method instead. The `customizer` is invoked with up to + * six arguments: (objValue, othValue [, index|key, object, other, stack]). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @param {Function} [customizer] The function to customize comparisons. + * @returns {boolean} Returns `true` if the values are equivalent, else `false`. + * @example + * + * function isGreeting(value) { + * return /^h(?:i|ello)$/.test(value); + * } + * + * function customizer(objValue, othValue) { + * if (isGreeting(objValue) && isGreeting(othValue)) { + * return true; + * } + * } + * + * var array = ['hello', 'goodbye']; + * var other = ['hi', 'goodbye']; + * + * _.isEqualWith(array, other, customizer); + * // => true + */ + function isEqualWith(value, other, customizer) { + customizer = typeof customizer == 'function' ? customizer : undefined; + var result = customizer ? customizer(value, other) : undefined; + return result === undefined ? baseIsEqual(value, other, undefined, customizer) : !!result; + } + + /** + * Checks if `value` is an `Error`, `EvalError`, `RangeError`, `ReferenceError`, + * `SyntaxError`, `TypeError`, or `URIError` object. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an error object, else `false`. + * @example + * + * _.isError(new Error); + * // => true + * + * _.isError(Error); + * // => false + */ + function isError(value) { + if (!isObjectLike(value)) { + return false; + } + var tag = baseGetTag(value); + return tag == errorTag || tag == domExcTag || + (typeof value.message == 'string' && typeof value.name == 'string' && !isPlainObject(value)); + } + + /** + * Checks if `value` is a finite primitive number. + * + * **Note:** This method is based on + * [`Number.isFinite`](https://mdn.io/Number/isFinite). + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a finite number, else `false`. + * @example + * + * _.isFinite(3); + * // => true + * + * _.isFinite(Number.MIN_VALUE); + * // => true + * + * _.isFinite(Infinity); + * // => false + * + * _.isFinite('3'); + * // => false + */ + function isFinite(value) { + return typeof value == 'number' && nativeIsFinite(value); + } + + /** + * Checks if `value` is classified as a `Function` object. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a function, else `false`. + * @example + * + * _.isFunction(_); + * // => true + * + * _.isFunction(/abc/); + * // => false + */ + function isFunction(value) { + if (!isObject(value)) { + return false; + } + // The use of `Object#toString` avoids issues with the `typeof` operator + // in Safari 9 which returns 'object' for typed arrays and other constructors. + var tag = baseGetTag(value); + return tag == funcTag || tag == genTag || tag == asyncTag || tag == proxyTag; + } + + /** + * Checks if `value` is an integer. + * + * **Note:** This method is based on + * [`Number.isInteger`](https://mdn.io/Number/isInteger). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an integer, else `false`. + * @example + * + * _.isInteger(3); + * // => true + * + * _.isInteger(Number.MIN_VALUE); + * // => false + * + * _.isInteger(Infinity); + * // => false + * + * _.isInteger('3'); + * // => false + */ + function isInteger(value) { + return typeof value == 'number' && value == toInteger(value); + } + + /** + * Checks if `value` is a valid array-like length. + * + * **Note:** This method is loosely based on + * [`ToLength`](http://ecma-international.org/ecma-262/7.0/#sec-tolength). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a valid length, else `false`. + * @example + * + * _.isLength(3); + * // => true + * + * _.isLength(Number.MIN_VALUE); + * // => false + * + * _.isLength(Infinity); + * // => false + * + * _.isLength('3'); + * // => false + */ + function isLength(value) { + return typeof value == 'number' && + value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER; + } + + /** + * Checks if `value` is the + * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types) + * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`) + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an object, else `false`. + * @example + * + * _.isObject({}); + * // => true + * + * _.isObject([1, 2, 3]); + * // => true + * + * _.isObject(_.noop); + * // => true + * + * _.isObject(null); + * // => false + */ + function isObject(value) { + var type = typeof value; + return value != null && (type == 'object' || type == 'function'); + } + + /** + * Checks if `value` is object-like. A value is object-like if it's not `null` + * and has a `typeof` result of "object". + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is object-like, else `false`. + * @example + * + * _.isObjectLike({}); + * // => true + * + * _.isObjectLike([1, 2, 3]); + * // => true + * + * _.isObjectLike(_.noop); + * // => false + * + * _.isObjectLike(null); + * // => false + */ + function isObjectLike(value) { + return value != null && typeof value == 'object'; + } + + /** + * Checks if `value` is classified as a `Map` object. + * + * @static + * @memberOf _ + * @since 4.3.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a map, else `false`. + * @example + * + * _.isMap(new Map); + * // => true + * + * _.isMap(new WeakMap); + * // => false + */ + var isMap = nodeIsMap ? baseUnary(nodeIsMap) : baseIsMap; + + /** + * Performs a partial deep comparison between `object` and `source` to + * determine if `object` contains equivalent property values. + * + * **Note:** This method is equivalent to `_.matches` when `source` is + * partially applied. + * + * Partial comparisons will match empty array and empty object `source` + * values against any array or object value, respectively. See `_.isEqual` + * for a list of supported value comparisons. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Lang + * @param {Object} object The object to inspect. + * @param {Object} source The object of property values to match. + * @returns {boolean} Returns `true` if `object` is a match, else `false`. + * @example + * + * var object = { 'a': 1, 'b': 2 }; + * + * _.isMatch(object, { 'b': 2 }); + * // => true + * + * _.isMatch(object, { 'b': 1 }); + * // => false + */ + function isMatch(object, source) { + return object === source || baseIsMatch(object, source, getMatchData(source)); + } + + /** + * This method is like `_.isMatch` except that it accepts `customizer` which + * is invoked to compare values. If `customizer` returns `undefined`, comparisons + * are handled by the method instead. The `customizer` is invoked with five + * arguments: (objValue, srcValue, index|key, object, source). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {Object} object The object to inspect. + * @param {Object} source The object of property values to match. + * @param {Function} [customizer] The function to customize comparisons. + * @returns {boolean} Returns `true` if `object` is a match, else `false`. + * @example + * + * function isGreeting(value) { + * return /^h(?:i|ello)$/.test(value); + * } + * + * function customizer(objValue, srcValue) { + * if (isGreeting(objValue) && isGreeting(srcValue)) { + * return true; + * } + * } + * + * var object = { 'greeting': 'hello' }; + * var source = { 'greeting': 'hi' }; + * + * _.isMatchWith(object, source, customizer); + * // => true + */ + function isMatchWith(object, source, customizer) { + customizer = typeof customizer == 'function' ? customizer : undefined; + return baseIsMatch(object, source, getMatchData(source), customizer); + } + + /** + * Checks if `value` is `NaN`. + * + * **Note:** This method is based on + * [`Number.isNaN`](https://mdn.io/Number/isNaN) and is not the same as + * global [`isNaN`](https://mdn.io/isNaN) which returns `true` for + * `undefined` and other non-number values. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is `NaN`, else `false`. + * @example + * + * _.isNaN(NaN); + * // => true + * + * _.isNaN(new Number(NaN)); + * // => true + * + * isNaN(undefined); + * // => true + * + * _.isNaN(undefined); + * // => false + */ + function isNaN(value) { + // An `NaN` primitive is the only value that is not equal to itself. + // Perform the `toStringTag` check first to avoid errors with some + // ActiveX objects in IE. + return isNumber(value) && value != +value; + } + + /** + * Checks if `value` is a pristine native function. + * + * **Note:** This method can't reliably detect native functions in the presence + * of the core-js package because core-js circumvents this kind of detection. + * Despite multiple requests, the core-js maintainer has made it clear: any + * attempt to fix the detection will be obstructed. As a result, we're left + * with little choice but to throw an error. Unfortunately, this also affects + * packages, like [babel-polyfill](https://www.npmjs.com/package/babel-polyfill), + * which rely on core-js. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a native function, + * else `false`. + * @example + * + * _.isNative(Array.prototype.push); + * // => true + * + * _.isNative(_); + * // => false + */ + function isNative(value) { + if (isMaskable(value)) { + throw new Error(CORE_ERROR_TEXT); + } + return baseIsNative(value); + } + + /** + * Checks if `value` is `null`. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is `null`, else `false`. + * @example + * + * _.isNull(null); + * // => true + * + * _.isNull(void 0); + * // => false + */ + function isNull(value) { + return value === null; + } + + /** + * Checks if `value` is `null` or `undefined`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is nullish, else `false`. + * @example + * + * _.isNil(null); + * // => true + * + * _.isNil(void 0); + * // => true + * + * _.isNil(NaN); + * // => false + */ + function isNil(value) { + return value == null; + } + + /** + * Checks if `value` is classified as a `Number` primitive or object. + * + * **Note:** To exclude `Infinity`, `-Infinity`, and `NaN`, which are + * classified as numbers, use the `_.isFinite` method. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a number, else `false`. + * @example + * + * _.isNumber(3); + * // => true + * + * _.isNumber(Number.MIN_VALUE); + * // => true + * + * _.isNumber(Infinity); + * // => true + * + * _.isNumber('3'); + * // => false + */ + function isNumber(value) { + return typeof value == 'number' || + (isObjectLike(value) && baseGetTag(value) == numberTag); + } + + /** + * Checks if `value` is a plain object, that is, an object created by the + * `Object` constructor or one with a `[[Prototype]]` of `null`. + * + * @static + * @memberOf _ + * @since 0.8.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a plain object, else `false`. + * @example + * + * function Foo() { + * this.a = 1; + * } + * + * _.isPlainObject(new Foo); + * // => false + * + * _.isPlainObject([1, 2, 3]); + * // => false + * + * _.isPlainObject({ 'x': 0, 'y': 0 }); + * // => true + * + * _.isPlainObject(Object.create(null)); + * // => true + */ + function isPlainObject(value) { + if (!isObjectLike(value) || baseGetTag(value) != objectTag) { + return false; + } + var proto = getPrototype(value); + if (proto === null) { + return true; + } + var Ctor = hasOwnProperty.call(proto, 'constructor') && proto.constructor; + return typeof Ctor == 'function' && Ctor instanceof Ctor && + funcToString.call(Ctor) == objectCtorString; + } + + /** + * Checks if `value` is classified as a `RegExp` object. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a regexp, else `false`. + * @example + * + * _.isRegExp(/abc/); + * // => true + * + * _.isRegExp('/abc/'); + * // => false + */ + var isRegExp = nodeIsRegExp ? baseUnary(nodeIsRegExp) : baseIsRegExp; + + /** + * Checks if `value` is a safe integer. An integer is safe if it's an IEEE-754 + * double precision number which isn't the result of a rounded unsafe integer. + * + * **Note:** This method is based on + * [`Number.isSafeInteger`](https://mdn.io/Number/isSafeInteger). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a safe integer, else `false`. + * @example + * + * _.isSafeInteger(3); + * // => true + * + * _.isSafeInteger(Number.MIN_VALUE); + * // => false + * + * _.isSafeInteger(Infinity); + * // => false + * + * _.isSafeInteger('3'); + * // => false + */ + function isSafeInteger(value) { + return isInteger(value) && value >= -MAX_SAFE_INTEGER && value <= MAX_SAFE_INTEGER; + } + + /** + * Checks if `value` is classified as a `Set` object. + * + * @static + * @memberOf _ + * @since 4.3.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a set, else `false`. + * @example + * + * _.isSet(new Set); + * // => true + * + * _.isSet(new WeakSet); + * // => false + */ + var isSet = nodeIsSet ? baseUnary(nodeIsSet) : baseIsSet; + + /** + * Checks if `value` is classified as a `String` primitive or object. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a string, else `false`. + * @example + * + * _.isString('abc'); + * // => true + * + * _.isString(1); + * // => false + */ + function isString(value) { + return typeof value == 'string' || + (!isArray(value) && isObjectLike(value) && baseGetTag(value) == stringTag); + } + + /** + * Checks if `value` is classified as a `Symbol` primitive or object. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a symbol, else `false`. + * @example + * + * _.isSymbol(Symbol.iterator); + * // => true + * + * _.isSymbol('abc'); + * // => false + */ + function isSymbol(value) { + return typeof value == 'symbol' || + (isObjectLike(value) && baseGetTag(value) == symbolTag); + } + + /** + * Checks if `value` is classified as a typed array. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a typed array, else `false`. + * @example + * + * _.isTypedArray(new Uint8Array); + * // => true + * + * _.isTypedArray([]); + * // => false + */ + var isTypedArray = nodeIsTypedArray ? baseUnary(nodeIsTypedArray) : baseIsTypedArray; + + /** + * Checks if `value` is `undefined`. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is `undefined`, else `false`. + * @example + * + * _.isUndefined(void 0); + * // => true + * + * _.isUndefined(null); + * // => false + */ + function isUndefined(value) { + return value === undefined; + } + + /** + * Checks if `value` is classified as a `WeakMap` object. + * + * @static + * @memberOf _ + * @since 4.3.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a weak map, else `false`. + * @example + * + * _.isWeakMap(new WeakMap); + * // => true + * + * _.isWeakMap(new Map); + * // => false + */ + function isWeakMap(value) { + return isObjectLike(value) && getTag(value) == weakMapTag; + } + + /** + * Checks if `value` is classified as a `WeakSet` object. + * + * @static + * @memberOf _ + * @since 4.3.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a weak set, else `false`. + * @example + * + * _.isWeakSet(new WeakSet); + * // => true + * + * _.isWeakSet(new Set); + * // => false + */ + function isWeakSet(value) { + return isObjectLike(value) && baseGetTag(value) == weakSetTag; + } + + /** + * Checks if `value` is less than `other`. + * + * @static + * @memberOf _ + * @since 3.9.0 + * @category Lang + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @returns {boolean} Returns `true` if `value` is less than `other`, + * else `false`. + * @see _.gt + * @example + * + * _.lt(1, 3); + * // => true + * + * _.lt(3, 3); + * // => false + * + * _.lt(3, 1); + * // => false + */ + var lt = createRelationalOperation(baseLt); + + /** + * Checks if `value` is less than or equal to `other`. + * + * @static + * @memberOf _ + * @since 3.9.0 + * @category Lang + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @returns {boolean} Returns `true` if `value` is less than or equal to + * `other`, else `false`. + * @see _.gte + * @example + * + * _.lte(1, 3); + * // => true + * + * _.lte(3, 3); + * // => true + * + * _.lte(3, 1); + * // => false + */ + var lte = createRelationalOperation(function(value, other) { + return value <= other; + }); + + /** + * Converts `value` to an array. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category Lang + * @param {*} value The value to convert. + * @returns {Array} Returns the converted array. + * @example + * + * _.toArray({ 'a': 1, 'b': 2 }); + * // => [1, 2] + * + * _.toArray('abc'); + * // => ['a', 'b', 'c'] + * + * _.toArray(1); + * // => [] + * + * _.toArray(null); + * // => [] + */ + function toArray(value) { + if (!value) { + return []; + } + if (isArrayLike(value)) { + return isString(value) ? stringToArray(value) : copyArray(value); + } + if (symIterator && value[symIterator]) { + return iteratorToArray(value[symIterator]()); + } + var tag = getTag(value), + func = tag == mapTag ? mapToArray : (tag == setTag ? setToArray : values); + + return func(value); + } + + /** + * Converts `value` to a finite number. + * + * @static + * @memberOf _ + * @since 4.12.0 + * @category Lang + * @param {*} value The value to convert. + * @returns {number} Returns the converted number. + * @example + * + * _.toFinite(3.2); + * // => 3.2 + * + * _.toFinite(Number.MIN_VALUE); + * // => 5e-324 + * + * _.toFinite(Infinity); + * // => 1.7976931348623157e+308 + * + * _.toFinite('3.2'); + * // => 3.2 + */ + function toFinite(value) { + if (!value) { + return value === 0 ? value : 0; + } + value = toNumber(value); + if (value === INFINITY || value === -INFINITY) { + var sign = (value < 0 ? -1 : 1); + return sign * MAX_INTEGER; + } + return value === value ? value : 0; + } + + /** + * Converts `value` to an integer. + * + * **Note:** This method is loosely based on + * [`ToInteger`](http://www.ecma-international.org/ecma-262/7.0/#sec-tointeger). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to convert. + * @returns {number} Returns the converted integer. + * @example + * + * _.toInteger(3.2); + * // => 3 + * + * _.toInteger(Number.MIN_VALUE); + * // => 0 + * + * _.toInteger(Infinity); + * // => 1.7976931348623157e+308 + * + * _.toInteger('3.2'); + * // => 3 + */ + function toInteger(value) { + var result = toFinite(value), + remainder = result % 1; + + return result === result ? (remainder ? result - remainder : result) : 0; + } + + /** + * Converts `value` to an integer suitable for use as the length of an + * array-like object. + * + * **Note:** This method is based on + * [`ToLength`](http://ecma-international.org/ecma-262/7.0/#sec-tolength). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to convert. + * @returns {number} Returns the converted integer. + * @example + * + * _.toLength(3.2); + * // => 3 + * + * _.toLength(Number.MIN_VALUE); + * // => 0 + * + * _.toLength(Infinity); + * // => 4294967295 + * + * _.toLength('3.2'); + * // => 3 + */ + function toLength(value) { + return value ? baseClamp(toInteger(value), 0, MAX_ARRAY_LENGTH) : 0; + } + + /** + * Converts `value` to a number. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to process. + * @returns {number} Returns the number. + * @example + * + * _.toNumber(3.2); + * // => 3.2 + * + * _.toNumber(Number.MIN_VALUE); + * // => 5e-324 + * + * _.toNumber(Infinity); + * // => Infinity + * + * _.toNumber('3.2'); + * // => 3.2 + */ + function toNumber(value) { + if (typeof value == 'number') { + return value; + } + if (isSymbol(value)) { + return NAN; + } + if (isObject(value)) { + var other = typeof value.valueOf == 'function' ? value.valueOf() : value; + value = isObject(other) ? (other + '') : other; + } + if (typeof value != 'string') { + return value === 0 ? value : +value; + } + value = baseTrim(value); + var isBinary = reIsBinary.test(value); + return (isBinary || reIsOctal.test(value)) + ? freeParseInt(value.slice(2), isBinary ? 2 : 8) + : (reIsBadHex.test(value) ? NAN : +value); + } + + /** + * Converts `value` to a plain object flattening inherited enumerable string + * keyed properties of `value` to own properties of the plain object. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Lang + * @param {*} value The value to convert. + * @returns {Object} Returns the converted plain object. + * @example + * + * function Foo() { + * this.b = 2; + * } + * + * Foo.prototype.c = 3; + * + * _.assign({ 'a': 1 }, new Foo); + * // => { 'a': 1, 'b': 2 } + * + * _.assign({ 'a': 1 }, _.toPlainObject(new Foo)); + * // => { 'a': 1, 'b': 2, 'c': 3 } + */ + function toPlainObject(value) { + return copyObject(value, keysIn(value)); + } + + /** + * Converts `value` to a safe integer. A safe integer can be compared and + * represented correctly. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to convert. + * @returns {number} Returns the converted integer. + * @example + * + * _.toSafeInteger(3.2); + * // => 3 + * + * _.toSafeInteger(Number.MIN_VALUE); + * // => 0 + * + * _.toSafeInteger(Infinity); + * // => 9007199254740991 + * + * _.toSafeInteger('3.2'); + * // => 3 + */ + function toSafeInteger(value) { + return value + ? baseClamp(toInteger(value), -MAX_SAFE_INTEGER, MAX_SAFE_INTEGER) + : (value === 0 ? value : 0); + } + + /** + * Converts `value` to a string. An empty string is returned for `null` + * and `undefined` values. The sign of `-0` is preserved. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to convert. + * @returns {string} Returns the converted string. + * @example + * + * _.toString(null); + * // => '' + * + * _.toString(-0); + * // => '-0' + * + * _.toString([1, 2, 3]); + * // => '1,2,3' + */ + function toString(value) { + return value == null ? '' : baseToString(value); + } + + /*------------------------------------------------------------------------*/ + + /** + * Assigns own enumerable string keyed properties of source objects to the + * destination object. Source objects are applied from left to right. + * Subsequent sources overwrite property assignments of previous sources. + * + * **Note:** This method mutates `object` and is loosely based on + * [`Object.assign`](https://mdn.io/Object/assign). + * + * @static + * @memberOf _ + * @since 0.10.0 + * @category Object + * @param {Object} object The destination object. + * @param {...Object} [sources] The source objects. + * @returns {Object} Returns `object`. + * @see _.assignIn + * @example + * + * function Foo() { + * this.a = 1; + * } + * + * function Bar() { + * this.c = 3; + * } + * + * Foo.prototype.b = 2; + * Bar.prototype.d = 4; + * + * _.assign({ 'a': 0 }, new Foo, new Bar); + * // => { 'a': 1, 'c': 3 } + */ + var assign = createAssigner(function(object, source) { + if (isPrototype(source) || isArrayLike(source)) { + copyObject(source, keys(source), object); + return; + } + for (var key in source) { + if (hasOwnProperty.call(source, key)) { + assignValue(object, key, source[key]); + } + } + }); + + /** + * This method is like `_.assign` except that it iterates over own and + * inherited source properties. + * + * **Note:** This method mutates `object`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @alias extend + * @category Object + * @param {Object} object The destination object. + * @param {...Object} [sources] The source objects. + * @returns {Object} Returns `object`. + * @see _.assign + * @example + * + * function Foo() { + * this.a = 1; + * } + * + * function Bar() { + * this.c = 3; + * } + * + * Foo.prototype.b = 2; + * Bar.prototype.d = 4; + * + * _.assignIn({ 'a': 0 }, new Foo, new Bar); + * // => { 'a': 1, 'b': 2, 'c': 3, 'd': 4 } + */ + var assignIn = createAssigner(function(object, source) { + copyObject(source, keysIn(source), object); + }); + + /** + * This method is like `_.assignIn` except that it accepts `customizer` + * which is invoked to produce the assigned values. If `customizer` returns + * `undefined`, assignment is handled by the method instead. The `customizer` + * is invoked with five arguments: (objValue, srcValue, key, object, source). + * + * **Note:** This method mutates `object`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @alias extendWith + * @category Object + * @param {Object} object The destination object. + * @param {...Object} sources The source objects. + * @param {Function} [customizer] The function to customize assigned values. + * @returns {Object} Returns `object`. + * @see _.assignWith + * @example + * + * function customizer(objValue, srcValue) { + * return _.isUndefined(objValue) ? srcValue : objValue; + * } + * + * var defaults = _.partialRight(_.assignInWith, customizer); + * + * defaults({ 'a': 1 }, { 'b': 2 }, { 'a': 3 }); + * // => { 'a': 1, 'b': 2 } + */ + var assignInWith = createAssigner(function(object, source, srcIndex, customizer) { + copyObject(source, keysIn(source), object, customizer); + }); + + /** + * This method is like `_.assign` except that it accepts `customizer` + * which is invoked to produce the assigned values. If `customizer` returns + * `undefined`, assignment is handled by the method instead. The `customizer` + * is invoked with five arguments: (objValue, srcValue, key, object, source). + * + * **Note:** This method mutates `object`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Object + * @param {Object} object The destination object. + * @param {...Object} sources The source objects. + * @param {Function} [customizer] The function to customize assigned values. + * @returns {Object} Returns `object`. + * @see _.assignInWith + * @example + * + * function customizer(objValue, srcValue) { + * return _.isUndefined(objValue) ? srcValue : objValue; + * } + * + * var defaults = _.partialRight(_.assignWith, customizer); + * + * defaults({ 'a': 1 }, { 'b': 2 }, { 'a': 3 }); + * // => { 'a': 1, 'b': 2 } + */ + var assignWith = createAssigner(function(object, source, srcIndex, customizer) { + copyObject(source, keys(source), object, customizer); + }); + + /** + * Creates an array of values corresponding to `paths` of `object`. + * + * @static + * @memberOf _ + * @since 1.0.0 + * @category Object + * @param {Object} object The object to iterate over. + * @param {...(string|string[])} [paths] The property paths to pick. + * @returns {Array} Returns the picked values. + * @example + * + * var object = { 'a': [{ 'b': { 'c': 3 } }, 4] }; + * + * _.at(object, ['a[0].b.c', 'a[1]']); + * // => [3, 4] + */ + var at = flatRest(baseAt); + + /** + * Creates an object that inherits from the `prototype` object. If a + * `properties` object is given, its own enumerable string keyed properties + * are assigned to the created object. + * + * @static + * @memberOf _ + * @since 2.3.0 + * @category Object + * @param {Object} prototype The object to inherit from. + * @param {Object} [properties] The properties to assign to the object. + * @returns {Object} Returns the new object. + * @example + * + * function Shape() { + * this.x = 0; + * this.y = 0; + * } + * + * function Circle() { + * Shape.call(this); + * } + * + * Circle.prototype = _.create(Shape.prototype, { + * 'constructor': Circle + * }); + * + * var circle = new Circle; + * circle instanceof Circle; + * // => true + * + * circle instanceof Shape; + * // => true + */ + function create(prototype, properties) { + var result = baseCreate(prototype); + return properties == null ? result : baseAssign(result, properties); + } + + /** + * Assigns own and inherited enumerable string keyed properties of source + * objects to the destination object for all destination properties that + * resolve to `undefined`. Source objects are applied from left to right. + * Once a property is set, additional values of the same property are ignored. + * + * **Note:** This method mutates `object`. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category Object + * @param {Object} object The destination object. + * @param {...Object} [sources] The source objects. + * @returns {Object} Returns `object`. + * @see _.defaultsDeep + * @example + * + * _.defaults({ 'a': 1 }, { 'b': 2 }, { 'a': 3 }); + * // => { 'a': 1, 'b': 2 } + */ + var defaults = baseRest(function(object, sources) { + object = Object(object); + + var index = -1; + var length = sources.length; + var guard = length > 2 ? sources[2] : undefined; + + if (guard && isIterateeCall(sources[0], sources[1], guard)) { + length = 1; + } + + while (++index < length) { + var source = sources[index]; + var props = keysIn(source); + var propsIndex = -1; + var propsLength = props.length; + + while (++propsIndex < propsLength) { + var key = props[propsIndex]; + var value = object[key]; + + if (value === undefined || + (eq(value, objectProto[key]) && !hasOwnProperty.call(object, key))) { + object[key] = source[key]; + } + } + } + + return object; + }); + + /** + * This method is like `_.defaults` except that it recursively assigns + * default properties. + * + * **Note:** This method mutates `object`. + * + * @static + * @memberOf _ + * @since 3.10.0 + * @category Object + * @param {Object} object The destination object. + * @param {...Object} [sources] The source objects. + * @returns {Object} Returns `object`. + * @see _.defaults + * @example + * + * _.defaultsDeep({ 'a': { 'b': 2 } }, { 'a': { 'b': 1, 'c': 3 } }); + * // => { 'a': { 'b': 2, 'c': 3 } } + */ + var defaultsDeep = baseRest(function(args) { + args.push(undefined, customDefaultsMerge); + return apply(mergeWith, undefined, args); + }); + + /** + * This method is like `_.find` except that it returns the key of the first + * element `predicate` returns truthy for instead of the element itself. + * + * @static + * @memberOf _ + * @since 1.1.0 + * @category Object + * @param {Object} object The object to inspect. + * @param {Function} [predicate=_.identity] The function invoked per iteration. + * @returns {string|undefined} Returns the key of the matched element, + * else `undefined`. + * @example + * + * var users = { + * 'barney': { 'age': 36, 'active': true }, + * 'fred': { 'age': 40, 'active': false }, + * 'pebbles': { 'age': 1, 'active': true } + * }; + * + * _.findKey(users, function(o) { return o.age < 40; }); + * // => 'barney' (iteration order is not guaranteed) + * + * // The `_.matches` iteratee shorthand. + * _.findKey(users, { 'age': 1, 'active': true }); + * // => 'pebbles' + * + * // The `_.matchesProperty` iteratee shorthand. + * _.findKey(users, ['active', false]); + * // => 'fred' + * + * // The `_.property` iteratee shorthand. + * _.findKey(users, 'active'); + * // => 'barney' + */ + function findKey(object, predicate) { + return baseFindKey(object, getIteratee(predicate, 3), baseForOwn); + } + + /** + * This method is like `_.findKey` except that it iterates over elements of + * a collection in the opposite order. + * + * @static + * @memberOf _ + * @since 2.0.0 + * @category Object + * @param {Object} object The object to inspect. + * @param {Function} [predicate=_.identity] The function invoked per iteration. + * @returns {string|undefined} Returns the key of the matched element, + * else `undefined`. + * @example + * + * var users = { + * 'barney': { 'age': 36, 'active': true }, + * 'fred': { 'age': 40, 'active': false }, + * 'pebbles': { 'age': 1, 'active': true } + * }; + * + * _.findLastKey(users, function(o) { return o.age < 40; }); + * // => returns 'pebbles' assuming `_.findKey` returns 'barney' + * + * // The `_.matches` iteratee shorthand. + * _.findLastKey(users, { 'age': 36, 'active': true }); + * // => 'barney' + * + * // The `_.matchesProperty` iteratee shorthand. + * _.findLastKey(users, ['active', false]); + * // => 'fred' + * + * // The `_.property` iteratee shorthand. + * _.findLastKey(users, 'active'); + * // => 'pebbles' + */ + function findLastKey(object, predicate) { + return baseFindKey(object, getIteratee(predicate, 3), baseForOwnRight); + } + + /** + * Iterates over own and inherited enumerable string keyed properties of an + * object and invokes `iteratee` for each property. The iteratee is invoked + * with three arguments: (value, key, object). Iteratee functions may exit + * iteration early by explicitly returning `false`. + * + * @static + * @memberOf _ + * @since 0.3.0 + * @category Object + * @param {Object} object The object to iterate over. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. + * @returns {Object} Returns `object`. + * @see _.forInRight + * @example + * + * function Foo() { + * this.a = 1; + * this.b = 2; + * } + * + * Foo.prototype.c = 3; + * + * _.forIn(new Foo, function(value, key) { + * console.log(key); + * }); + * // => Logs 'a', 'b', then 'c' (iteration order is not guaranteed). + */ + function forIn(object, iteratee) { + return object == null + ? object + : baseFor(object, getIteratee(iteratee, 3), keysIn); + } + + /** + * This method is like `_.forIn` except that it iterates over properties of + * `object` in the opposite order. + * + * @static + * @memberOf _ + * @since 2.0.0 + * @category Object + * @param {Object} object The object to iterate over. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. + * @returns {Object} Returns `object`. + * @see _.forIn + * @example + * + * function Foo() { + * this.a = 1; + * this.b = 2; + * } + * + * Foo.prototype.c = 3; + * + * _.forInRight(new Foo, function(value, key) { + * console.log(key); + * }); + * // => Logs 'c', 'b', then 'a' assuming `_.forIn` logs 'a', 'b', then 'c'. + */ + function forInRight(object, iteratee) { + return object == null + ? object + : baseForRight(object, getIteratee(iteratee, 3), keysIn); + } + + /** + * Iterates over own enumerable string keyed properties of an object and + * invokes `iteratee` for each property. The iteratee is invoked with three + * arguments: (value, key, object). Iteratee functions may exit iteration + * early by explicitly returning `false`. + * + * @static + * @memberOf _ + * @since 0.3.0 + * @category Object + * @param {Object} object The object to iterate over. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. + * @returns {Object} Returns `object`. + * @see _.forOwnRight + * @example + * + * function Foo() { + * this.a = 1; + * this.b = 2; + * } + * + * Foo.prototype.c = 3; + * + * _.forOwn(new Foo, function(value, key) { + * console.log(key); + * }); + * // => Logs 'a' then 'b' (iteration order is not guaranteed). + */ + function forOwn(object, iteratee) { + return object && baseForOwn(object, getIteratee(iteratee, 3)); + } + + /** + * This method is like `_.forOwn` except that it iterates over properties of + * `object` in the opposite order. + * + * @static + * @memberOf _ + * @since 2.0.0 + * @category Object + * @param {Object} object The object to iterate over. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. + * @returns {Object} Returns `object`. + * @see _.forOwn + * @example + * + * function Foo() { + * this.a = 1; + * this.b = 2; + * } + * + * Foo.prototype.c = 3; + * + * _.forOwnRight(new Foo, function(value, key) { + * console.log(key); + * }); + * // => Logs 'b' then 'a' assuming `_.forOwn` logs 'a' then 'b'. + */ + function forOwnRight(object, iteratee) { + return object && baseForOwnRight(object, getIteratee(iteratee, 3)); + } + + /** + * Creates an array of function property names from own enumerable properties + * of `object`. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category Object + * @param {Object} object The object to inspect. + * @returns {Array} Returns the function names. + * @see _.functionsIn + * @example + * + * function Foo() { + * this.a = _.constant('a'); + * this.b = _.constant('b'); + * } + * + * Foo.prototype.c = _.constant('c'); + * + * _.functions(new Foo); + * // => ['a', 'b'] + */ + function functions(object) { + return object == null ? [] : baseFunctions(object, keys(object)); + } + + /** + * Creates an array of function property names from own and inherited + * enumerable properties of `object`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Object + * @param {Object} object The object to inspect. + * @returns {Array} Returns the function names. + * @see _.functions + * @example + * + * function Foo() { + * this.a = _.constant('a'); + * this.b = _.constant('b'); + * } + * + * Foo.prototype.c = _.constant('c'); + * + * _.functionsIn(new Foo); + * // => ['a', 'b', 'c'] + */ + function functionsIn(object) { + return object == null ? [] : baseFunctions(object, keysIn(object)); + } + + /** + * Gets the value at `path` of `object`. If the resolved value is + * `undefined`, the `defaultValue` is returned in its place. + * + * @static + * @memberOf _ + * @since 3.7.0 + * @category Object + * @param {Object} object The object to query. + * @param {Array|string} path The path of the property to get. + * @param {*} [defaultValue] The value returned for `undefined` resolved values. + * @returns {*} Returns the resolved value. + * @example + * + * var object = { 'a': [{ 'b': { 'c': 3 } }] }; + * + * _.get(object, 'a[0].b.c'); + * // => 3 + * + * _.get(object, ['a', '0', 'b', 'c']); + * // => 3 + * + * _.get(object, 'a.b.c', 'default'); + * // => 'default' + */ + function get(object, path, defaultValue) { + var result = object == null ? undefined : baseGet(object, path); + return result === undefined ? defaultValue : result; + } + + /** + * Checks if `path` is a direct property of `object`. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category Object + * @param {Object} object The object to query. + * @param {Array|string} path The path to check. + * @returns {boolean} Returns `true` if `path` exists, else `false`. + * @example + * + * var object = { 'a': { 'b': 2 } }; + * var other = _.create({ 'a': _.create({ 'b': 2 }) }); + * + * _.has(object, 'a'); + * // => true + * + * _.has(object, 'a.b'); + * // => true + * + * _.has(object, ['a', 'b']); + * // => true + * + * _.has(other, 'a'); + * // => false + */ + function has(object, path) { + return object != null && hasPath(object, path, baseHas); + } + + /** + * Checks if `path` is a direct or inherited property of `object`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Object + * @param {Object} object The object to query. + * @param {Array|string} path The path to check. + * @returns {boolean} Returns `true` if `path` exists, else `false`. + * @example + * + * var object = _.create({ 'a': _.create({ 'b': 2 }) }); + * + * _.hasIn(object, 'a'); + * // => true + * + * _.hasIn(object, 'a.b'); + * // => true + * + * _.hasIn(object, ['a', 'b']); + * // => true + * + * _.hasIn(object, 'b'); + * // => false + */ + function hasIn(object, path) { + return object != null && hasPath(object, path, baseHasIn); + } + + /** + * Creates an object composed of the inverted keys and values of `object`. + * If `object` contains duplicate values, subsequent values overwrite + * property assignments of previous values. + * + * @static + * @memberOf _ + * @since 0.7.0 + * @category Object + * @param {Object} object The object to invert. + * @returns {Object} Returns the new inverted object. + * @example + * + * var object = { 'a': 1, 'b': 2, 'c': 1 }; + * + * _.invert(object); + * // => { '1': 'c', '2': 'b' } + */ + var invert = createInverter(function(result, value, key) { + if (value != null && + typeof value.toString != 'function') { + value = nativeObjectToString.call(value); + } + + result[value] = key; + }, constant(identity)); + + /** + * This method is like `_.invert` except that the inverted object is generated + * from the results of running each element of `object` thru `iteratee`. The + * corresponding inverted value of each inverted key is an array of keys + * responsible for generating the inverted value. The iteratee is invoked + * with one argument: (value). + * + * @static + * @memberOf _ + * @since 4.1.0 + * @category Object + * @param {Object} object The object to invert. + * @param {Function} [iteratee=_.identity] The iteratee invoked per element. + * @returns {Object} Returns the new inverted object. + * @example + * + * var object = { 'a': 1, 'b': 2, 'c': 1 }; + * + * _.invertBy(object); + * // => { '1': ['a', 'c'], '2': ['b'] } + * + * _.invertBy(object, function(value) { + * return 'group' + value; + * }); + * // => { 'group1': ['a', 'c'], 'group2': ['b'] } + */ + var invertBy = createInverter(function(result, value, key) { + if (value != null && + typeof value.toString != 'function') { + value = nativeObjectToString.call(value); + } + + if (hasOwnProperty.call(result, value)) { + result[value].push(key); + } else { + result[value] = [key]; + } + }, getIteratee); + + /** + * Invokes the method at `path` of `object`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Object + * @param {Object} object The object to query. + * @param {Array|string} path The path of the method to invoke. + * @param {...*} [args] The arguments to invoke the method with. + * @returns {*} Returns the result of the invoked method. + * @example + * + * var object = { 'a': [{ 'b': { 'c': [1, 2, 3, 4] } }] }; + * + * _.invoke(object, 'a[0].b.c.slice', 1, 3); + * // => [2, 3] + */ + var invoke = baseRest(baseInvoke); + + /** + * Creates an array of the own enumerable property names of `object`. + * + * **Note:** Non-object values are coerced to objects. See the + * [ES spec](http://ecma-international.org/ecma-262/7.0/#sec-object.keys) + * for more details. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category Object + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property names. + * @example + * + * function Foo() { + * this.a = 1; + * this.b = 2; + * } + * + * Foo.prototype.c = 3; + * + * _.keys(new Foo); + * // => ['a', 'b'] (iteration order is not guaranteed) + * + * _.keys('hi'); + * // => ['0', '1'] + */ + function keys(object) { + return isArrayLike(object) ? arrayLikeKeys(object) : baseKeys(object); + } + + /** + * Creates an array of the own and inherited enumerable property names of `object`. + * + * **Note:** Non-object values are coerced to objects. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Object + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property names. + * @example + * + * function Foo() { + * this.a = 1; + * this.b = 2; + * } + * + * Foo.prototype.c = 3; + * + * _.keysIn(new Foo); + * // => ['a', 'b', 'c'] (iteration order is not guaranteed) + */ + function keysIn(object) { + return isArrayLike(object) ? arrayLikeKeys(object, true) : baseKeysIn(object); + } + + /** + * The opposite of `_.mapValues`; this method creates an object with the + * same values as `object` and keys generated by running each own enumerable + * string keyed property of `object` thru `iteratee`. The iteratee is invoked + * with three arguments: (value, key, object). + * + * @static + * @memberOf _ + * @since 3.8.0 + * @category Object + * @param {Object} object The object to iterate over. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. + * @returns {Object} Returns the new mapped object. + * @see _.mapValues + * @example + * + * _.mapKeys({ 'a': 1, 'b': 2 }, function(value, key) { + * return key + value; + * }); + * // => { 'a1': 1, 'b2': 2 } + */ + function mapKeys(object, iteratee) { + var result = {}; + iteratee = getIteratee(iteratee, 3); + + baseForOwn(object, function(value, key, object) { + baseAssignValue(result, iteratee(value, key, object), value); + }); + return result; + } + + /** + * Creates an object with the same keys as `object` and values generated + * by running each own enumerable string keyed property of `object` thru + * `iteratee`. The iteratee is invoked with three arguments: + * (value, key, object). + * + * @static + * @memberOf _ + * @since 2.4.0 + * @category Object + * @param {Object} object The object to iterate over. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. + * @returns {Object} Returns the new mapped object. + * @see _.mapKeys + * @example + * + * var users = { + * 'fred': { 'user': 'fred', 'age': 40 }, + * 'pebbles': { 'user': 'pebbles', 'age': 1 } + * }; + * + * _.mapValues(users, function(o) { return o.age; }); + * // => { 'fred': 40, 'pebbles': 1 } (iteration order is not guaranteed) + * + * // The `_.property` iteratee shorthand. + * _.mapValues(users, 'age'); + * // => { 'fred': 40, 'pebbles': 1 } (iteration order is not guaranteed) + */ + function mapValues(object, iteratee) { + var result = {}; + iteratee = getIteratee(iteratee, 3); + + baseForOwn(object, function(value, key, object) { + baseAssignValue(result, key, iteratee(value, key, object)); + }); + return result; + } + + /** + * This method is like `_.assign` except that it recursively merges own and + * inherited enumerable string keyed properties of source objects into the + * destination object. Source properties that resolve to `undefined` are + * skipped if a destination value exists. Array and plain object properties + * are merged recursively. Other objects and value types are overridden by + * assignment. Source objects are applied from left to right. Subsequent + * sources overwrite property assignments of previous sources. + * + * **Note:** This method mutates `object`. + * + * @static + * @memberOf _ + * @since 0.5.0 + * @category Object + * @param {Object} object The destination object. + * @param {...Object} [sources] The source objects. + * @returns {Object} Returns `object`. + * @example + * + * var object = { + * 'a': [{ 'b': 2 }, { 'd': 4 }] + * }; + * + * var other = { + * 'a': [{ 'c': 3 }, { 'e': 5 }] + * }; + * + * _.merge(object, other); + * // => { 'a': [{ 'b': 2, 'c': 3 }, { 'd': 4, 'e': 5 }] } + */ + var merge = createAssigner(function(object, source, srcIndex) { + baseMerge(object, source, srcIndex); + }); + + /** + * This method is like `_.merge` except that it accepts `customizer` which + * is invoked to produce the merged values of the destination and source + * properties. If `customizer` returns `undefined`, merging is handled by the + * method instead. The `customizer` is invoked with six arguments: + * (objValue, srcValue, key, object, source, stack). + * + * **Note:** This method mutates `object`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Object + * @param {Object} object The destination object. + * @param {...Object} sources The source objects. + * @param {Function} customizer The function to customize assigned values. + * @returns {Object} Returns `object`. + * @example + * + * function customizer(objValue, srcValue) { + * if (_.isArray(objValue)) { + * return objValue.concat(srcValue); + * } + * } + * + * var object = { 'a': [1], 'b': [2] }; + * var other = { 'a': [3], 'b': [4] }; + * + * _.mergeWith(object, other, customizer); + * // => { 'a': [1, 3], 'b': [2, 4] } + */ + var mergeWith = createAssigner(function(object, source, srcIndex, customizer) { + baseMerge(object, source, srcIndex, customizer); + }); + + /** + * The opposite of `_.pick`; this method creates an object composed of the + * own and inherited enumerable property paths of `object` that are not omitted. + * + * **Note:** This method is considerably slower than `_.pick`. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category Object + * @param {Object} object The source object. + * @param {...(string|string[])} [paths] The property paths to omit. + * @returns {Object} Returns the new object. + * @example + * + * var object = { 'a': 1, 'b': '2', 'c': 3 }; + * + * _.omit(object, ['a', 'c']); + * // => { 'b': '2' } + */ + var omit = flatRest(function(object, paths) { + var result = {}; + if (object == null) { + return result; + } + var isDeep = false; + paths = arrayMap(paths, function(path) { + path = castPath(path, object); + isDeep || (isDeep = path.length > 1); + return path; + }); + copyObject(object, getAllKeysIn(object), result); + if (isDeep) { + result = baseClone(result, CLONE_DEEP_FLAG | CLONE_FLAT_FLAG | CLONE_SYMBOLS_FLAG, customOmitClone); + } + var length = paths.length; + while (length--) { + baseUnset(result, paths[length]); + } + return result; + }); + + /** + * The opposite of `_.pickBy`; this method creates an object composed of + * the own and inherited enumerable string keyed properties of `object` that + * `predicate` doesn't return truthy for. The predicate is invoked with two + * arguments: (value, key). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Object + * @param {Object} object The source object. + * @param {Function} [predicate=_.identity] The function invoked per property. + * @returns {Object} Returns the new object. + * @example + * + * var object = { 'a': 1, 'b': '2', 'c': 3 }; + * + * _.omitBy(object, _.isNumber); + * // => { 'b': '2' } + */ + function omitBy(object, predicate) { + return pickBy(object, negate(getIteratee(predicate))); + } + + /** + * Creates an object composed of the picked `object` properties. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category Object + * @param {Object} object The source object. + * @param {...(string|string[])} [paths] The property paths to pick. + * @returns {Object} Returns the new object. + * @example + * + * var object = { 'a': 1, 'b': '2', 'c': 3 }; + * + * _.pick(object, ['a', 'c']); + * // => { 'a': 1, 'c': 3 } + */ + var pick = flatRest(function(object, paths) { + return object == null ? {} : basePick(object, paths); + }); + + /** + * Creates an object composed of the `object` properties `predicate` returns + * truthy for. The predicate is invoked with two arguments: (value, key). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Object + * @param {Object} object The source object. + * @param {Function} [predicate=_.identity] The function invoked per property. + * @returns {Object} Returns the new object. + * @example + * + * var object = { 'a': 1, 'b': '2', 'c': 3 }; + * + * _.pickBy(object, _.isNumber); + * // => { 'a': 1, 'c': 3 } + */ + function pickBy(object, predicate) { + if (object == null) { + return {}; + } + var props = arrayMap(getAllKeysIn(object), function(prop) { + return [prop]; + }); + predicate = getIteratee(predicate); + return basePickBy(object, props, function(value, path) { + return predicate(value, path[0]); + }); + } + + /** + * This method is like `_.get` except that if the resolved value is a + * function it's invoked with the `this` binding of its parent object and + * its result is returned. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category Object + * @param {Object} object The object to query. + * @param {Array|string} path The path of the property to resolve. + * @param {*} [defaultValue] The value returned for `undefined` resolved values. + * @returns {*} Returns the resolved value. + * @example + * + * var object = { 'a': [{ 'b': { 'c1': 3, 'c2': _.constant(4) } }] }; + * + * _.result(object, 'a[0].b.c1'); + * // => 3 + * + * _.result(object, 'a[0].b.c2'); + * // => 4 + * + * _.result(object, 'a[0].b.c3', 'default'); + * // => 'default' + * + * _.result(object, 'a[0].b.c3', _.constant('default')); + * // => 'default' + */ + function result(object, path, defaultValue) { + path = castPath(path, object); + + var index = -1, + length = path.length; + + // Ensure the loop is entered when path is empty. + if (!length) { + length = 1; + object = undefined; + } + while (++index < length) { + var value = object == null ? undefined : object[toKey(path[index])]; + if (value === undefined) { + index = length; + value = defaultValue; + } + object = isFunction(value) ? value.call(object) : value; + } + return object; + } + + /** + * Sets the value at `path` of `object`. If a portion of `path` doesn't exist, + * it's created. Arrays are created for missing index properties while objects + * are created for all other missing properties. Use `_.setWith` to customize + * `path` creation. + * + * **Note:** This method mutates `object`. + * + * @static + * @memberOf _ + * @since 3.7.0 + * @category Object + * @param {Object} object The object to modify. + * @param {Array|string} path The path of the property to set. + * @param {*} value The value to set. + * @returns {Object} Returns `object`. + * @example + * + * var object = { 'a': [{ 'b': { 'c': 3 } }] }; + * + * _.set(object, 'a[0].b.c', 4); + * console.log(object.a[0].b.c); + * // => 4 + * + * _.set(object, ['x', '0', 'y', 'z'], 5); + * console.log(object.x[0].y.z); + * // => 5 + */ + function set(object, path, value) { + return object == null ? object : baseSet(object, path, value); + } + + /** + * This method is like `_.set` except that it accepts `customizer` which is + * invoked to produce the objects of `path`. If `customizer` returns `undefined` + * path creation is handled by the method instead. The `customizer` is invoked + * with three arguments: (nsValue, key, nsObject). + * + * **Note:** This method mutates `object`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Object + * @param {Object} object The object to modify. + * @param {Array|string} path The path of the property to set. + * @param {*} value The value to set. + * @param {Function} [customizer] The function to customize assigned values. + * @returns {Object} Returns `object`. + * @example + * + * var object = {}; + * + * _.setWith(object, '[0][1]', 'a', Object); + * // => { '0': { '1': 'a' } } + */ + function setWith(object, path, value, customizer) { + customizer = typeof customizer == 'function' ? customizer : undefined; + return object == null ? object : baseSet(object, path, value, customizer); + } + + /** + * Creates an array of own enumerable string keyed-value pairs for `object` + * which can be consumed by `_.fromPairs`. If `object` is a map or set, its + * entries are returned. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @alias entries + * @category Object + * @param {Object} object The object to query. + * @returns {Array} Returns the key-value pairs. + * @example + * + * function Foo() { + * this.a = 1; + * this.b = 2; + * } + * + * Foo.prototype.c = 3; + * + * _.toPairs(new Foo); + * // => [['a', 1], ['b', 2]] (iteration order is not guaranteed) + */ + var toPairs = createToPairs(keys); + + /** + * Creates an array of own and inherited enumerable string keyed-value pairs + * for `object` which can be consumed by `_.fromPairs`. If `object` is a map + * or set, its entries are returned. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @alias entriesIn + * @category Object + * @param {Object} object The object to query. + * @returns {Array} Returns the key-value pairs. + * @example + * + * function Foo() { + * this.a = 1; + * this.b = 2; + * } + * + * Foo.prototype.c = 3; + * + * _.toPairsIn(new Foo); + * // => [['a', 1], ['b', 2], ['c', 3]] (iteration order is not guaranteed) + */ + var toPairsIn = createToPairs(keysIn); + + /** + * An alternative to `_.reduce`; this method transforms `object` to a new + * `accumulator` object which is the result of running each of its own + * enumerable string keyed properties thru `iteratee`, with each invocation + * potentially mutating the `accumulator` object. If `accumulator` is not + * provided, a new object with the same `[[Prototype]]` will be used. The + * iteratee is invoked with four arguments: (accumulator, value, key, object). + * Iteratee functions may exit iteration early by explicitly returning `false`. + * + * @static + * @memberOf _ + * @since 1.3.0 + * @category Object + * @param {Object} object The object to iterate over. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. + * @param {*} [accumulator] The custom accumulator value. + * @returns {*} Returns the accumulated value. + * @example + * + * _.transform([2, 3, 4], function(result, n) { + * result.push(n *= n); + * return n % 2 == 0; + * }, []); + * // => [4, 9] + * + * _.transform({ 'a': 1, 'b': 2, 'c': 1 }, function(result, value, key) { + * (result[value] || (result[value] = [])).push(key); + * }, {}); + * // => { '1': ['a', 'c'], '2': ['b'] } + */ + function transform(object, iteratee, accumulator) { + var isArr = isArray(object), + isArrLike = isArr || isBuffer(object) || isTypedArray(object); + + iteratee = getIteratee(iteratee, 4); + if (accumulator == null) { + var Ctor = object && object.constructor; + if (isArrLike) { + accumulator = isArr ? new Ctor : []; + } + else if (isObject(object)) { + accumulator = isFunction(Ctor) ? baseCreate(getPrototype(object)) : {}; + } + else { + accumulator = {}; + } + } + (isArrLike ? arrayEach : baseForOwn)(object, function(value, index, object) { + return iteratee(accumulator, value, index, object); + }); + return accumulator; + } + + /** + * Removes the property at `path` of `object`. + * + * **Note:** This method mutates `object`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Object + * @param {Object} object The object to modify. + * @param {Array|string} path The path of the property to unset. + * @returns {boolean} Returns `true` if the property is deleted, else `false`. + * @example + * + * var object = { 'a': [{ 'b': { 'c': 7 } }] }; + * _.unset(object, 'a[0].b.c'); + * // => true + * + * console.log(object); + * // => { 'a': [{ 'b': {} }] }; + * + * _.unset(object, ['a', '0', 'b', 'c']); + * // => true + * + * console.log(object); + * // => { 'a': [{ 'b': {} }] }; + */ + function unset(object, path) { + return object == null ? true : baseUnset(object, path); + } + + /** + * This method is like `_.set` except that accepts `updater` to produce the + * value to set. Use `_.updateWith` to customize `path` creation. The `updater` + * is invoked with one argument: (value). + * + * **Note:** This method mutates `object`. + * + * @static + * @memberOf _ + * @since 4.6.0 + * @category Object + * @param {Object} object The object to modify. + * @param {Array|string} path The path of the property to set. + * @param {Function} updater The function to produce the updated value. + * @returns {Object} Returns `object`. + * @example + * + * var object = { 'a': [{ 'b': { 'c': 3 } }] }; + * + * _.update(object, 'a[0].b.c', function(n) { return n * n; }); + * console.log(object.a[0].b.c); + * // => 9 + * + * _.update(object, 'x[0].y.z', function(n) { return n ? n + 1 : 0; }); + * console.log(object.x[0].y.z); + * // => 0 + */ + function update(object, path, updater) { + return object == null ? object : baseUpdate(object, path, castFunction(updater)); + } + + /** + * This method is like `_.update` except that it accepts `customizer` which is + * invoked to produce the objects of `path`. If `customizer` returns `undefined` + * path creation is handled by the method instead. The `customizer` is invoked + * with three arguments: (nsValue, key, nsObject). + * + * **Note:** This method mutates `object`. + * + * @static + * @memberOf _ + * @since 4.6.0 + * @category Object + * @param {Object} object The object to modify. + * @param {Array|string} path The path of the property to set. + * @param {Function} updater The function to produce the updated value. + * @param {Function} [customizer] The function to customize assigned values. + * @returns {Object} Returns `object`. + * @example + * + * var object = {}; + * + * _.updateWith(object, '[0][1]', _.constant('a'), Object); + * // => { '0': { '1': 'a' } } + */ + function updateWith(object, path, updater, customizer) { + customizer = typeof customizer == 'function' ? customizer : undefined; + return object == null ? object : baseUpdate(object, path, castFunction(updater), customizer); + } + + /** + * Creates an array of the own enumerable string keyed property values of `object`. + * + * **Note:** Non-object values are coerced to objects. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category Object + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property values. + * @example + * + * function Foo() { + * this.a = 1; + * this.b = 2; + * } + * + * Foo.prototype.c = 3; + * + * _.values(new Foo); + * // => [1, 2] (iteration order is not guaranteed) + * + * _.values('hi'); + * // => ['h', 'i'] + */ + function values(object) { + return object == null ? [] : baseValues(object, keys(object)); + } + + /** + * Creates an array of the own and inherited enumerable string keyed property + * values of `object`. + * + * **Note:** Non-object values are coerced to objects. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Object + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property values. + * @example + * + * function Foo() { + * this.a = 1; + * this.b = 2; + * } + * + * Foo.prototype.c = 3; + * + * _.valuesIn(new Foo); + * // => [1, 2, 3] (iteration order is not guaranteed) + */ + function valuesIn(object) { + return object == null ? [] : baseValues(object, keysIn(object)); + } + + /*------------------------------------------------------------------------*/ + + /** + * Clamps `number` within the inclusive `lower` and `upper` bounds. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Number + * @param {number} number The number to clamp. + * @param {number} [lower] The lower bound. + * @param {number} upper The upper bound. + * @returns {number} Returns the clamped number. + * @example + * + * _.clamp(-10, -5, 5); + * // => -5 + * + * _.clamp(10, -5, 5); + * // => 5 + */ + function clamp(number, lower, upper) { + if (upper === undefined) { + upper = lower; + lower = undefined; + } + if (upper !== undefined) { + upper = toNumber(upper); + upper = upper === upper ? upper : 0; + } + if (lower !== undefined) { + lower = toNumber(lower); + lower = lower === lower ? lower : 0; + } + return baseClamp(toNumber(number), lower, upper); + } + + /** + * Checks if `n` is between `start` and up to, but not including, `end`. If + * `end` is not specified, it's set to `start` with `start` then set to `0`. + * If `start` is greater than `end` the params are swapped to support + * negative ranges. + * + * @static + * @memberOf _ + * @since 3.3.0 + * @category Number + * @param {number} number The number to check. + * @param {number} [start=0] The start of the range. + * @param {number} end The end of the range. + * @returns {boolean} Returns `true` if `number` is in the range, else `false`. + * @see _.range, _.rangeRight + * @example + * + * _.inRange(3, 2, 4); + * // => true + * + * _.inRange(4, 8); + * // => true + * + * _.inRange(4, 2); + * // => false + * + * _.inRange(2, 2); + * // => false + * + * _.inRange(1.2, 2); + * // => true + * + * _.inRange(5.2, 4); + * // => false + * + * _.inRange(-3, -2, -6); + * // => true + */ + function inRange(number, start, end) { + start = toFinite(start); + if (end === undefined) { + end = start; + start = 0; + } else { + end = toFinite(end); + } + number = toNumber(number); + return baseInRange(number, start, end); + } + + /** + * Produces a random number between the inclusive `lower` and `upper` bounds. + * If only one argument is provided a number between `0` and the given number + * is returned. If `floating` is `true`, or either `lower` or `upper` are + * floats, a floating-point number is returned instead of an integer. + * + * **Note:** JavaScript follows the IEEE-754 standard for resolving + * floating-point values which can produce unexpected results. + * + * @static + * @memberOf _ + * @since 0.7.0 + * @category Number + * @param {number} [lower=0] The lower bound. + * @param {number} [upper=1] The upper bound. + * @param {boolean} [floating] Specify returning a floating-point number. + * @returns {number} Returns the random number. + * @example + * + * _.random(0, 5); + * // => an integer between 0 and 5 + * + * _.random(5); + * // => also an integer between 0 and 5 + * + * _.random(5, true); + * // => a floating-point number between 0 and 5 + * + * _.random(1.2, 5.2); + * // => a floating-point number between 1.2 and 5.2 + */ + function random(lower, upper, floating) { + if (floating && typeof floating != 'boolean' && isIterateeCall(lower, upper, floating)) { + upper = floating = undefined; + } + if (floating === undefined) { + if (typeof upper == 'boolean') { + floating = upper; + upper = undefined; + } + else if (typeof lower == 'boolean') { + floating = lower; + lower = undefined; + } + } + if (lower === undefined && upper === undefined) { + lower = 0; + upper = 1; + } + else { + lower = toFinite(lower); + if (upper === undefined) { + upper = lower; + lower = 0; + } else { + upper = toFinite(upper); + } + } + if (lower > upper) { + var temp = lower; + lower = upper; + upper = temp; + } + if (floating || lower % 1 || upper % 1) { + var rand = nativeRandom(); + return nativeMin(lower + (rand * (upper - lower + freeParseFloat('1e-' + ((rand + '').length - 1)))), upper); + } + return baseRandom(lower, upper); + } + + /*------------------------------------------------------------------------*/ + + /** + * Converts `string` to [camel case](https://en.wikipedia.org/wiki/CamelCase). + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category String + * @param {string} [string=''] The string to convert. + * @returns {string} Returns the camel cased string. + * @example + * + * _.camelCase('Foo Bar'); + * // => 'fooBar' + * + * _.camelCase('--foo-bar--'); + * // => 'fooBar' + * + * _.camelCase('__FOO_BAR__'); + * // => 'fooBar' + */ + var camelCase = createCompounder(function(result, word, index) { + word = word.toLowerCase(); + return result + (index ? capitalize(word) : word); + }); + + /** + * Converts the first character of `string` to upper case and the remaining + * to lower case. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category String + * @param {string} [string=''] The string to capitalize. + * @returns {string} Returns the capitalized string. + * @example + * + * _.capitalize('FRED'); + * // => 'Fred' + */ + function capitalize(string) { + return upperFirst(toString(string).toLowerCase()); + } + + /** + * Deburrs `string` by converting + * [Latin-1 Supplement](https://en.wikipedia.org/wiki/Latin-1_Supplement_(Unicode_block)#Character_table) + * and [Latin Extended-A](https://en.wikipedia.org/wiki/Latin_Extended-A) + * letters to basic Latin letters and removing + * [combining diacritical marks](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks). + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category String + * @param {string} [string=''] The string to deburr. + * @returns {string} Returns the deburred string. + * @example + * + * _.deburr('déjà vu'); + * // => 'deja vu' + */ + function deburr(string) { + string = toString(string); + return string && string.replace(reLatin, deburrLetter).replace(reComboMark, ''); + } + + /** + * Checks if `string` ends with the given target string. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category String + * @param {string} [string=''] The string to inspect. + * @param {string} [target] The string to search for. + * @param {number} [position=string.length] The position to search up to. + * @returns {boolean} Returns `true` if `string` ends with `target`, + * else `false`. + * @example + * + * _.endsWith('abc', 'c'); + * // => true + * + * _.endsWith('abc', 'b'); + * // => false + * + * _.endsWith('abc', 'b', 2); + * // => true + */ + function endsWith(string, target, position) { + string = toString(string); + target = baseToString(target); + + var length = string.length; + position = position === undefined + ? length + : baseClamp(toInteger(position), 0, length); + + var end = position; + position -= target.length; + return position >= 0 && string.slice(position, end) == target; + } + + /** + * Converts the characters "&", "<", ">", '"', and "'" in `string` to their + * corresponding HTML entities. + * + * **Note:** No other characters are escaped. To escape additional + * characters use a third-party library like [_he_](https://mths.be/he). + * + * Though the ">" character is escaped for symmetry, characters like + * ">" and "/" don't need escaping in HTML and have no special meaning + * unless they're part of a tag or unquoted attribute value. See + * [Mathias Bynens's article](https://mathiasbynens.be/notes/ambiguous-ampersands) + * (under "semi-related fun fact") for more details. + * + * When working with HTML you should always + * [quote attribute values](http://wonko.com/post/html-escaping) to reduce + * XSS vectors. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category String + * @param {string} [string=''] The string to escape. + * @returns {string} Returns the escaped string. + * @example + * + * _.escape('fred, barney, & pebbles'); + * // => 'fred, barney, & pebbles' + */ + function escape(string) { + string = toString(string); + return (string && reHasUnescapedHtml.test(string)) + ? string.replace(reUnescapedHtml, escapeHtmlChar) + : string; + } + + /** + * Escapes the `RegExp` special characters "^", "$", "\", ".", "*", "+", + * "?", "(", ")", "[", "]", "{", "}", and "|" in `string`. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category String + * @param {string} [string=''] The string to escape. + * @returns {string} Returns the escaped string. + * @example + * + * _.escapeRegExp('[lodash](https://lodash.com/)'); + * // => '\[lodash\]\(https://lodash\.com/\)' + */ + function escapeRegExp(string) { + string = toString(string); + return (string && reHasRegExpChar.test(string)) + ? string.replace(reRegExpChar, '\\$&') + : string; + } + + /** + * Converts `string` to + * [kebab case](https://en.wikipedia.org/wiki/Letter_case#Special_case_styles). + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category String + * @param {string} [string=''] The string to convert. + * @returns {string} Returns the kebab cased string. + * @example + * + * _.kebabCase('Foo Bar'); + * // => 'foo-bar' + * + * _.kebabCase('fooBar'); + * // => 'foo-bar' + * + * _.kebabCase('__FOO_BAR__'); + * // => 'foo-bar' + */ + var kebabCase = createCompounder(function(result, word, index) { + return result + (index ? '-' : '') + word.toLowerCase(); + }); + + /** + * Converts `string`, as space separated words, to lower case. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category String + * @param {string} [string=''] The string to convert. + * @returns {string} Returns the lower cased string. + * @example + * + * _.lowerCase('--Foo-Bar--'); + * // => 'foo bar' + * + * _.lowerCase('fooBar'); + * // => 'foo bar' + * + * _.lowerCase('__FOO_BAR__'); + * // => 'foo bar' + */ + var lowerCase = createCompounder(function(result, word, index) { + return result + (index ? ' ' : '') + word.toLowerCase(); + }); + + /** + * Converts the first character of `string` to lower case. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category String + * @param {string} [string=''] The string to convert. + * @returns {string} Returns the converted string. + * @example + * + * _.lowerFirst('Fred'); + * // => 'fred' + * + * _.lowerFirst('FRED'); + * // => 'fRED' + */ + var lowerFirst = createCaseFirst('toLowerCase'); + + /** + * Pads `string` on the left and right sides if it's shorter than `length`. + * Padding characters are truncated if they can't be evenly divided by `length`. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category String + * @param {string} [string=''] The string to pad. + * @param {number} [length=0] The padding length. + * @param {string} [chars=' '] The string used as padding. + * @returns {string} Returns the padded string. + * @example + * + * _.pad('abc', 8); + * // => ' abc ' + * + * _.pad('abc', 8, '_-'); + * // => '_-abc_-_' + * + * _.pad('abc', 3); + * // => 'abc' + */ + function pad(string, length, chars) { + string = toString(string); + length = toInteger(length); + + var strLength = length ? stringSize(string) : 0; + if (!length || strLength >= length) { + return string; + } + var mid = (length - strLength) / 2; + return ( + createPadding(nativeFloor(mid), chars) + + string + + createPadding(nativeCeil(mid), chars) + ); + } + + /** + * Pads `string` on the right side if it's shorter than `length`. Padding + * characters are truncated if they exceed `length`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category String + * @param {string} [string=''] The string to pad. + * @param {number} [length=0] The padding length. + * @param {string} [chars=' '] The string used as padding. + * @returns {string} Returns the padded string. + * @example + * + * _.padEnd('abc', 6); + * // => 'abc ' + * + * _.padEnd('abc', 6, '_-'); + * // => 'abc_-_' + * + * _.padEnd('abc', 3); + * // => 'abc' + */ + function padEnd(string, length, chars) { + string = toString(string); + length = toInteger(length); + + var strLength = length ? stringSize(string) : 0; + return (length && strLength < length) + ? (string + createPadding(length - strLength, chars)) + : string; + } + + /** + * Pads `string` on the left side if it's shorter than `length`. Padding + * characters are truncated if they exceed `length`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category String + * @param {string} [string=''] The string to pad. + * @param {number} [length=0] The padding length. + * @param {string} [chars=' '] The string used as padding. + * @returns {string} Returns the padded string. + * @example + * + * _.padStart('abc', 6); + * // => ' abc' + * + * _.padStart('abc', 6, '_-'); + * // => '_-_abc' + * + * _.padStart('abc', 3); + * // => 'abc' + */ + function padStart(string, length, chars) { + string = toString(string); + length = toInteger(length); + + var strLength = length ? stringSize(string) : 0; + return (length && strLength < length) + ? (createPadding(length - strLength, chars) + string) + : string; + } + + /** + * Converts `string` to an integer of the specified radix. If `radix` is + * `undefined` or `0`, a `radix` of `10` is used unless `value` is a + * hexadecimal, in which case a `radix` of `16` is used. + * + * **Note:** This method aligns with the + * [ES5 implementation](https://es5.github.io/#x15.1.2.2) of `parseInt`. + * + * @static + * @memberOf _ + * @since 1.1.0 + * @category String + * @param {string} string The string to convert. + * @param {number} [radix=10] The radix to interpret `value` by. + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. + * @returns {number} Returns the converted integer. + * @example + * + * _.parseInt('08'); + * // => 8 + * + * _.map(['6', '08', '10'], _.parseInt); + * // => [6, 8, 10] + */ + function parseInt(string, radix, guard) { + if (guard || radix == null) { + radix = 0; + } else if (radix) { + radix = +radix; + } + return nativeParseInt(toString(string).replace(reTrimStart, ''), radix || 0); + } + + /** + * Repeats the given string `n` times. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category String + * @param {string} [string=''] The string to repeat. + * @param {number} [n=1] The number of times to repeat the string. + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. + * @returns {string} Returns the repeated string. + * @example + * + * _.repeat('*', 3); + * // => '***' + * + * _.repeat('abc', 2); + * // => 'abcabc' + * + * _.repeat('abc', 0); + * // => '' + */ + function repeat(string, n, guard) { + if ((guard ? isIterateeCall(string, n, guard) : n === undefined)) { + n = 1; + } else { + n = toInteger(n); + } + return baseRepeat(toString(string), n); + } + + /** + * Replaces matches for `pattern` in `string` with `replacement`. + * + * **Note:** This method is based on + * [`String#replace`](https://mdn.io/String/replace). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category String + * @param {string} [string=''] The string to modify. + * @param {RegExp|string} pattern The pattern to replace. + * @param {Function|string} replacement The match replacement. + * @returns {string} Returns the modified string. + * @example + * + * _.replace('Hi Fred', 'Fred', 'Barney'); + * // => 'Hi Barney' + */ + function replace() { + var args = arguments, + string = toString(args[0]); + + return args.length < 3 ? string : string.replace(args[1], args[2]); + } + + /** + * Converts `string` to + * [snake case](https://en.wikipedia.org/wiki/Snake_case). + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category String + * @param {string} [string=''] The string to convert. + * @returns {string} Returns the snake cased string. + * @example + * + * _.snakeCase('Foo Bar'); + * // => 'foo_bar' + * + * _.snakeCase('fooBar'); + * // => 'foo_bar' + * + * _.snakeCase('--FOO-BAR--'); + * // => 'foo_bar' + */ + var snakeCase = createCompounder(function(result, word, index) { + return result + (index ? '_' : '') + word.toLowerCase(); + }); + + /** + * Splits `string` by `separator`. + * + * **Note:** This method is based on + * [`String#split`](https://mdn.io/String/split). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category String + * @param {string} [string=''] The string to split. + * @param {RegExp|string} separator The separator pattern to split by. + * @param {number} [limit] The length to truncate results to. + * @returns {Array} Returns the string segments. + * @example + * + * _.split('a-b-c', '-', 2); + * // => ['a', 'b'] + */ + function split(string, separator, limit) { + if (limit && typeof limit != 'number' && isIterateeCall(string, separator, limit)) { + separator = limit = undefined; + } + limit = limit === undefined ? MAX_ARRAY_LENGTH : limit >>> 0; + if (!limit) { + return []; + } + string = toString(string); + if (string && ( + typeof separator == 'string' || + (separator != null && !isRegExp(separator)) + )) { + separator = baseToString(separator); + if (!separator && hasUnicode(string)) { + return castSlice(stringToArray(string), 0, limit); + } + } + return string.split(separator, limit); + } + + /** + * Converts `string` to + * [start case](https://en.wikipedia.org/wiki/Letter_case#Stylistic_or_specialised_usage). + * + * @static + * @memberOf _ + * @since 3.1.0 + * @category String + * @param {string} [string=''] The string to convert. + * @returns {string} Returns the start cased string. + * @example + * + * _.startCase('--foo-bar--'); + * // => 'Foo Bar' + * + * _.startCase('fooBar'); + * // => 'Foo Bar' + * + * _.startCase('__FOO_BAR__'); + * // => 'FOO BAR' + */ + var startCase = createCompounder(function(result, word, index) { + return result + (index ? ' ' : '') + upperFirst(word); + }); + + /** + * Checks if `string` starts with the given target string. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category String + * @param {string} [string=''] The string to inspect. + * @param {string} [target] The string to search for. + * @param {number} [position=0] The position to search from. + * @returns {boolean} Returns `true` if `string` starts with `target`, + * else `false`. + * @example + * + * _.startsWith('abc', 'a'); + * // => true + * + * _.startsWith('abc', 'b'); + * // => false + * + * _.startsWith('abc', 'b', 1); + * // => true + */ + function startsWith(string, target, position) { + string = toString(string); + position = position == null + ? 0 + : baseClamp(toInteger(position), 0, string.length); + + target = baseToString(target); + return string.slice(position, position + target.length) == target; + } + + /** + * Creates a compiled template function that can interpolate data properties + * in "interpolate" delimiters, HTML-escape interpolated data properties in + * "escape" delimiters, and execute JavaScript in "evaluate" delimiters. Data + * properties may be accessed as free variables in the template. If a setting + * object is given, it takes precedence over `_.templateSettings` values. + * + * **Note:** In the development build `_.template` utilizes + * [sourceURLs](http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/#toc-sourceurl) + * for easier debugging. + * + * For more information on precompiling templates see + * [lodash's custom builds documentation](https://lodash.com/custom-builds). + * + * For more information on Chrome extension sandboxes see + * [Chrome's extensions documentation](https://developer.chrome.com/extensions/sandboxingEval). + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category String + * @param {string} [string=''] The template string. + * @param {Object} [options={}] The options object. + * @param {RegExp} [options.escape=_.templateSettings.escape] + * The HTML "escape" delimiter. + * @param {RegExp} [options.evaluate=_.templateSettings.evaluate] + * The "evaluate" delimiter. + * @param {Object} [options.imports=_.templateSettings.imports] + * An object to import into the template as free variables. + * @param {RegExp} [options.interpolate=_.templateSettings.interpolate] + * The "interpolate" delimiter. + * @param {string} [options.sourceURL='lodash.templateSources[n]'] + * The sourceURL of the compiled template. + * @param {string} [options.variable='obj'] + * The data object variable name. + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. + * @returns {Function} Returns the compiled template function. + * @example + * + * // Use the "interpolate" delimiter to create a compiled template. + * var compiled = _.template('hello <%= user %>!'); + * compiled({ 'user': 'fred' }); + * // => 'hello fred!' + * + * // Use the HTML "escape" delimiter to escape data property values. + * var compiled = _.template('<%- value %>'); + * compiled({ 'value': '