From 705166b5d5f08a2d05b2d317e96869dfc7001e18 Mon Sep 17 00:00:00 2001 From: snehabandla Date: Fri, 5 Dec 2025 14:57:11 -0800 Subject: [PATCH 1/2] Adding in task and tests for it --- Tasks/BicepDeployV0/README.md | 230 ++ .../resources.resjson/en-US/resources.resjson | 87 + Tasks/BicepDeployV0/Tests/L0.ts | 167 ++ .../Tests/deploymentsCreateFailures.ts | 46 + .../Tests/deploymentsFailures.ts | 37 + .../Tests/deploymentsInlineYamlParams.ts | 59 + .../Tests/deploymentsValidation.ts | 54 + .../BicepDeployV0/Tests/deploymentsWhatIf.ts | 40 + .../Tests/files/basic-sub/main.bicep | 9 + .../Tests/files/basic-sub/main.bicepparam | 8 + .../Tests/files/basic-sub/main.json | 37 + .../files/basic-sub/main.parameters.json | 18 + .../Tests/files/basic/main.bicep | 7 + .../Tests/files/basic/main.bicepparam | 8 + .../BicepDeployV0/Tests/files/basic/main.json | 37 + .../Tests/files/basic/main.parameters.json | 18 + .../Tests/files/deployerror/main.bicep | 8 + .../Tests/files/deployerror/main.bicepparam | 3 + .../Tests/files/validationerror/main.bicep | 10 + .../files/validationerror/main.bicepparam | 3 + Tasks/BicepDeployV0/Tests/package-lock.json | 2599 +++++++++++++++++ Tasks/BicepDeployV0/Tests/package.json | 27 + Tasks/BicepDeployV0/Tests/runErrorObject.ts | 29 + Tasks/BicepDeployV0/Tests/runStringError.ts | 29 + .../Tests/stacksCreateFailures.ts | 53 + Tasks/BicepDeployV0/Tests/stacksFailures.ts | 41 + .../Tests/stacksInlineYamlParams.ts | 62 + Tasks/BicepDeployV0/Tests/stacksValidation.ts | 57 + Tasks/BicepDeployV0/Tests/utils.ts | 38 + Tasks/BicepDeployV0/icon.png | Bin 0 -> 15797 bytes Tasks/BicepDeployV0/icon.svg | 67 + Tasks/BicepDeployV0/logging.ts | 62 + Tasks/BicepDeployV0/main.ts | 35 + Tasks/BicepDeployV0/package-lock.json | 499 ++++ Tasks/BicepDeployV0/package.json | 28 + Tasks/BicepDeployV0/task.json | 399 +++ Tasks/BicepDeployV0/task.loc.json | 402 +++ Tasks/BicepDeployV0/taskIO.ts | 52 + Tasks/BicepDeployV0/tsconfig.json | 9 + make-options.json | 2 + 40 files changed, 5376 insertions(+) create mode 100644 Tasks/BicepDeployV0/README.md create mode 100644 Tasks/BicepDeployV0/Strings/resources.resjson/en-US/resources.resjson create mode 100644 Tasks/BicepDeployV0/Tests/L0.ts create mode 100644 Tasks/BicepDeployV0/Tests/deploymentsCreateFailures.ts create mode 100644 Tasks/BicepDeployV0/Tests/deploymentsFailures.ts create mode 100644 Tasks/BicepDeployV0/Tests/deploymentsInlineYamlParams.ts create mode 100644 Tasks/BicepDeployV0/Tests/deploymentsValidation.ts create mode 100644 Tasks/BicepDeployV0/Tests/deploymentsWhatIf.ts create mode 100644 Tasks/BicepDeployV0/Tests/files/basic-sub/main.bicep create mode 100644 Tasks/BicepDeployV0/Tests/files/basic-sub/main.bicepparam create mode 100644 Tasks/BicepDeployV0/Tests/files/basic-sub/main.json create mode 100644 Tasks/BicepDeployV0/Tests/files/basic-sub/main.parameters.json create mode 100644 Tasks/BicepDeployV0/Tests/files/basic/main.bicep create mode 100644 Tasks/BicepDeployV0/Tests/files/basic/main.bicepparam create mode 100644 Tasks/BicepDeployV0/Tests/files/basic/main.json create mode 100644 Tasks/BicepDeployV0/Tests/files/basic/main.parameters.json create mode 100644 Tasks/BicepDeployV0/Tests/files/deployerror/main.bicep create mode 100644 Tasks/BicepDeployV0/Tests/files/deployerror/main.bicepparam create mode 100644 Tasks/BicepDeployV0/Tests/files/validationerror/main.bicep create mode 100644 Tasks/BicepDeployV0/Tests/files/validationerror/main.bicepparam create mode 100644 Tasks/BicepDeployV0/Tests/package-lock.json create mode 100644 Tasks/BicepDeployV0/Tests/package.json create mode 100644 Tasks/BicepDeployV0/Tests/runErrorObject.ts create mode 100644 Tasks/BicepDeployV0/Tests/runStringError.ts create mode 100644 Tasks/BicepDeployV0/Tests/stacksCreateFailures.ts create mode 100644 Tasks/BicepDeployV0/Tests/stacksFailures.ts create mode 100644 Tasks/BicepDeployV0/Tests/stacksInlineYamlParams.ts create mode 100644 Tasks/BicepDeployV0/Tests/stacksValidation.ts create mode 100644 Tasks/BicepDeployV0/Tests/utils.ts create mode 100644 Tasks/BicepDeployV0/icon.png create mode 100644 Tasks/BicepDeployV0/icon.svg create mode 100644 Tasks/BicepDeployV0/logging.ts create mode 100644 Tasks/BicepDeployV0/main.ts create mode 100644 Tasks/BicepDeployV0/package-lock.json create mode 100644 Tasks/BicepDeployV0/package.json create mode 100644 Tasks/BicepDeployV0/task.json create mode 100644 Tasks/BicepDeployV0/task.loc.json create mode 100644 Tasks/BicepDeployV0/taskIO.ts create mode 100644 Tasks/BicepDeployV0/tsconfig.json diff --git a/Tasks/BicepDeployV0/README.md b/Tasks/BicepDeployV0/README.md new file mode 100644 index 000000000000..1d03a054fa10 --- /dev/null +++ b/Tasks/BicepDeployV0/README.md @@ -0,0 +1,230 @@ +# Bicep Deploy Task + +## Overview + +The Bicep Deploy task is used to deploy and manage Azure resources using [Bicep](https://learn.microsoft.com/azure/azure-resource-manager/bicep/overview) files. Bicep is a domain-specific language (DSL) that uses declarative syntax to deploy Azure resources. This task supports both standard Azure deployments and [Azure Deployment Stacks](https://learn.microsoft.com/azure/azure-resource-manager/bicep/deployment-stacks), providing a simplified and more maintainable way to manage your Azure infrastructure as code. + +The task handles: +- Creating or updating Azure resources using Bicep templates +- Validating Bicep templates before deployment +- Previewing changes with What-If operations +- Managing deployment stacks with lifecycle policies +- Deleting deployments and deployment stacks +- Installing and managing Bicep CLI versions automatically + +## What's New in Version 1.0 + +- **Native Bicep Support**: Direct deployment from `.bicep` and `.bicepparam` files without requiring pre-compilation to ARM templates +- **Deployment Stacks**: Full support for Azure Deployment Stacks with deny settings, unmanaged resource policies, and lifecycle management +- **Automatic Bicep CLI Management**: Automatically downloads and caches the specified version of Bicep CLI +- **Cross-Platform**: Works with Windows, Linux, and macOS agents +- **Multiple Deployment Scopes**: Supports Resource Group, Subscription, Management Group, and Tenant scopes +- **What-If Operations**: Preview changes before applying them to your Azure environment +- **Flexible Parameter Input**: Support for inline YAML/JSON parameters and traditional parameter files +- **Output Masking**: Automatically mask sensitive outputs like secrets and connection strings + +## Prerequisites + +### Azure Subscription + +To deploy to Azure, an Azure subscription must be linked to Azure Pipelines using a service connection: + +1. Navigate to **Project Settings** → **Service connections** +2. Create a new service connection of type **Azure Resource Manager** +3. Choose authentication method: + - **Service Principal (automatic)** - Recommended for most scenarios + - **Service Principal (manual)** - For advanced configurations + - **Managed Identity** - For Azure-hosted agents with managed identities + - **Workload Identity Federation** - For enhanced security without secrets + +For troubleshooting service connections, refer to the [Azure RM endpoint documentation](https://learn.microsoft.com/azure/devops/pipelines/library/connect-to-azure). + +### Agent Requirements + +- **Minimum Agent Version**: 2.144.0 +- **Supported OS**: Windows, Linux, macOS +- **Node.js**: Node.js 20 or higher (included in modern hosted agents) +- **Bicep CLI**: Automatically installed by the task (no manual installation required) + +## Parameters + +The table below lists all task inputs. Required inputs are marked with **\***. + +### Core Parameters + +| Input Name | Required | Description | Allowed Values | +|------------|----------|-------------|----------------| +| `executionType` | Yes | Deployment model to use | `Deployment` (standard ARM deployment)
`Deployment Stack` (with lifecycle management) | +| `operation` | Yes | Action to perform | `Create or update`
`Validate`
`What-If (preview changes)` (Deployment only)
`Delete` | +| `deploymentScope` | Yes | Scope for the deployment | `Resource Group`
`Subscription`
`Management Group`
`Tenant` | +| `deploymentName` | No | Name for the deployment or stack. Auto-generated if not provided. | Any valid string | +| `connectedServiceName` | Yes | Azure Resource Manager service connection | Service connection name | +| `subscriptionId` | Conditional | Target Azure subscription (required for Resource Group and Subscription scopes) | Subscription ID | +| `resourceGroupName` | Conditional | Target resource group name (required for Resource Group scope) | Resource group name | +| `location` | Conditional | Azure region for deployment metadata (required for Subscription, Management Group, and Tenant scopes) | Azure region name | +| `tenantId` | Conditional | Azure AD tenant ID (required for Tenant scope) | Tenant GUID | +| `managementGroupId` | Conditional | Management group identifier (required for Management Group scope) | Management group ID | + +### Template Parameters + +| Input Name | Required | Description | Allowed Values | +|------------|----------|-------------|----------------| +| `templateFile` | No | Path to the Bicep template file | File path (`.bicep`) | +| `parametersFile` | No | Path to the parameters file | File path (`.json` or `.bicepparam`) | +| `overrideParameters` | No | Inline parameter values that override parameters file. Accepts JSON or YAML format. | JSON or YAML object | + +**Note**: Follow [Azure Naming Guidelines](https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/naming-and-tagging) when specifying resource names in parameters: + +| Resource Type | Length | Casing | Valid Characters | Globally Unique | +|--------------|--------|--------|------------------|-----------------| +| Storage Account | 3-24 | lowercase | alphanumeric | Yes | +| Resource Group | 2-64 | case-insensitive | alphanumeric, periods, underscores, hyphens, parentheses (cannot end in period) | No | +| Key Vault | 3-24 | case-insensitive | alphanumeric and hyphens | Yes | +| DNS Name | 3-63 | lowercase | alphanumeric and hyphens | Yes | + +### Deployment Stack Parameters + +These inputs apply when `executionType` is set to `Deployment Stack`. + +| Input Name | Required | Description | Allowed Values | +|------------|----------|-------------|----------------| +| `actionOnUnmanage` | Yes (for stacks) | Action for resources not in template | `Detach` (default - keep resources but remove from stack)
`Delete` (delete unmanaged resources) | +| `actionOnUnmanageResourceGroups` | No | Action for unmanaged resource groups (Subscription/Management Group/Tenant scopes only) | `Detach`
`Delete` | +| `actionOnUnmanageManagementGroups` | No | Action for unmanaged management groups (Tenant scope only) | `Detach`
`Delete` | +| `denySettingsMode` | Yes (for stacks) | Protection level against unauthorized changes | `None` (default - no protection)
`DenyDelete` (prevent deletion)
`DenyWriteAndDelete` (prevent modification and deletion) | +| `denySettingsExcludedActions` | No | Comma-separated list of Azure RBAC actions excluded from deny settings | e.g., `Microsoft.Compute/virtualMachines/write` | +| `denySettingsExcludedPrincipals` | No | Comma-separated list of Azure AD principal IDs excluded from deny settings | Azure AD principal GUIDs | +| `denySettingsApplyToChildScopes` | No | Apply deny settings to child resource scopes | `true`
`false` | +| `bypassStackOutOfSyncError` | No | Skip errors when stack is out of sync with Azure resources | `true`
`false` | + +### Advanced Parameters + +| Input Name | Required | Description | Allowed Values | +|------------|----------|-------------|----------------| +| `deploymentDescription` | No | Description text for the deployment or stack | Any string | +| `tags` | No | Tags as JSON or YAML object (Deployment Stack only) | JSON or YAML object | +| `bicepVersion` | No | Specific Bicep CLI version to use. Uses latest stable version if empty. | Version string (e.g., `0.30.23`) | +| `maskedOutputs` | No | Comma-separated list of output names to mask in logs for security | e.g., `connectionString,adminPassword` | +| `environment` | No | Target Azure cloud environment | `azureCloud` (default)
`azureChinaCloud`
`azureGermanCloud`
`azureUSGovernment` | +| `whatIfExcludeChangeTypes` | No | Comma-separated change types to exclude from What-If output (What-If operation only) | e.g., `NoChange,Ignore` | +| `validationLevel` | No | Template validation level (Validate and What-If operations only) | `provider`
`template`
`providerNoRbac` | + +## Usage Examples + +### Example 1: Basic Deployment + +```yaml +- task: BicepDeploy@1 + displayName: 'Deploy Bicep Template' + inputs: + azureResourceManagerConnection: 'Azure-Connection' + subscriptionId: '$(subscriptionId)' + resourceGroupName: 'my-resource-group' + templateFile: 'infra/main.bicep' + parametersFile: 'infra/main.bicepparam' +``` + +### Example 2: Deployment Stack + +```yaml +- task: BicepDeploy@1 + displayName: 'Deploy with Stack Protection' + inputs: + type: 'deploymentStack' + operation: 'create' + name: 'production-stack' + azureResourceManagerConnection: 'Azure-Connection' + subscriptionId: '$(subscriptionId)' + resourceGroupName: 'production-rg' + templateFile: 'infra/main.bicep' + parametersFile: 'infra/production.bicepparam' + actionOnUnmanageResources: 'delete' + denySettingsMode: 'denyWriteAndDelete' +``` + +### Example 3: Subscription-Level Deployment + +```yaml +- task: BicepDeploy@1 + displayName: 'Deploy Subscription Resources' + inputs: + scope: 'subscription' + azureResourceManagerConnection: 'Azure-Connection' + subscriptionId: '$(subscriptionId)' + location: 'eastus' + templateFile: 'infra/subscription.bicep' + parametersFile: 'infra/subscription.bicepparam' +``` + +## Deployment Outputs + +The task automatically creates pipeline variables for all outputs defined in your Bicep template. These variables can be used in subsequent tasks. + +**Defining Outputs in Bicep** + +Outputs are defined in the Bicep template using the `output` keyword. For example: + +```bicep +output storageAccountName string = storageAccount.name +output webAppUrl string = webApp.properties.defaultHostName +output intOutput int = 42 +output objectOutput object = { + key1: 'value1' + key2: 'value2' +} +``` + +For detailed guidance, refer to the [Bicep Outputs documentation](https://learn.microsoft.com/azure/azure-resource-manager/bicep/outputs). + +**How Outputs Become Available** + +After the deployment completes successfully, all outputs are automatically converted to Azure Pipelines variables with the same names as defined in your Bicep template. These variables are created at the pipeline level and can be directly referenced in subsequent tasks using the standard variable syntax: `$(outputName)`. + +### Accessing Outputs in PowerShell + +```yaml +- task: BicepDeploy@1 + displayName: 'Deploy Infrastructure' + inputs: + azureResourceManagerConnection: 'Azure-Connection' + subscriptionId: '$(subscriptionId)' + resourceGroupName: 'my-resource-group' + templateFile: 'infra/main.bicep' + +- task: PowerShell@2 + displayName: 'Use Deployment Outputs' + inputs: + targetType: 'inline' + script: | + Write-Host "Storage Account Name: $(storageAccountName)" + Write-Host "Web App URL: $(webAppUrl)" +``` + +### Accessing Outputs in Bash + +```yaml +- task: BicepDeploy@1 + displayName: 'Deploy Infrastructure' + inputs: + azureResourceManagerConnection: 'Azure-Connection' + subscriptionId: '$(subscriptionId)' + resourceGroupName: 'my-resource-group' + templateFile: 'infra/main.bicep' + +- task: Bash@3 + displayName: 'Use Deployment Outputs' + inputs: + targetType: 'inline' + script: | + echo "Storage Account Name: $(storageAccountName)" + echo "Web App URL: $(webAppUrl)" +``` + +## Feedback and Support + +Please report issues or request features at [Developer Community Forum](https://developercommunity.visualstudio.com/spaces/21/index.html). + +For Bicep-specific questions and issues, refer to: +- [Bicep Documentation](https://learn.microsoft.com/azure/azure-resource-manager/bicep/) +- [Bicep GitHub Repository](https://github.com/Azure/bicep) +- [Azure Deployment Stacks Documentation](https://learn.microsoft.com/azure/azure-resource-manager/bicep/deployment-stacks) \ No newline at end of file diff --git a/Tasks/BicepDeployV0/Strings/resources.resjson/en-US/resources.resjson b/Tasks/BicepDeployV0/Strings/resources.resjson/en-US/resources.resjson new file mode 100644 index 000000000000..a6cf46801ad8 --- /dev/null +++ b/Tasks/BicepDeployV0/Strings/resources.resjson/en-US/resources.resjson @@ -0,0 +1,87 @@ +{ + "loc.friendlyName": "Bicep Deploy", + "loc.helpMarkDown": "[Learn more about this task](https://aka.ms/bicepdeploytaskreadme)", + "loc.description": "Deploy and Manage Azure Resources using Bicep Files", + "loc.instanceNameFormat": "Bicep $(operation) $(name)", + "loc.group.displayName.AzureDetails": "Azure Details", + "loc.group.displayName.Template": "Template", + "loc.group.displayName.DeploymentStack": "Deployment Stack Options", + "loc.group.displayName.Advanced": "Advanced", + "loc.input.label.type": "Execution type", + "loc.input.help.type": "Specifies the execution type, deployment or deploymentStack.", + "loc.input.label.operation": "Operation", + "loc.input.help.operation": "Specifies the operation to perform.", + "loc.input.label.scope": "Deployment scope", + "loc.input.help.scope": "Specifies the scope at which resources are deployed.", + "loc.input.label.name": "Deployment name", + "loc.input.help.name": "Specifies the name of the deployment or deployment stack. If not provided, a default name will be generated.", + "loc.input.label.ConnectedServiceName": "Azure Resource Manager connection", + "loc.input.help.ConnectedServiceName": "Select the Azure Resource Manager service connection.", + "loc.input.label.subscriptionId": "Subscription", + "loc.input.help.subscriptionId": "Select the Azure subscription. Required if scope is subscription or resourceGroup.", + "loc.input.label.resourceGroupName": "Resource group", + "loc.input.help.resourceGroupName": "Provide the name of the resource group.", + "loc.input.label.location": "Location", + "loc.input.help.location": "Location to store deployment metadata. Required for subscription, managementGroup, and tenant scopes.", + "loc.input.label.tenantId": "Tenant ID", + "loc.input.help.tenantId": "Specifies the tenant ID. Required if scope is tenant.", + "loc.input.label.managementGroupId": "Management group ID", + "loc.input.help.managementGroupId": "Specifies the management group ID. Required if scope is managementGroup.", + "loc.input.label.templateFile": "Template file", + "loc.input.help.templateFile": "Specify the path to the Bicep template file (.bicep).", + "loc.input.label.parametersFile": "Parameters file", + "loc.input.help.parametersFile": "Specify the path to the parameters file (.json or .bicepparam).", + "loc.input.label.parameters": "Override parameters", + "loc.input.help.parameters": "Specify inline parameters as a JSON or YAML object. Example: {\"param1\": \"value1\", \"param2\": \"value2\"}", + "loc.input.label.actionOnUnmanageResources": "Action on unmanaged resources", + "loc.input.help.actionOnUnmanageResources": "Specifies the action to take on resources not defined in the template.", + "loc.input.label.actionOnUnmanageResourceGroups": "Action on unmanaged resource groups", + "loc.input.help.actionOnUnmanageResourceGroups": "Specifies the action to take on resource groups not defined in the template.", + "loc.input.label.actionOnUnmanageManagementGroups": "Action on unmanaged management groups", + "loc.input.help.actionOnUnmanageManagementGroups": "Specifies the action to take on management groups not defined in the template.", + "loc.input.label.denySettingsMode": "Deny settings mode", + "loc.input.help.denySettingsMode": "Specifies the mode of the deny settings to prevent unauthorized changes.", + "loc.input.label.denySettingsExcludedActions": "Deny settings excluded actions", + "loc.input.help.denySettingsExcludedActions": "Comma-separated list of actions to exclude from deny settings.", + "loc.input.label.denySettingsExcludedPrincipals": "Deny settings excluded principals", + "loc.input.help.denySettingsExcludedPrincipals": "Comma-separated list of principal IDs to exclude from deny settings.", + "loc.input.label.denySettingsApplyToChildScopes": "Apply deny settings to child scopes", + "loc.input.help.denySettingsApplyToChildScopes": "When enabled, deny settings also apply to child scopes of managed resources.", + "loc.input.label.bypassStackOutOfSyncError": "Bypass stack out of sync error", + "loc.input.help.bypassStackOutOfSyncError": "Bypass errors when the deployment stack is out of sync.", + "loc.input.label.description": "Description", + "loc.input.help.description": "Description for the deployment or deployment stack.", + "loc.input.label.tags": "Tags", + "loc.input.help.tags": "Tags as JSON or YAML object. Example: {\"Environment\": \"Development\", \"Owner\": \"TeamName\"}", + "loc.input.label.bicepVersion": "Bicep version", + "loc.input.help.bicepVersion": "Specify the version of Bicep to use (e.g., '0.38.5'). If not provided, the latest version will be used.", + "loc.input.label.maskedOutputs": "Masked outputs", + "loc.input.help.maskedOutputs": "Comma-separated list of output names to mask values for (e.g., secrets).", + "loc.input.label.environment": "Azure environment", + "loc.input.help.environment": "Specifies the Azure environment to use.", + "loc.input.label.whatIfExcludeChangeTypes": "What-If exclude change types", + "loc.input.help.whatIfExcludeChangeTypes": "Comma-separated list of change types to exclude from What-If operation (e.g., noChange, ignore).", + "loc.input.label.validationLevel": "Validation level", + "loc.input.help.validationLevel": "Validation level for deployment operations.", + "loc.messages.CreateFailed": "Create failed", + "loc.messages.ValidationFailed": "Validation failed", + "loc.messages.OperationFailed": "Operation failed", + "loc.messages.RequestFailedCorrelation": "Request failed. CorrelationId: %s", + "loc.messages.InputMustBeBoolean": "Input '%s' must be a boolean value", + "loc.messages.InputRequired": "Input '%s' is required but not provided", + "loc.messages.InputMustBeEnum": "Input '%s' must be one of the following values: '%s'", + "loc.messages.InputMustBeValidObject": "Input '%s' must be a valid JSON or YAML object", + "loc.messages.InputMustBeStringObject": "Input '%s' must be a valid JSON or YAML object containing only string values", + "loc.messages.LocationRequired": "Location is required", + "loc.messages.FailedToDetermineScope": "Failed to determine deployment scope from Bicep file.", + "loc.messages.UnsupportedParametersFile": "Unsupported parameters file type: %s", + "loc.messages.UnsupportedTemplateFile": "Unsupported template file type: %s", + "loc.messages.TemplateFileRequired": "Template file is required", + "loc.messages.InvalidChangeType": "Invalid ChangeType: %s", + "loc.messages.UnknownPropertyChangeType": "Unknown property change type: %s.", + "loc.messages.InvalidJsonValue": "Invalid JSON value: %s", + "loc.messages.DiagnosticsReturned": "Diagnostics returned by the API", + "loc.messages.BicepVersionInstalled": "Installed Bicep version %s to %s", + "loc.messages.TaskConfig": "Task config: %s", + "loc.messages.OperationSucceeded": "Operation completed successfully" +} \ No newline at end of file diff --git a/Tasks/BicepDeployV0/Tests/L0.ts b/Tasks/BicepDeployV0/Tests/L0.ts new file mode 100644 index 000000000000..645db997a468 --- /dev/null +++ b/Tasks/BicepDeployV0/Tests/L0.ts @@ -0,0 +1,167 @@ +import assert = require("assert"); +import path = require("path"); +import * as ttm from "azure-pipelines-task-lib/mock-test"; + +// Enable to improve traces while testing +// beforeEach(() => { +// process.env.TASK_TEST_TRACE = '1'; +// }); + +// Helper function to validate expected errors in test results +function assertHasErrors(tr: ttm.MockTestRunner, expectedErrors: string[], testName: string, expectedCount?: number) { + assert(tr.failed === true, "task should have failed"); + + assert(tr.errorIssues.length === expectedCount, `${testName}: should have exactly ${expectedCount} error message(s), but got ${tr.errorIssues.length}`); + expectedErrors.forEach(expectedError => { + const hasError = tr.errorIssues.some(e => e.includes(expectedError)); + assert(hasError, `${testName}: should have error containing '${expectedError}'`); + }); +} + +// Helper function to validate successful test results +function assertSucceeded(tr: ttm.MockTestRunner, testName: string) { + assert(tr.failed === false, `${testName}: task should not have failed`); + assert(tr.errorIssues.length === 0, `${testName}: should have no error issues`); + assert(tr.stdout.includes("OperationSucceeded"), `${testName}: should have success message`); +} + +describe("run error handling tests", function() { + this.timeout(20000); + it("sets the failed result using a string error", async function() { + let tp: string = path.join(__dirname, "runStringError.js"); + let tr: ttm.MockTestRunner = new ttm.MockTestRunner(tp); + + await tr.runAsync(); + + assertHasErrors(tr, ["This is an error!"], this.test!.title, 1); + }); + + it("sets the failed result using an Error", async function() { + let tp: string = path.join(__dirname, "runErrorObject.js"); + let tr: ttm.MockTestRunner = new ttm.MockTestRunner(tp); + + await tr.runAsync(); + + assertHasErrors(tr, ["This is an error!"], this.test!.title, 1); + }); +}); + +describe("deployments tests", function() { + // Set timeout for all tests in this suite (needed for Bicep installation) + this.timeout(90000); + + it("runs validation", async function() { + let tp: string = path.join(__dirname, "deploymentsValidation.js"); + + let tr: ttm.MockTestRunner = new ttm.MockTestRunner(tp); + + await tr.runAsync(); + + assertSucceeded(tr, this.test!.title); + }); + + it("runs create and handles failures", async function() { + let tp: string = path.join(__dirname, "deploymentsCreateFailures.js"); + + let tr: ttm.MockTestRunner = new ttm.MockTestRunner(tp); + + await tr.runAsync(); + + assertHasErrors(tr, [ + "RequestFailedCorrelation", + "DeploymentFailed", + "ResourceNotFound", + "CreateFailed" + ], this.test!.title, 3); + }); + + it("handles deployment failures", async function() { + let tp: string = path.join(__dirname, "deploymentsFailures.js"); + + let tr: ttm.MockTestRunner = new ttm.MockTestRunner(tp); + + await tr.runAsync(); + + assertHasErrors(tr, [ + "RequestFailedCorrelation", + "InvalidTemplateDeployment", + "StorageAccountAlreadyTaken", + "ValidationFailed" + ], this.test!.title, 3); + }); + + it("runs what-if", async function() { + let tp: string = path.join(__dirname, "deploymentsWhatIf.js"); + + let tr: ttm.MockTestRunner = new ttm.MockTestRunner(tp); + + await tr.runAsync(); + + assertSucceeded(tr, this.test!.title); + }); + + it("handles inline yaml parameters", async function() { + let tp: string = path.join(__dirname, "deploymentsInlineYamlParams.js"); + + let tr: ttm.MockTestRunner = new ttm.MockTestRunner(tp); + + await tr.runAsync(); + + assertSucceeded(tr, this.test!.title); + }); +}); + +describe("stacks tests", function() { + // Set timeout for all tests in this suite (needed for Bicep installation) + this.timeout(90000); + + it("runs validation", async function() { + let tp: string = path.join(__dirname, "stacksValidation.js"); + + let tr: ttm.MockTestRunner = new ttm.MockTestRunner(tp); + + await tr.runAsync(); + + assertSucceeded(tr, this.test!.title); + }); + + it("runs create and handles failures", async function() { + let tp: string = path.join(__dirname, "stacksCreateFailures.js"); + + let tr: ttm.MockTestRunner = new ttm.MockTestRunner(tp); + + await tr.runAsync(); + + assertHasErrors(tr, [ + "RequestFailedCorrelation", + "DeploymentStackDeploymentFailed", + "DeploymentFailed", + "CreateFailed" + ], this.test!.title, 3); + }); + + it("handles deployment failures", async function() { + let tp: string = path.join(__dirname, "stacksFailures.js"); + + let tr: ttm.MockTestRunner = new ttm.MockTestRunner(tp); + + await tr.runAsync(); + + assertHasErrors(tr, [ + "RequestFailedCorrelation", + "InvalidTemplateDeployment", + "StorageAccountAlreadyTaken", + "ValidationFailed" + ], this.test!.title, 3); + }); + + it("handles inline yaml parameters", async function() { + let tp: string = path.join(__dirname, "stacksInlineYamlParams.js"); + + let tr: ttm.MockTestRunner = new ttm.MockTestRunner(tp); + + await tr.runAsync(); + + assertSucceeded(tr, this.test!.title); + }); +}); \ No newline at end of file diff --git a/Tasks/BicepDeployV0/Tests/deploymentsCreateFailures.ts b/Tasks/BicepDeployV0/Tests/deploymentsCreateFailures.ts new file mode 100644 index 000000000000..a0783a991c81 --- /dev/null +++ b/Tasks/BicepDeployV0/Tests/deploymentsCreateFailures.ts @@ -0,0 +1,46 @@ +// Import and configure rewiremock BEFORE anything else loads +const rewiremock = require('rewiremock/node'); + +import * as path from 'path'; +import tmrm = require("azure-pipelines-task-lib/mock-run"); +import { environmentData, createMockRestError } from './utils'; + +// Mock deploymentCreate to throw deployment error +const mockDeploymentCreate = async () => { + const error = { + code: "DeploymentFailed", + target: `/subscriptions/${environmentData.subscriptionId}/resourceGroups/${environmentData.resourceGroupName}/providers/Microsoft.Resources/deployments/e2e-create`, + message: "At least one resource deployment operation failed. Please list deployment operations for details. Please see https://aka.ms/arm-deployment-operations for usage details.", + details: [ + { + code: "ResourceNotFound", + message: `The Resource 'Microsoft.Storage/storageAccounts/foo' under resource group '${environmentData.resourceGroupName}' was not found. For more details please go to https://aka.ms/ARMResourceNotFoundFix` + } + ] + }; + + throw createMockRestError('Deployment failed', error, undefined); +}; + +// Enable rewiremock globally +rewiremock.enable(); + +// Mock the deployments module - this will intercept ALL requires of it, including internal ones +rewiremock('@azure/bicep-deploy-common/deployments') + .callThrough() + .with({ deploymentCreate: mockDeploymentCreate }); + +let taskPath = path.join(__dirname, '..', 'main.js'); +let tr: tmrm.TaskMockRunner = new tmrm.TaskMockRunner(taskPath); + +tr.setInput('type', 'deployment'); +tr.setInput('operation', 'create'); +tr.setInput('name', 'test-create'); +tr.setInput('scope', 'resourceGroup'); +tr.setInput('subscriptionId', environmentData.subscriptionId); +tr.setInput('resourceGroupName', environmentData.resourceGroupName); +tr.setInput('parametersFile', path.join(__dirname, 'files', 'deployerror', 'main.bicepparam')); + +tr.run(); + +rewiremock.disable(); diff --git a/Tasks/BicepDeployV0/Tests/deploymentsFailures.ts b/Tasks/BicepDeployV0/Tests/deploymentsFailures.ts new file mode 100644 index 000000000000..d3f444865cbd --- /dev/null +++ b/Tasks/BicepDeployV0/Tests/deploymentsFailures.ts @@ -0,0 +1,37 @@ +// Import and configure rewiremock BEFORE anything else loads +const rewiremock = require('rewiremock/node'); + +import * as path from 'path'; +import * as crypto from 'crypto'; +import tmrm = require("azure-pipelines-task-lib/mock-run"); +import { environmentData, createMockRestError, createValidationFailureError } from './utils'; + +// Mock deploymentValidate to throw validation error +const mockDeploymentValidate = async () => { + const correlationId = crypto.randomUUID(); + const error = createValidationFailureError('e2e-validate', correlationId); + throw createMockRestError('Validation failed', error, correlationId); +}; + +// Enable rewiremock globally +rewiremock.enable(); + +// Mock the deployments module +rewiremock('@azure/bicep-deploy-common/deployments') + .callThrough() + .with({ deploymentValidate: mockDeploymentValidate }); + +let taskPath = path.join(__dirname, '..', 'main.js'); +let tr: tmrm.TaskMockRunner = new tmrm.TaskMockRunner(taskPath); + +tr.setInput('type', 'deployment'); +tr.setInput('operation', 'validate'); +tr.setInput('name', 'test-validate'); +tr.setInput('scope', 'resourceGroup'); +tr.setInput('subscriptionId', environmentData.subscriptionId); +tr.setInput('resourceGroupName', environmentData.resourceGroupName); +tr.setInput('parametersFile', path.join(__dirname, 'files', 'validationerror', 'main.bicepparam')); + +tr.run(); + +rewiremock.disable(); diff --git a/Tasks/BicepDeployV0/Tests/deploymentsInlineYamlParams.ts b/Tasks/BicepDeployV0/Tests/deploymentsInlineYamlParams.ts new file mode 100644 index 000000000000..67eb13d62793 --- /dev/null +++ b/Tasks/BicepDeployV0/Tests/deploymentsInlineYamlParams.ts @@ -0,0 +1,59 @@ +// Import and configure rewiremock BEFORE anything else loads +const rewiremock = require('rewiremock/node'); + +import * as path from 'path'; +import tmrm = require("azure-pipelines-task-lib/mock-run"); +import { environmentData } from './utils'; + +// Mock deploymentValidate to return successful validation +const mockDeploymentValidate = async () => { + return { + properties: { + outputs: { + stringOutput: { + type: 'String', + value: 'hello world' + }, + intOutput: { + type: 'Int', + value: 42 + }, + objectOutput: { + type: 'Object', + value: { + prop1: 'value1', + prop2: 'value2' + } + } + } + } + }; +}; + +// Enable rewiremock globally +rewiremock.enable(); + +// Mock the deployments module +rewiremock('@azure/bicep-deploy-common/deployments') + .callThrough() + .with({ deploymentValidate: mockDeploymentValidate }); + +let taskPath = path.join(__dirname, '..', 'main.js'); +let tr: tmrm.TaskMockRunner = new tmrm.TaskMockRunner(taskPath); + +tr.setInput('type', 'deployment'); +tr.setInput('operation', 'validate'); +tr.setInput('name', 'test-validate'); +tr.setInput('scope', 'resourceGroup'); +tr.setInput('subscriptionId', environmentData.subscriptionId); +tr.setInput('resourceGroupName', environmentData.resourceGroupName); +tr.setInput('templateFile', path.join(__dirname, 'files', 'basic', 'main.bicep')); +tr.setInput('parameters', `intParam: 42 +stringParam: hello world +objectParam: + prop1: value1 + prop2: value2`); + +tr.run(); + +rewiremock.disable(); diff --git a/Tasks/BicepDeployV0/Tests/deploymentsValidation.ts b/Tasks/BicepDeployV0/Tests/deploymentsValidation.ts new file mode 100644 index 000000000000..55a6b9a56a60 --- /dev/null +++ b/Tasks/BicepDeployV0/Tests/deploymentsValidation.ts @@ -0,0 +1,54 @@ +// Import and configure rewiremock BEFORE anything else loads +const rewiremock = require('rewiremock/node'); + +import * as path from 'path'; +import tmrm = require("azure-pipelines-task-lib/mock-run"); +import { environmentData } from './utils'; + +// Mock deploymentValidate to return successful validation +const mockDeploymentValidate = async () => { + return { + properties: { + outputs: { + stringOutput: { + type: 'String', + value: 'hello world' + }, + intOutput: { + type: 'Int', + value: 42 + }, + objectOutput: { + type: 'Object', + value: { + prop1: 'value1', + prop2: 'value2' + } + } + } + } + }; +}; + +// Enable rewiremock globally +rewiremock.enable(); + +// Mock the deployments module +rewiremock('@azure/bicep-deploy-common/deployments') + .callThrough() + .with({ deploymentValidate: mockDeploymentValidate }); + +let taskPath = path.join(__dirname, '..', 'main.js'); +let tr: tmrm.TaskMockRunner = new tmrm.TaskMockRunner(taskPath); + +tr.setInput('type', 'deployment'); +tr.setInput('operation', 'validate'); +tr.setInput('name', 'test-validate'); +tr.setInput('scope', 'resourceGroup'); +tr.setInput('subscriptionId', environmentData.subscriptionId); +tr.setInput('resourceGroupName', environmentData.resourceGroupName); +tr.setInput('parametersFile', path.join(__dirname, 'files', 'basic', 'main.bicepparam')); + +tr.run(); + +rewiremock.disable(); diff --git a/Tasks/BicepDeployV0/Tests/deploymentsWhatIf.ts b/Tasks/BicepDeployV0/Tests/deploymentsWhatIf.ts new file mode 100644 index 000000000000..c7cc27591470 --- /dev/null +++ b/Tasks/BicepDeployV0/Tests/deploymentsWhatIf.ts @@ -0,0 +1,40 @@ +// Import and configure rewiremock BEFORE anything else loads +const rewiremock = require('rewiremock/node'); + +import * as path from 'path'; +import tmrm = require("azure-pipelines-task-lib/mock-run"); +import { environmentData } from './utils'; + +// Mock deploymentWhatIf to return successful what-if result +const mockDeploymentWhatIf = async () => { + return { + status: 'Succeeded', + properties: { + changes: [], + provisioningState: 'Succeeded' + } + }; +}; + +// Enable rewiremock globally +rewiremock.enable(); + +// Mock the deployments module +rewiremock('@azure/bicep-deploy-common/deployments') + .callThrough() + .with({ deploymentWhatIf: mockDeploymentWhatIf }); + +let taskPath = path.join(__dirname, '..', 'main.js'); +let tr: tmrm.TaskMockRunner = new tmrm.TaskMockRunner(taskPath); + +tr.setInput('type', 'deployment'); +tr.setInput('operation', 'whatIf'); +tr.setInput('name', 'test-validate'); +tr.setInput('scope', 'resourceGroup'); +tr.setInput('subscriptionId', environmentData.subscriptionId); +tr.setInput('resourceGroupName', environmentData.resourceGroupName); +tr.setInput('parametersFile', path.join(__dirname, 'files', 'basic', 'main.bicepparam')); + +tr.run(); + +rewiremock.disable(); diff --git a/Tasks/BicepDeployV0/Tests/files/basic-sub/main.bicep b/Tasks/BicepDeployV0/Tests/files/basic-sub/main.bicep new file mode 100644 index 000000000000..5eadb3f802a7 --- /dev/null +++ b/Tasks/BicepDeployV0/Tests/files/basic-sub/main.bicep @@ -0,0 +1,9 @@ +targetScope = 'subscription' + +param stringParam string +param intParam int +param objectParam object + +output stringOutput string = stringParam +output intOutput int = intParam +output objectOutput object = objectParam diff --git a/Tasks/BicepDeployV0/Tests/files/basic-sub/main.bicepparam b/Tasks/BicepDeployV0/Tests/files/basic-sub/main.bicepparam new file mode 100644 index 000000000000..b4354db83dcb --- /dev/null +++ b/Tasks/BicepDeployV0/Tests/files/basic-sub/main.bicepparam @@ -0,0 +1,8 @@ +using 'main.bicep' + +param intParam = 42 +param stringParam = 'hello world' +param objectParam = { + prop1: 'value1' + prop2: 'value2' +} diff --git a/Tasks/BicepDeployV0/Tests/files/basic-sub/main.json b/Tasks/BicepDeployV0/Tests/files/basic-sub/main.json new file mode 100644 index 000000000000..7b1b8b2c485f --- /dev/null +++ b/Tasks/BicepDeployV0/Tests/files/basic-sub/main.json @@ -0,0 +1,37 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2018-05-01/subscriptionDeploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.30.23.60470", + "templateHash": "16476773654784878732" + } + }, + "parameters": { + "stringParam": { + "type": "string" + }, + "intParam": { + "type": "int" + }, + "objectParam": { + "type": "object" + } + }, + "resources": [], + "outputs": { + "stringOutput": { + "type": "string", + "value": "[parameters('stringParam')]" + }, + "intOutput": { + "type": "int", + "value": "[parameters('intParam')]" + }, + "objectOutput": { + "type": "object", + "value": "[parameters('objectParam')]" + } + } +} \ No newline at end of file diff --git a/Tasks/BicepDeployV0/Tests/files/basic-sub/main.parameters.json b/Tasks/BicepDeployV0/Tests/files/basic-sub/main.parameters.json new file mode 100644 index 000000000000..cc34c127ed2c --- /dev/null +++ b/Tasks/BicepDeployV0/Tests/files/basic-sub/main.parameters.json @@ -0,0 +1,18 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "intParam": { + "value": 42 + }, + "stringParam": { + "value": "hello world" + }, + "objectParam": { + "value": { + "prop1": "value1", + "prop2": "value2" + } + } + } +} \ No newline at end of file diff --git a/Tasks/BicepDeployV0/Tests/files/basic/main.bicep b/Tasks/BicepDeployV0/Tests/files/basic/main.bicep new file mode 100644 index 000000000000..27e239f2c8ab --- /dev/null +++ b/Tasks/BicepDeployV0/Tests/files/basic/main.bicep @@ -0,0 +1,7 @@ +param stringParam string +param intParam int +param objectParam object + +output stringOutput string = stringParam +output intOutput int = intParam +output objectOutput object = objectParam diff --git a/Tasks/BicepDeployV0/Tests/files/basic/main.bicepparam b/Tasks/BicepDeployV0/Tests/files/basic/main.bicepparam new file mode 100644 index 000000000000..b4354db83dcb --- /dev/null +++ b/Tasks/BicepDeployV0/Tests/files/basic/main.bicepparam @@ -0,0 +1,8 @@ +using 'main.bicep' + +param intParam = 42 +param stringParam = 'hello world' +param objectParam = { + prop1: 'value1' + prop2: 'value2' +} diff --git a/Tasks/BicepDeployV0/Tests/files/basic/main.json b/Tasks/BicepDeployV0/Tests/files/basic/main.json new file mode 100644 index 000000000000..e5b200d902de --- /dev/null +++ b/Tasks/BicepDeployV0/Tests/files/basic/main.json @@ -0,0 +1,37 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.30.3.12046", + "templateHash": "12629837844740609201" + } + }, + "parameters": { + "stringParam": { + "type": "string" + }, + "intParam": { + "type": "int" + }, + "objectParam": { + "type": "object" + } + }, + "resources": [], + "outputs": { + "stringOutput": { + "type": "string", + "value": "[parameters('stringParam')]" + }, + "intOutput": { + "type": "int", + "value": "[parameters('intParam')]" + }, + "objectOutput": { + "type": "object", + "value": "[parameters('objectParam')]" + } + } +} \ No newline at end of file diff --git a/Tasks/BicepDeployV0/Tests/files/basic/main.parameters.json b/Tasks/BicepDeployV0/Tests/files/basic/main.parameters.json new file mode 100644 index 000000000000..cc34c127ed2c --- /dev/null +++ b/Tasks/BicepDeployV0/Tests/files/basic/main.parameters.json @@ -0,0 +1,18 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "intParam": { + "value": 42 + }, + "stringParam": { + "value": "hello world" + }, + "objectParam": { + "value": { + "prop1": "value1", + "prop2": "value2" + } + } + } +} \ No newline at end of file diff --git a/Tasks/BicepDeployV0/Tests/files/deployerror/main.bicep b/Tasks/BicepDeployV0/Tests/files/deployerror/main.bicep new file mode 100644 index 000000000000..a362279d3064 --- /dev/null +++ b/Tasks/BicepDeployV0/Tests/files/deployerror/main.bicep @@ -0,0 +1,8 @@ +param input string + +// This will fail at deploy time, because the resource doesn't exist +resource sa 'Microsoft.Storage/storageAccounts@2019-06-01' existing = { + name: input +} + +output accessTier string = sa.properties.accessTier diff --git a/Tasks/BicepDeployV0/Tests/files/deployerror/main.bicepparam b/Tasks/BicepDeployV0/Tests/files/deployerror/main.bicepparam new file mode 100644 index 000000000000..c5ce7da0373e --- /dev/null +++ b/Tasks/BicepDeployV0/Tests/files/deployerror/main.bicepparam @@ -0,0 +1,3 @@ +using 'main.bicep' + +param input = 'foo' diff --git a/Tasks/BicepDeployV0/Tests/files/validationerror/main.bicep b/Tasks/BicepDeployV0/Tests/files/validationerror/main.bicep new file mode 100644 index 000000000000..7b97a656847c --- /dev/null +++ b/Tasks/BicepDeployV0/Tests/files/validationerror/main.bicep @@ -0,0 +1,10 @@ +param input string + +resource sa 'Microsoft.Storage/storageAccounts@2019-06-01' = { + name: input + location: resourceGroup().location + kind: 'StorageV2' + sku: { + name: 'Standard_LRS' + } +} diff --git a/Tasks/BicepDeployV0/Tests/files/validationerror/main.bicepparam b/Tasks/BicepDeployV0/Tests/files/validationerror/main.bicepparam new file mode 100644 index 000000000000..c5ce7da0373e --- /dev/null +++ b/Tasks/BicepDeployV0/Tests/files/validationerror/main.bicepparam @@ -0,0 +1,3 @@ +using 'main.bicep' + +param input = 'foo' diff --git a/Tasks/BicepDeployV0/Tests/package-lock.json b/Tasks/BicepDeployV0/Tests/package-lock.json new file mode 100644 index 000000000000..f373bbb3b3bf --- /dev/null +++ b/Tasks/BicepDeployV0/Tests/package-lock.json @@ -0,0 +1,2599 @@ +{ + "name": "bicepdeploy", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "bicepdeploy", + "license": "MIT", + "devDependencies": { + "@types/mocha": "^10.0.10", + "@types/node": "^24.10.1", + "@types/sinon": "^17.0.4", + "mocha": "^10.0.0", + "mockery": "^2.1.0", + "rewiremock": "^3.14.6", + "sinon": "^19.0.5" + } + }, + "node_modules/@sinonjs/commons": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", + "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "type-detect": "4.0.8" + } + }, + "node_modules/@sinonjs/fake-timers": { + "version": "13.0.5", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-13.0.5.tgz", + "integrity": "sha512-36/hTbH2uaWuGVERyC6da9YwGWnzUZXuPro/F2LfsdOsLnCojz/iSH8MxUt/FD2S5XBSVPhmArFUXcpCQ2Hkiw==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@sinonjs/commons": "^3.0.1" + } + }, + "node_modules/@sinonjs/samsam": { + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-8.0.3.tgz", + "integrity": "sha512-hw6HbX+GyVZzmaYNh82Ecj1vdGZrqVIn/keDTg63IgAwiQPO+xCz99uG6Woqgb4tM0mUiFENKZ4cqd7IX94AXQ==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@sinonjs/commons": "^3.0.1", + "type-detect": "^4.1.0" + } + }, + "node_modules/@sinonjs/samsam/node_modules/type-detect": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.1.0.tgz", + "integrity": "sha512-Acylog8/luQ8L7il+geoSxhEkazvkslg7PSNKOX59mbB9cOveP5aq9h74Y7YU8yDpJwetzQQrfIwtf4Wp4LKcw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/@sinonjs/text-encoding": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/@sinonjs/text-encoding/-/text-encoding-0.7.3.tgz", + "integrity": "sha512-DE427ROAphMQzU4ENbliGYrBSYPXF+TtLg9S8vzeA+OF4ZKzoDdzfL8sxuMUGS/lgRhM6j1URSk9ghf7Xo1tyA==", + "dev": true, + "license": "(Unlicense OR Apache-2.0)" + }, + "node_modules/@types/mocha": { + "version": "10.0.10", + "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-10.0.10.tgz", + "integrity": "sha512-xPyYSz1cMPnJQhl0CLMH68j3gprKZaTjG3s5Vi+fDgx+uhG9NOXwbVt52eFS8ECyXhyKcjDLCBEqBExKuiZb7Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "24.10.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-24.10.1.tgz", + "integrity": "sha512-GNWcUTRBgIRJD5zj+Tq0fKOJ5XZajIiBroOF0yvj2bSU1WvNdYS/dn9UxwsujGW4JX06dnHyjV2y9rRaybH0iQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~7.16.0" + } + }, + "node_modules/@types/sinon": { + "version": "17.0.4", + "resolved": "https://registry.npmjs.org/@types/sinon/-/sinon-17.0.4.tgz", + "integrity": "sha512-RHnIrhfPO3+tJT0s7cFaXGZvsL4bbR3/k7z3P312qMS4JaS2Tk+KiwiLx1S0rQ56ERj00u1/BtdyVd0FY+Pdew==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/sinonjs__fake-timers": "*" + } + }, + "node_modules/@types/sinonjs__fake-timers": { + "version": "15.0.1", + "resolved": "https://registry.npmjs.org/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-15.0.1.tgz", + "integrity": "sha512-Ko2tjWJq8oozHzHV+reuvS5KYIRAokHnGbDwGh/J64LntgpbuylF74ipEL24HCyRjf9FOlBiBHWBR1RlVKsI1w==", + "dev": true, + "license": "MIT" + }, + "node_modules/ansi-colors": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", + "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "license": "ISC", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true, + "license": "Python-2.0" + }, + "node_modules/asn1.js": { + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.10.1.tgz", + "integrity": "sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==", + "dev": true, + "license": "MIT", + "dependencies": { + "bn.js": "^4.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0" + } + }, + "node_modules/asn1.js/node_modules/bn.js": { + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.2.tgz", + "integrity": "sha512-n4DSx829VRTRByMRGdjQ9iqsN0Bh4OolPsFnaZBLcbi8iXcB+kJ9s7EnRt4wILZNV3kPLHkRVfOc/HvhC3ovDw==", + "dev": true, + "license": "MIT" + }, + "node_modules/assert": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/assert/-/assert-1.5.1.tgz", + "integrity": "sha512-zzw1uCAgLbsKwBfFc8CX78DDg+xZeBksSO3vwVIDDN5i94eOrPsSSyiVhmsSABFDM/OcpE2aagCat9dnWQLG1A==", + "dev": true, + "license": "MIT", + "dependencies": { + "object.assign": "^4.1.4", + "util": "^0.10.4" + } + }, + "node_modules/assert/node_modules/inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==", + "dev": true, + "license": "ISC" + }, + "node_modules/assert/node_modules/util": { + "version": "0.10.4", + "resolved": "https://registry.npmjs.org/util/-/util-0.10.4.tgz", + "integrity": "sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A==", + "dev": true, + "license": "MIT", + "dependencies": { + "inherits": "2.0.3" + } + }, + "node_modules/available-typed-arrays": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/babel-runtime": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", + "integrity": "sha512-ITKNuq2wKlW1fJg9sSW52eepoYgZBggvOAHC0u/CYu/qxQ9EVzThCgR69BnSXLHjy2f7SY5zaQ4yt7H9ZVxY2g==", + "dev": true, + "license": "MIT", + "dependencies": { + "core-js": "^2.4.0", + "regenerator-runtime": "^0.11.0" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/bn.js": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.2.tgz", + "integrity": "sha512-v2YAxEmKaBLahNwE1mjp4WON6huMNeuDvagFZW+ASCuA/ku0bXR9hSMw0XpiqMoA3+rmnyck/tPRSFQkoC9Cuw==", + "dev": true, + "license": "MIT" + }, + "node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/brorand": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", + "integrity": "sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==", + "dev": true, + "license": "MIT" + }, + "node_modules/browser-stdout": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", + "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", + "dev": true, + "license": "ISC" + }, + "node_modules/browserify-aes": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", + "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer-xor": "^1.0.3", + "cipher-base": "^1.0.0", + "create-hash": "^1.1.0", + "evp_bytestokey": "^1.0.3", + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/browserify-cipher": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz", + "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==", + "dev": true, + "license": "MIT", + "dependencies": { + "browserify-aes": "^1.0.4", + "browserify-des": "^1.0.0", + "evp_bytestokey": "^1.0.0" + } + }, + "node_modules/browserify-des": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz", + "integrity": "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "cipher-base": "^1.0.1", + "des.js": "^1.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "node_modules/browserify-rsa": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.1.1.tgz", + "integrity": "sha512-YBjSAiTqM04ZVei6sXighu679a3SqWORA3qZTEqZImnlkDIFtKc6pNutpjyZ8RJTjQtuYfeetkxM11GwoYXMIQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "bn.js": "^5.2.1", + "randombytes": "^2.1.0", + "safe-buffer": "^5.2.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/browserify-sign": { + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.5.tgz", + "integrity": "sha512-C2AUdAJg6rlM2W5QMp2Q4KGQMVBwR1lIimTsUnutJ8bMpW5B52pGpR2gEnNBNwijumDo5FojQ0L9JrXA8m4YEw==", + "dev": true, + "license": "ISC", + "dependencies": { + "bn.js": "^5.2.2", + "browserify-rsa": "^4.1.1", + "create-hash": "^1.2.0", + "create-hmac": "^1.1.7", + "elliptic": "^6.6.1", + "inherits": "^2.0.4", + "parse-asn1": "^5.1.9", + "readable-stream": "^2.3.8", + "safe-buffer": "^5.2.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/browserify-zlib": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz", + "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==", + "dev": true, + "license": "MIT", + "dependencies": { + "pako": "~1.0.5" + } + }, + "node_modules/buffer": { + "version": "4.9.2", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.2.tgz", + "integrity": "sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg==", + "dev": true, + "license": "MIT", + "dependencies": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4", + "isarray": "^1.0.0" + } + }, + "node_modules/buffer-xor": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", + "integrity": "sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/builtin-status-codes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", + "integrity": "sha512-HpGFw18DgFWlncDfjTa2rcQ4W88O1mC8e8yZ2AvQY5KDaktSTwo+KRf6nHK6FRI5FyRyb/5T6+TSxfP7QyGsmQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/call-bind": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz", + "integrity": "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.0", + "es-define-property": "^1.0.0", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/chalk/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/cipher-base": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.7.tgz", + "integrity": "sha512-Mz9QMT5fJe7bKI7MH31UilT5cEK5EHHRCccw/YRFsRY47AuNgaV6HY3rscp0/I4Q+tTW/5zoqpSeRRI54TkDWA==", + "dev": true, + "license": "MIT", + "dependencies": { + "inherits": "^2.0.4", + "safe-buffer": "^5.2.1", + "to-buffer": "^1.2.2" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" + }, + "node_modules/compare-module-exports": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/compare-module-exports/-/compare-module-exports-2.1.0.tgz", + "integrity": "sha512-3Lc0sTIuX1jmY2K2RrXRJOND6KsRTX2D4v3+eu1PDptsuJZVK4LZc852eZa9I+avj0NrUKlTNgqvccNOH6mbGg==", + "dev": true, + "license": "ISC" + }, + "node_modules/console-browserify": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.2.0.tgz", + "integrity": "sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA==", + "dev": true + }, + "node_modules/constants-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", + "integrity": "sha512-xFxOwqIzR/e1k1gLiWEophSCMqXcwVHIH7akf7b/vxcUeGunlj3hvZaaqxwHsTgn+IndtkQJgSztIDWeumWJDQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/core-js": { + "version": "2.6.12", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.12.tgz", + "integrity": "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==", + "deprecated": "core-js@<3.23.3 is no longer maintained and not recommended for usage due to the number of issues. Because of the V8 engine whims, feature detection in old core-js versions could cause a slowdown up to 100x even if nothing is polyfilled. Some versions have web compatibility issues. Please, upgrade your dependencies to the actual version of core-js.", + "dev": true, + "hasInstallScript": true, + "license": "MIT" + }, + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/create-ecdh": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.4.tgz", + "integrity": "sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A==", + "dev": true, + "license": "MIT", + "dependencies": { + "bn.js": "^4.1.0", + "elliptic": "^6.5.3" + } + }, + "node_modules/create-ecdh/node_modules/bn.js": { + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.2.tgz", + "integrity": "sha512-n4DSx829VRTRByMRGdjQ9iqsN0Bh4OolPsFnaZBLcbi8iXcB+kJ9s7EnRt4wILZNV3kPLHkRVfOc/HvhC3ovDw==", + "dev": true, + "license": "MIT" + }, + "node_modules/create-hash": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", + "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", + "dev": true, + "license": "MIT", + "dependencies": { + "cipher-base": "^1.0.1", + "inherits": "^2.0.1", + "md5.js": "^1.3.4", + "ripemd160": "^2.0.1", + "sha.js": "^2.4.0" + } + }, + "node_modules/create-hmac": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", + "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", + "dev": true, + "license": "MIT", + "dependencies": { + "cipher-base": "^1.0.3", + "create-hash": "^1.1.0", + "inherits": "^2.0.1", + "ripemd160": "^2.0.0", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } + }, + "node_modules/crypto-browserify": { + "version": "3.12.1", + "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.1.tgz", + "integrity": "sha512-r4ESw/IlusD17lgQi1O20Fa3qNnsckR126TdUuBgAu7GBYSIPvdNyONd3Zrxh0xCwA4+6w/TDArBPsMvhur+KQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "browserify-cipher": "^1.0.1", + "browserify-sign": "^4.2.3", + "create-ecdh": "^4.0.4", + "create-hash": "^1.2.0", + "create-hmac": "^1.1.7", + "diffie-hellman": "^5.0.3", + "hash-base": "~3.0.4", + "inherits": "^2.0.4", + "pbkdf2": "^3.1.2", + "public-encrypt": "^4.0.3", + "randombytes": "^2.1.0", + "randomfill": "^1.0.4" + }, + "engines": { + "node": ">= 0.10" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decamelize": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", + "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/define-properties": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/des.js": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.1.0.tgz", + "integrity": "sha512-r17GxjhUCjSRy8aiJpr8/UadFIzMzJGexI3Nmz4ADi9LYSFx4gTBp80+NaX/YsXWWLhpZ7v/v/ubEc/bCNfKwg==", + "dev": true, + "license": "MIT", + "dependencies": { + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0" + } + }, + "node_modules/diff": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.0.tgz", + "integrity": "sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/diffie-hellman": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", + "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", + "dev": true, + "license": "MIT", + "dependencies": { + "bn.js": "^4.1.0", + "miller-rabin": "^4.0.0", + "randombytes": "^2.0.0" + } + }, + "node_modules/diffie-hellman/node_modules/bn.js": { + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.2.tgz", + "integrity": "sha512-n4DSx829VRTRByMRGdjQ9iqsN0Bh4OolPsFnaZBLcbi8iXcB+kJ9s7EnRt4wILZNV3kPLHkRVfOc/HvhC3ovDw==", + "dev": true, + "license": "MIT" + }, + "node_modules/domain-browser": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz", + "integrity": "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.4", + "npm": ">=1.2" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/elliptic": { + "version": "6.6.1", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.6.1.tgz", + "integrity": "sha512-RaddvvMatK2LJHqFJ+YA4WysVN5Ita9E35botqIYspQ4TkRAlCicdzKOjlyv/1Za5RyTNn7di//eEV0uTAfe3g==", + "dev": true, + "license": "MIT", + "dependencies": { + "bn.js": "^4.11.9", + "brorand": "^1.1.0", + "hash.js": "^1.0.0", + "hmac-drbg": "^1.0.1", + "inherits": "^2.0.4", + "minimalistic-assert": "^1.0.1", + "minimalistic-crypto-utils": "^1.0.1" + } + }, + "node_modules/elliptic/node_modules/bn.js": { + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.2.tgz", + "integrity": "sha512-n4DSx829VRTRByMRGdjQ9iqsN0Bh4OolPsFnaZBLcbi8iXcB+kJ9s7EnRt4wILZNV3kPLHkRVfOc/HvhC3ovDw==", + "dev": true, + "license": "MIT" + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.x" + } + }, + "node_modules/evp_bytestokey": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", + "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", + "dev": true, + "license": "MIT", + "dependencies": { + "md5.js": "^1.3.4", + "safe-buffer": "^5.1.1" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", + "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", + "dev": true, + "license": "BSD-3-Clause", + "bin": { + "flat": "cli.js" + } + }, + "node_modules/for-each": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz", + "integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-callable": "^1.2.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true, + "license": "ISC" + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, + "license": "ISC", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "dev": true, + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/glob": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", + "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hash-base": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.5.tgz", + "integrity": "sha512-vXm0l45VbcHEVlTCzs8M+s0VeYsB2lnlAaThoLKGXr3bE/VWDOelNUnycUPEhKEaXARL2TEFjBOyUiM6+55KBg==", + "dev": true, + "license": "MIT", + "dependencies": { + "inherits": "^2.0.4", + "safe-buffer": "^5.2.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/hash.js": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", + "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", + "dev": true, + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.1" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "dev": true, + "license": "MIT", + "bin": { + "he": "bin/he" + } + }, + "node_modules/hmac-drbg": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", + "integrity": "sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg==", + "dev": true, + "license": "MIT", + "dependencies": { + "hash.js": "^1.0.3", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.1" + } + }, + "node_modules/https-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", + "integrity": "sha512-J+FkSdyD+0mA0N+81tMotaRMfSL9SGi+xpD3T6YApKsc3bGSXJlfXri3VyFOeYkfLRQisDk1W+jIFFKBeUBbBg==", + "dev": true, + "license": "MIT" + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "BSD-3-Clause" + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "dev": true, + "license": "ISC", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "license": "MIT", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-plain-obj": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", + "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-typed-array": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz", + "integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "which-typed-array": "^1.1.16" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/js-yaml": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", + "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/just-extend": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-6.2.0.tgz", + "integrity": "sha512-cYofQu2Xpom82S6qD778jBDpwvvy39s1l/hrYij2u9AMdQcGRpaBu6kY4mVhuno5kJVi1DAz4aiphA2WI1/OAw==", + "dev": true, + "license": "MIT" + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-symbols": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/md5.js": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", + "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", + "dev": true, + "license": "MIT", + "dependencies": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "node_modules/miller-rabin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", + "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "bn.js": "^4.0.0", + "brorand": "^1.0.1" + }, + "bin": { + "miller-rabin": "bin/miller-rabin" + } + }, + "node_modules/miller-rabin/node_modules/bn.js": { + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.2.tgz", + "integrity": "sha512-n4DSx829VRTRByMRGdjQ9iqsN0Bh4OolPsFnaZBLcbi8iXcB+kJ9s7EnRt4wILZNV3kPLHkRVfOc/HvhC3ovDw==", + "dev": true, + "license": "MIT" + }, + "node_modules/minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", + "dev": true, + "license": "ISC" + }, + "node_modules/minimalistic-crypto-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", + "integrity": "sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==", + "dev": true, + "license": "MIT" + }, + "node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/mocha": { + "version": "10.8.2", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.8.2.tgz", + "integrity": "sha512-VZlYo/WE8t1tstuRmqgeyBgCbJc/lEdopaa+axcKzTBJ+UIdlAB9XnmvTCAH4pwR4ElNInaedhEBmZD8iCSVEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-colors": "^4.1.3", + "browser-stdout": "^1.3.1", + "chokidar": "^3.5.3", + "debug": "^4.3.5", + "diff": "^5.2.0", + "escape-string-regexp": "^4.0.0", + "find-up": "^5.0.0", + "glob": "^8.1.0", + "he": "^1.2.0", + "js-yaml": "^4.1.0", + "log-symbols": "^4.1.0", + "minimatch": "^5.1.6", + "ms": "^2.1.3", + "serialize-javascript": "^6.0.2", + "strip-json-comments": "^3.1.1", + "supports-color": "^8.1.1", + "workerpool": "^6.5.1", + "yargs": "^16.2.0", + "yargs-parser": "^20.2.9", + "yargs-unparser": "^2.0.0" + }, + "bin": { + "_mocha": "bin/_mocha", + "mocha": "bin/mocha.js" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/mockery": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mockery/-/mockery-2.1.0.tgz", + "integrity": "sha512-9VkOmxKlWXoDO/h1jDZaS4lH33aWfRiJiNT/tKj+8OGzrcFDLo8d0syGdbsc3Bc4GvRXPb+NMMvojotmuGJTvA==", + "dev": true + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/nise": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/nise/-/nise-6.1.1.tgz", + "integrity": "sha512-aMSAzLVY7LyeM60gvBS423nBmIPP+Wy7St7hsb+8/fc1HmeoHJfLO8CKse4u3BtOZvQLJghYPI2i/1WZrEj5/g==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@sinonjs/commons": "^3.0.1", + "@sinonjs/fake-timers": "^13.0.1", + "@sinonjs/text-encoding": "^0.7.3", + "just-extend": "^6.2.0", + "path-to-regexp": "^8.1.0" + } + }, + "node_modules/node-libs-browser": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.2.1.tgz", + "integrity": "sha512-h/zcD8H9kaDZ9ALUWwlBUDo6TKF8a7qBSCSEGfjTVIYeqsioSKaAX+BN7NgiMGp6iSIXZ3PxgCu8KS3b71YK5Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "assert": "^1.1.1", + "browserify-zlib": "^0.2.0", + "buffer": "^4.3.0", + "console-browserify": "^1.1.0", + "constants-browserify": "^1.0.0", + "crypto-browserify": "^3.11.0", + "domain-browser": "^1.1.1", + "events": "^3.0.0", + "https-browserify": "^1.0.0", + "os-browserify": "^0.3.0", + "path-browserify": "0.0.1", + "process": "^0.11.10", + "punycode": "^1.2.4", + "querystring-es3": "^0.2.0", + "readable-stream": "^2.3.3", + "stream-browserify": "^2.0.1", + "stream-http": "^2.7.2", + "string_decoder": "^1.0.0", + "timers-browserify": "^2.0.4", + "tty-browserify": "0.0.0", + "url": "^0.11.0", + "util": "^0.11.0", + "vm-browserify": "^1.0.1" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.assign": { + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.7.tgz", + "integrity": "sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0", + "has-symbols": "^1.1.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/os-browserify": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", + "integrity": "sha512-gjcpUc3clBf9+210TRaDWbf+rZZZEshZ+DlXMRCeAjp0xhTrnQsKHypIy1J3d5hKdUzj69t708EHtU8P6bUn0A==", + "dev": true, + "license": "MIT" + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pako": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", + "dev": true, + "license": "(MIT AND Zlib)" + }, + "node_modules/parse-asn1": { + "version": "5.1.9", + "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.9.tgz", + "integrity": "sha512-fIYNuZ/HastSb80baGOuPRo1O9cf4baWw5WsAp7dBuUzeTD/BoaG8sVTdlPFksBE2lF21dN+A1AnrpIjSWqHHg==", + "dev": true, + "license": "ISC", + "dependencies": { + "asn1.js": "^4.10.1", + "browserify-aes": "^1.2.0", + "evp_bytestokey": "^1.0.3", + "pbkdf2": "^3.1.5", + "safe-buffer": "^5.2.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/path-browserify": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.1.tgz", + "integrity": "sha512-BapA40NHICOS+USX9SN4tyhq+A2RrN/Ws5F0Z5aMHDp98Fl86lX8Oti8B7uN93L4Ifv4fHOEA+pQw87gmMO/lQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true, + "license": "MIT" + }, + "node_modules/path-to-regexp": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.3.0.tgz", + "integrity": "sha512-7jdwVIRtsP8MYpdXSwOS0YdD0Du+qOoF/AEPIt88PcCFrZCzx41oxku1jD88hZBwbNUIEfpqvuhjFaMAqMTWnA==", + "dev": true, + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/pbkdf2": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.5.tgz", + "integrity": "sha512-Q3CG/cYvCO1ye4QKkuH7EXxs3VC/rI1/trd+qX2+PolbaKG0H+bgcZzrTt96mMyRtejk+JMCiLUn3y29W8qmFQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "create-hash": "^1.2.0", + "create-hmac": "^1.1.7", + "ripemd160": "^2.0.3", + "safe-buffer": "^5.2.1", + "sha.js": "^2.4.12", + "to-buffer": "^1.2.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/possible-typed-array-names": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz", + "integrity": "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6.0" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true, + "license": "MIT" + }, + "node_modules/public-encrypt": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz", + "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "bn.js": "^4.1.0", + "browserify-rsa": "^4.0.0", + "create-hash": "^1.1.0", + "parse-asn1": "^5.0.0", + "randombytes": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "node_modules/public-encrypt/node_modules/bn.js": { + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.2.tgz", + "integrity": "sha512-n4DSx829VRTRByMRGdjQ9iqsN0Bh4OolPsFnaZBLcbi8iXcB+kJ9s7EnRt4wILZNV3kPLHkRVfOc/HvhC3ovDw==", + "dev": true, + "license": "MIT" + }, + "node_modules/punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/qs": { + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz", + "integrity": "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/querystring-es3": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", + "integrity": "sha512-773xhDQnZBMFobEiztv8LIl70ch5MSF/jUQVlhwFyBILqq96anmoctVIYz+ZRp0qbCKATTn6ev02M3r7Ga5vqA==", + "dev": true, + "engines": { + "node": ">=0.4.x" + } + }, + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, + "node_modules/randomfill": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", + "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", + "dev": true, + "license": "MIT", + "dependencies": { + "randombytes": "^2.0.5", + "safe-buffer": "^5.1.0" + } + }, + "node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "license": "MIT", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/readable-stream/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true, + "license": "MIT" + }, + "node_modules/readable-stream/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/regenerator-runtime": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", + "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==", + "dev": true, + "license": "MIT" + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/rewiremock": { + "version": "3.14.6", + "resolved": "https://registry.npmjs.org/rewiremock/-/rewiremock-3.14.6.tgz", + "integrity": "sha512-hjpS7iQUTVVh/IHV4GE1ypg4IzlgVc34gxZBarwwVrKfnjlyqHJuQdsia6Ac7m4f4k/zxxA3tX285MOstdysRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "babel-runtime": "^6.26.0", + "compare-module-exports": "^2.1.0", + "node-libs-browser": "^2.1.0", + "path-parse": "^1.0.5", + "wipe-node-cache": "^2.1.2", + "wipe-webpack-cache": "^2.1.0" + } + }, + "node_modules/ripemd160": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.3.tgz", + "integrity": "sha512-5Di9UC0+8h1L6ZD2d7awM7E/T4uA1fJRlx6zk/NvdCCVEoAnFqvHmCuNeIKoCeIixBX/q8uM+6ycDvF8woqosA==", + "dev": true, + "license": "MIT", + "dependencies": { + "hash-base": "^3.1.2", + "inherits": "^2.0.4" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/ripemd160/node_modules/hash-base": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.2.tgz", + "integrity": "sha512-Bb33KbowVTIj5s7Ked1OsqHUeCpz//tPwR+E2zJgJKo9Z5XolZ9b6bdUgjmYlwnWhoOQKoTd1TYToZGn5mAYOg==", + "dev": true, + "license": "MIT", + "dependencies": { + "inherits": "^2.0.4", + "readable-stream": "^2.3.8", + "safe-buffer": "^5.2.1", + "to-buffer": "^1.2.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/serialize-javascript": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", + "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "randombytes": "^2.1.0" + } + }, + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==", + "dev": true, + "license": "MIT" + }, + "node_modules/sha.js": { + "version": "2.4.12", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.12.tgz", + "integrity": "sha512-8LzC5+bvI45BjpfXU8V5fdU2mfeKiQe1D1gIMn7XUlF3OTUrpdJpPPH4EMAnF0DsHHdSZqCdSss5qCmJKuiO3w==", + "dev": true, + "license": "(MIT AND BSD-3-Clause)", + "dependencies": { + "inherits": "^2.0.4", + "safe-buffer": "^5.2.1", + "to-buffer": "^1.2.0" + }, + "bin": { + "sha.js": "bin.js" + }, + "engines": { + "node": ">= 0.10" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", + "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/sinon": { + "version": "19.0.5", + "resolved": "https://registry.npmjs.org/sinon/-/sinon-19.0.5.tgz", + "integrity": "sha512-r15s9/s+ub/d4bxNXqIUmwp6imVSdTorIRaxoecYjqTVLZ8RuoXr/4EDGwIBo6Waxn7f2gnURX9zuhAfCwaF6Q==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@sinonjs/commons": "^3.0.1", + "@sinonjs/fake-timers": "^13.0.5", + "@sinonjs/samsam": "^8.0.1", + "diff": "^7.0.0", + "nise": "^6.1.1", + "supports-color": "^7.2.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/sinon" + } + }, + "node_modules/sinon/node_modules/diff": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-7.0.0.tgz", + "integrity": "sha512-PJWHUb1RFevKCwaFA9RlG5tCd+FO5iRh9A8HEtkmBH2Li03iJriB6m6JIN4rGz3K3JLawI7/veA1xzRKP6ISBw==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/sinon/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/stream-browserify": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.2.tgz", + "integrity": "sha512-nX6hmklHs/gr2FuxYDltq8fJA1GDlxKQCz8O/IM4atRqBH8OORmBNgfvW5gG10GT/qQ9u0CzIvr2X5Pkt6ntqg==", + "dev": true, + "license": "MIT", + "dependencies": { + "inherits": "~2.0.1", + "readable-stream": "^2.0.2" + } + }, + "node_modules/stream-http": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.8.3.tgz", + "integrity": "sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "builtin-status-codes": "^3.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.3.6", + "to-arraybuffer": "^1.0.0", + "xtend": "^4.0.0" + } + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dev": true, + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/timers-browserify": { + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.12.tgz", + "integrity": "sha512-9phl76Cqm6FhSX9Xe1ZUAMLtm1BLkKj2Qd5ApyWkXzsMRaA7dgr81kf4wJmQf/hAvg8EEyJxDo3du/0KlhPiKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "setimmediate": "^1.0.4" + }, + "engines": { + "node": ">=0.6.0" + } + }, + "node_modules/to-arraybuffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz", + "integrity": "sha512-okFlQcoGTi4LQBG/PgSYblw9VOyptsz2KJZqc6qtgGdes8VktzUQkj4BI2blit072iS8VODNcMA+tvnS9dnuMA==", + "dev": true, + "license": "MIT" + }, + "node_modules/to-buffer": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.2.2.tgz", + "integrity": "sha512-db0E3UJjcFhpDhAF4tLo03oli3pwl3dbnzXOUIlRKrp+ldk/VUxzpWYZENsw2SZiuBjHAk7DfB0VU7NKdpb6sw==", + "dev": true, + "license": "MIT", + "dependencies": { + "isarray": "^2.0.5", + "safe-buffer": "^5.2.1", + "typed-array-buffer": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/to-buffer/node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true, + "license": "MIT" + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/tty-browserify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", + "integrity": "sha512-JVa5ijo+j/sOoHGjw0sxw734b1LhBkQ3bvUGNdxnVXDCX81Yx7TFgnZygxrIIWn23hbfTaMYLwRmAxFyDuFmIw==", + "dev": true, + "license": "MIT" + }, + "node_modules/type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/typed-array-buffer": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz", + "integrity": "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-typed-array": "^1.1.14" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/undici-types": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz", + "integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==", + "dev": true, + "license": "MIT" + }, + "node_modules/url": { + "version": "0.11.4", + "resolved": "https://registry.npmjs.org/url/-/url-0.11.4.tgz", + "integrity": "sha512-oCwdVC7mTuWiPyjLUz/COz5TLk6wgp0RCsN+wHZ2Ekneac9w8uuV0njcbbie2ME+Vs+d6duwmYuR3HgQXs1fOg==", + "dev": true, + "license": "MIT", + "dependencies": { + "punycode": "^1.4.1", + "qs": "^6.12.3" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/util": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/util/-/util-0.11.1.tgz", + "integrity": "sha512-HShAsny+zS2TZfaXxD9tYj4HQGlBezXZMZuM/S5PKLLoZkShZiGk9o5CzukI1LVHZvjdvZ2Sj1aW/Ndn2NB/HQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "inherits": "2.0.3" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true, + "license": "MIT" + }, + "node_modules/util/node_modules/inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==", + "dev": true, + "license": "ISC" + }, + "node_modules/vm-browserify": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.2.tgz", + "integrity": "sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/which-typed-array": { + "version": "1.1.19", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.19.tgz", + "integrity": "sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw==", + "dev": true, + "license": "MIT", + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "for-each": "^0.3.5", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/wipe-node-cache": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/wipe-node-cache/-/wipe-node-cache-2.1.2.tgz", + "integrity": "sha512-m7NXa8qSxBGMtdQilOu53ctMaIBXy93FOP04EC1Uf4bpsE+r+adfLKwIMIvGbABsznaSNxK/ErD4xXDyY5og9w==", + "dev": true, + "license": "MIT" + }, + "node_modules/wipe-webpack-cache": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/wipe-webpack-cache/-/wipe-webpack-cache-2.1.0.tgz", + "integrity": "sha512-OXzQMGpA7MnQQ8AG+uMl5mWR2ezy6fw1+DMHY+wzYP1qkF1jrek87psLBmhZEj+er4efO/GD4R8jXWFierobaA==", + "dev": true, + "license": "MIT", + "dependencies": { + "wipe-node-cache": "^2.1.0" + } + }, + "node_modules/workerpool": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.5.1.tgz", + "integrity": "sha512-Fs4dNYcsdpYSAfVxhnl1L5zTksjvOJxtC5hzMNl+1t9B8hTJTdKDyZ5ju7ztgPy+ft9tBFXoOlDNiOT9WUXZlA==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.4" + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dev": true, + "license": "MIT", + "dependencies": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs-unparser": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", + "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", + "dev": true, + "license": "MIT", + "dependencies": { + "camelcase": "^6.0.0", + "decamelize": "^4.0.0", + "flat": "^5.0.2", + "is-plain-obj": "^2.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + } + } +} diff --git a/Tasks/BicepDeployV0/Tests/package.json b/Tasks/BicepDeployV0/Tests/package.json new file mode 100644 index 000000000000..bc6cf8f5ce51 --- /dev/null +++ b/Tasks/BicepDeployV0/Tests/package.json @@ -0,0 +1,27 @@ +{ + "name": "bicepdeploy", + "description": "Azure Pipelines Bicep Deploy V0 Task Tests", + "main": "L0.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "repository": { + "type": "git", + "url": "git+ssh://git@github.com/Microsoft/azure-pipelines-tasks.git" + }, + "author": "Microsoft Corporation", + "license": "MIT", + "bugs": { + "url": "https://github.com/Microsoft/azure-pipelines-tasks/issues" + }, + "homepage": "https://github.com/Microsoft/azure-pipelines-tasks#readme", + "devDependencies": { + "@types/mocha": "^10.0.10", + "@types/node": "^24.10.1", + "@types/sinon": "^17.0.4", + "mocha": "^10.0.0", + "mockery": "^2.1.0", + "rewiremock": "^3.14.6", + "sinon": "^19.0.5" + } +} diff --git a/Tasks/BicepDeployV0/Tests/runErrorObject.ts b/Tasks/BicepDeployV0/Tests/runErrorObject.ts new file mode 100644 index 000000000000..bbc9a570317f --- /dev/null +++ b/Tasks/BicepDeployV0/Tests/runErrorObject.ts @@ -0,0 +1,29 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. +import * as path from "path"; +import * as tmrm from "azure-pipelines-task-lib/mock-run"; +import { environmentData } from './utils'; + +let taskPath = path.join(__dirname, "..", "main.js"); +let tr: tmrm.TaskMockRunner = new tmrm.TaskMockRunner(taskPath); + +// Set task inputs +tr.setInput('type', 'deployment'); +tr.setInput('name', 'test-deployment'); +tr.setInput('operation', 'create'); +tr.setInput('scope', 'resourceGroup'); +tr.setInput('subscriptionId', environmentData.subscriptionId); +tr.setInput('resourceGroupName', environmentData.resourceGroupName); +tr.setInput('location', 'eastus'); +tr.setInput('templateFile', path.join(__dirname, "files", "valid", "main.bicep")); +tr.setInput('parametersFile', path.join(__dirname, "files", "valid", "main.bicepparam")); + +// Clone bicep-deploy-common and override getTemplateAndParameters to throw Error object +const bicepCommon = require('@azure/bicep-deploy-common'); +const bicepCommonClone = Object.assign({}, bicepCommon); +bicepCommonClone.getTemplateAndParameters = function() { + throw new Error(`This is an error!`); +}; +tr.registerMock('@azure/bicep-deploy-common', bicepCommonClone); + +tr.run(); diff --git a/Tasks/BicepDeployV0/Tests/runStringError.ts b/Tasks/BicepDeployV0/Tests/runStringError.ts new file mode 100644 index 000000000000..657365a65a96 --- /dev/null +++ b/Tasks/BicepDeployV0/Tests/runStringError.ts @@ -0,0 +1,29 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. +import * as path from "path"; +import * as tmrm from "azure-pipelines-task-lib/mock-run"; +import { environmentData } from './utils'; + +let taskPath = path.join(__dirname, "..", "main.js"); +let tr: tmrm.TaskMockRunner = new tmrm.TaskMockRunner(taskPath); + +// Set task inputs +tr.setInput('type', 'deployment'); +tr.setInput('name', 'test-deployment'); +tr.setInput('operation', 'create'); +tr.setInput('scope', 'resourceGroup'); +tr.setInput('subscriptionId', environmentData.subscriptionId); +tr.setInput('resourceGroupName', environmentData.resourceGroupName); +tr.setInput('location', 'eastus'); +tr.setInput('templateFile', path.join(__dirname, "files", "valid", "main.bicep")); +tr.setInput('parametersFile', path.join(__dirname, "files", "valid", "main.bicepparam")); + +// Clone bicep-deploy-common and override getTemplateAndParameters to throw string error +const bicepCommon = require('@azure/bicep-deploy-common'); +const bicepCommonClone = Object.assign({}, bicepCommon); +bicepCommonClone.getTemplateAndParameters = function() { + throw `This is an error!`; +}; +tr.registerMock('@azure/bicep-deploy-common', bicepCommonClone); + +tr.run(); diff --git a/Tasks/BicepDeployV0/Tests/stacksCreateFailures.ts b/Tasks/BicepDeployV0/Tests/stacksCreateFailures.ts new file mode 100644 index 000000000000..d2d3f9536640 --- /dev/null +++ b/Tasks/BicepDeployV0/Tests/stacksCreateFailures.ts @@ -0,0 +1,53 @@ +// Import and configure rewiremock BEFORE anything else loads +const rewiremock = require('rewiremock/node'); + +import * as path from 'path'; +import * as crypto from 'crypto'; +import tmrm = require("azure-pipelines-task-lib/mock-run"); +import { environmentData, createMockRestError } from './utils'; + +// Mock stackCreate to throw deployment error +const mockStackCreate = async () => { + const errorCorrelationId = crypto.randomUUID(); + const correlationId = crypto.randomUUID(); + const error = { + code: "DeploymentStackDeploymentFailed", + message: `One or more resources could not be deployed. Correlation id: '${errorCorrelationId}'.`, + details: [ + { + code: "DeploymentFailed", + target: `/subscriptions/${environmentData.subscriptionId}/resourceGroups/${environmentData.resourceGroupName}/providers/Microsoft.Resources/deployments/e2e-create-251130211keuw`, + message: "At least one resource deployment operation failed. Please list deployment operations for details. Please see https://aka.ms/arm-deployment-operations for usage details.", + details: [] + } + ] + }; + + throw createMockRestError('Stack create failed', error, correlationId); +}; + +// Enable rewiremock globally +rewiremock.enable(); + +// Mock the stacks module +rewiremock('@azure/bicep-deploy-common/stacks') + .callThrough() + .with({ stackCreate: mockStackCreate }); + +let taskPath = path.join(__dirname, '..', 'main.js'); +let tr: tmrm.TaskMockRunner = new tmrm.TaskMockRunner(taskPath); + +tr.setInput('type', 'deploymentStack'); +tr.setInput('operation', 'create'); +tr.setInput('name', 'test-create'); +tr.setInput('scope', 'resourceGroup'); +tr.setInput('subscriptionId', environmentData.subscriptionId); +tr.setInput('resourceGroupName', environmentData.resourceGroupName); +tr.setInput('parametersFile', path.join(__dirname, 'files', 'deployerror', 'main.bicepparam')); +tr.setInput('actionOnUnmanageResources', 'detach'); +tr.setInput('actionOnUnmanageResourceGroups', 'detach'); +tr.setInput('denySettingsMode', 'none'); + +tr.run(); + +rewiremock.disable(); diff --git a/Tasks/BicepDeployV0/Tests/stacksFailures.ts b/Tasks/BicepDeployV0/Tests/stacksFailures.ts new file mode 100644 index 000000000000..549b7dcfb3d0 --- /dev/null +++ b/Tasks/BicepDeployV0/Tests/stacksFailures.ts @@ -0,0 +1,41 @@ +// Import and configure rewiremock BEFORE anything else loads +const rewiremock = require('rewiremock/node'); + +import * as path from 'path'; +import * as crypto from 'crypto'; +import tmrm = require("azure-pipelines-task-lib/mock-run"); +import { environmentData, createMockRestError, createValidationFailureError } from './utils'; + +// Mock stackValidate to throw validation error +const mockStackValidate = async () => { + const trackingId = crypto.randomUUID(); + const correlationId = crypto.randomUUID(); + const error = createValidationFailureError('e2e-validate', trackingId); + throw createMockRestError('Stack validation failed', error, correlationId); +}; + +// Enable rewiremock globally +rewiremock.enable(); + +// Mock the stacks module +rewiremock('@azure/bicep-deploy-common/stacks') + .callThrough() + .with({ stackValidate: mockStackValidate }); + +let taskPath = path.join(__dirname, '..', 'main.js'); +let tr: tmrm.TaskMockRunner = new tmrm.TaskMockRunner(taskPath); + +tr.setInput('type', 'deploymentStack'); +tr.setInput('operation', 'validate'); +tr.setInput('name', 'test-validate'); +tr.setInput('scope', 'resourceGroup'); +tr.setInput('subscriptionId', environmentData.subscriptionId); +tr.setInput('resourceGroupName', environmentData.resourceGroupName); +tr.setInput('parametersFile', path.join(__dirname, 'files', 'validationerror', 'main.bicepparam')); +tr.setInput('actionOnUnmanageResources', 'detach'); +tr.setInput('actionOnUnmanageResourceGroups', 'detach'); +tr.setInput('denySettingsMode', 'none'); + +tr.run(); + +rewiremock.disable(); diff --git a/Tasks/BicepDeployV0/Tests/stacksInlineYamlParams.ts b/Tasks/BicepDeployV0/Tests/stacksInlineYamlParams.ts new file mode 100644 index 000000000000..0fc75b11a3ae --- /dev/null +++ b/Tasks/BicepDeployV0/Tests/stacksInlineYamlParams.ts @@ -0,0 +1,62 @@ +// Import and configure rewiremock BEFORE anything else loads +const rewiremock = require('rewiremock/node'); + +import * as path from 'path'; +import tmrm = require("azure-pipelines-task-lib/mock-run"); +import { environmentData } from './utils'; + +// Mock stackValidate to return successful validation +const mockStackValidate = async () => { + return { + properties: { + outputs: { + stringOutput: { + type: 'String', + value: 'hello world' + }, + intOutput: { + type: 'Int', + value: 42 + }, + objectOutput: { + type: 'Object', + value: { + prop1: 'value1', + prop2: 'value2' + } + } + } + } + }; +}; + +// Enable rewiremock globally +rewiremock.enable(); + +// Mock the stacks module +rewiremock('@azure/bicep-deploy-common/stacks') + .callThrough() + .with({ stackValidate: mockStackValidate }); + +let taskPath = path.join(__dirname, '..', 'main.js'); +let tr: tmrm.TaskMockRunner = new tmrm.TaskMockRunner(taskPath); + +tr.setInput('type', 'deploymentStack'); +tr.setInput('operation', 'validate'); +tr.setInput('name', 'test-validate'); +tr.setInput('scope', 'resourceGroup'); +tr.setInput('subscriptionId', environmentData.subscriptionId); +tr.setInput('resourceGroupName', environmentData.resourceGroupName); +tr.setInput('templateFile', path.join(__dirname, 'files', 'basic', 'main.bicep')); +tr.setInput('parameters', `intParam: 42 +stringParam: hello world +objectParam: + prop1: value1 + prop2: value2`); +tr.setInput('actionOnUnmanageResources', 'detach'); +tr.setInput('actionOnUnmanageResourceGroups', 'detach'); +tr.setInput('denySettingsMode', 'none'); + +tr.run(); + +rewiremock.disable(); diff --git a/Tasks/BicepDeployV0/Tests/stacksValidation.ts b/Tasks/BicepDeployV0/Tests/stacksValidation.ts new file mode 100644 index 000000000000..90702997f953 --- /dev/null +++ b/Tasks/BicepDeployV0/Tests/stacksValidation.ts @@ -0,0 +1,57 @@ +// Import and configure rewiremock BEFORE anything else loads +const rewiremock = require('rewiremock/node'); + +import * as path from 'path'; +import tmrm = require("azure-pipelines-task-lib/mock-run"); +import { environmentData } from './utils'; + +// Mock stackValidate to return successful validation +const mockStackValidate = async () => { + return { + properties: { + outputs: { + stringOutput: { + type: 'String', + value: 'hello world' + }, + intOutput: { + type: 'Int', + value: 42 + }, + objectOutput: { + type: 'Object', + value: { + prop1: 'value1', + prop2: 'value2' + } + } + } + } + }; +}; + +// Enable rewiremock globally +rewiremock.enable(); + +// Mock the stacks module +rewiremock('@azure/bicep-deploy-common/stacks') + .callThrough() + .with({ stackValidate: mockStackValidate }); + +let taskPath = path.join(__dirname, '..', 'main.js'); +let tr: tmrm.TaskMockRunner = new tmrm.TaskMockRunner(taskPath); + +tr.setInput('type', 'deploymentStack'); +tr.setInput('operation', 'validate'); +tr.setInput('name', 'test-validate'); +tr.setInput('scope', 'resourceGroup'); +tr.setInput('subscriptionId', environmentData.subscriptionId); +tr.setInput('resourceGroupName', environmentData.resourceGroupName); +tr.setInput('parametersFile', path.join(__dirname, 'files', 'basic', 'main.bicepparam')); +tr.setInput('actionOnUnmanageResources', 'detach'); +tr.setInput('actionOnUnmanageResourceGroups', 'detach'); +tr.setInput('denySettingsMode', 'none'); + +tr.run(); + +rewiremock.disable(); diff --git a/Tasks/BicepDeployV0/Tests/utils.ts b/Tasks/BicepDeployV0/Tests/utils.ts new file mode 100644 index 000000000000..ef1409e6504f --- /dev/null +++ b/Tasks/BicepDeployV0/Tests/utils.ts @@ -0,0 +1,38 @@ +export const environmentData = { + subscriptionId: '00000000-0000-0000-0000-000000000000', + resourceGroupName: 'mock-resource-group', +}; + +export function createMockRestError(message: string, error: any, correlationId: string = 'test-correlation-id'): any { + const restError: any = new Error(message); + restError.name = 'RestError'; + restError.code = 'RestError'; + restError.statusCode = 400; + restError.response = { + headers: { + get: (name: string) => name === 'x-ms-correlation-request-id' ? correlationId : undefined + } + }; + restError.details = { error }; + return restError; +} + +export function createValidationFailureError(deploymentName: string = 'e2e-validate', trackingId: string = 'test-tracking-id') { + return { + code: "InvalidTemplateDeployment", + message: `The template deployment '${deploymentName}' is not valid according to the validation procedure. The tracking id is '${trackingId}'. See inner errors for details.`, + details: [ + { + code: "PreflightValidationCheckFailed", + message: "Preflight validation failed. Please refer to the details for the specific errors.", + details: [ + { + code: "StorageAccountAlreadyTaken", + message: "The storage account named foo is already taken.", + target: "foo" + } + ] + } + ] + }; +} diff --git a/Tasks/BicepDeployV0/icon.png b/Tasks/BicepDeployV0/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..32689a796c0354c79d4ac437318a30cef919e16c GIT binary patch literal 15797 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 literal 0 HcmV?d00001 diff --git a/Tasks/BicepDeployV0/icon.svg b/Tasks/BicepDeployV0/icon.svg new file mode 100644 index 000000000000..221ccf0ac440 --- /dev/null +++ b/Tasks/BicepDeployV0/icon.svg @@ -0,0 +1,67 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Tasks/BicepDeployV0/logging.ts b/Tasks/BicepDeployV0/logging.ts new file mode 100644 index 000000000000..64287b8ae8ce --- /dev/null +++ b/Tasks/BicepDeployV0/logging.ts @@ -0,0 +1,62 @@ +import * as tl from "azure-pipelines-task-lib/task"; +import { Color, colorize, Logger, LoggingMessageConfig, ErrorMessageConfig } from "@azure/bicep-deploy-common"; + +const logWarningRaw = (message: string) => tl.warning(message); +const logErrorRaw = (message: string) => tl.error(message); + +export class TaskLogger implements Logger { + isDebugEnabled = () => (process.env["SYSTEM_DEBUG"] || "").toLowerCase() === "true"; + debug = (message: string) => tl.debug(message); + logInfoRaw = (message: string) => console.log(message); + logInfo = (message: string) => this.logInfoRaw(colorize(message, Color.Blue)); + logWarning = (message: string) => logWarningRaw(colorize(message, Color.Yellow)); + logError = (message: string) => logErrorRaw(colorize(message, Color.Red)); +} + +export const loggingMessageConfig: LoggingMessageConfig = { + diagnosticsReturned: tl.loc('DiagnosticsReturned'), + bicepVersionInstalled: (version: string, path: string) => + tl.loc('BicepVersionInstalled', version, path), + requestFailedCorrelation: (correlationId: string | null) => + tl.loc('RequestFailedCorrelation', correlationId), +}; + +export const errorMessageConfig: ErrorMessageConfig = { + // Handler errors + createFailed: tl.loc('CreateFailed'), + validationFailed: tl.loc('ValidationFailed'), + operationFailed: tl.loc('OperationFailed'), + requestFailedCorrelation: (correlationId: string) => + tl.loc('RequestFailedCorrelation', correlationId), + + // Input errors + inputMustBeBoolean: (inputName: string) => + tl.loc('InputMustBeBoolean', inputName), + inputRequired: (inputName: string) => + tl.loc('InputRequired', inputName), + inputMustBeEnum: (inputName: string, allowedValues: string[]) => + tl.loc('InputMustBeEnum', inputName, allowedValues.join(`', '`)), + inputMustBeValidObject: (inputName: string) => + tl.loc('InputMustBeValidObject', inputName), + inputMustBeStringObject: (inputName: string) => + tl.loc('InputMustBeStringObject', inputName), + + // Utils errors + locationRequired: tl.loc('LocationRequired'), + failedToDetermineScope: tl.loc('FailedToDetermineScope'), + + // File errors + unsupportedParametersFile: (parametersFile: string) => + tl.loc('UnsupportedParametersFile', parametersFile), + unsupportedTemplateFile: (templateFile: string) => + tl.loc('UnsupportedTemplateFile', templateFile), + templateFileRequired: tl.loc('TemplateFileRequired'), + + // WhatIf errors + invalidChangeType: (changeType: string) => + tl.loc('InvalidChangeType', changeType), + unknownPropertyChangeType: (propertyChangeType: string) => + tl.loc('UnknownPropertyChangeType', propertyChangeType), + invalidJsonValue: (value: unknown) => + tl.loc('InvalidJsonValue', value), +}; \ No newline at end of file diff --git a/Tasks/BicepDeployV0/main.ts b/Tasks/BicepDeployV0/main.ts new file mode 100644 index 000000000000..fb20ec9bb9a4 --- /dev/null +++ b/Tasks/BicepDeployV0/main.ts @@ -0,0 +1,35 @@ +import tl = require('azure-pipelines-task-lib/task'); +import { + parseConfig, + getTemplateAndParameters, + execute +} from '@azure/bicep-deploy-common'; +import { TaskInputParameterNames, TaskInputReader, TaskOutputSetter } from './taskIO'; +import { TaskLogger, errorMessageConfig, loggingMessageConfig } from './logging'; + +export async function run() { + try { + const inputReader = new TaskInputReader(); + const inputParameterNames = new TaskInputParameterNames(); + const logger = new TaskLogger(); + const outputSetter = new TaskOutputSetter(); + + // Parse configuration from task inputs + const config = parseConfig(inputReader, inputParameterNames); + logger.logInfo(tl.loc('TaskConfig', JSON.stringify(config, null, 2))); + + // Get template and parameters + const files = await getTemplateAndParameters(config, logger); + + // Execute the deployment or deployment stack operation + await execute(config, files, logger, outputSetter, errorMessageConfig, loggingMessageConfig); + tl.setResult(tl.TaskResult.Succeeded, tl.loc('OperationSucceeded')); + } catch (err: any) { + const errorMessage = err instanceof Error ? err.message : String(err); + + // tl.error doesn't need to be called separately as setResult calls it internally. + tl.setResult(tl.TaskResult.Failed, errorMessage); + } +} + +run(); diff --git a/Tasks/BicepDeployV0/package-lock.json b/Tasks/BicepDeployV0/package-lock.json new file mode 100644 index 000000000000..dfd5183d6403 --- /dev/null +++ b/Tasks/BicepDeployV0/package-lock.json @@ -0,0 +1,499 @@ +{ + "name": "bicepdeploy", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "bicepdeploy", + "license": "MIT", + "dependencies": { + "@azure/bicep-deploy-common": "^0.0.2-dev", + "@types/mocha": "^5.2.7", + "@types/node": "^20.3.1", + "@types/q": "^1.5.8", + "azure-pipelines-task-lib": "^5.2.2" + }, + "devDependencies": { + "typescript": "5.1.6" + } + }, + "../../../bicep-deploy/packages/bicep-deploy-common": { + "name": "@azure/bicep-deploy-common", + "version": "0.0.2-dev", + "license": "MIT", + "dependencies": { + "@azure/arm-resources": "^6.0.0", + "@azure/arm-resourcesdeploymentstacks": "^1.0.0", + "@azure/identity": "^4.10.2", + "bicep-node": "^0.0.8", + "yaml": "^2.7.0" + }, + "devDependencies": { + "@types/node": "^22.15.29", + "@vitest/eslint-plugin": "^1.4.3", + "eslint": "^9.39.1", + "eslint-config-prettier": "^10.1.5", + "eslint-plugin-notice": "^1.0.0", + "eslint-plugin-prettier": "^5.5.4", + "ts-node": "^10.9.2", + "tsdown": "^0.16.5", + "typescript": "^5.8.3", + "typescript-eslint": "^8.32.0", + "vitest": "^4.0.10", + "yaml": "^2.7.1" + }, + "engines": { + "node": ">=22" + } + }, + "node_modules/@azure/bicep-deploy-common": { + "resolved": "../../../bicep-deploy/packages/bicep-deploy-common", + "link": true + }, + "node_modules/@types/mocha": { + "version": "5.2.7", + "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-5.2.7.tgz", + "integrity": "sha512-NYrtPht0wGzhwe9+/idPaBB+TqkY9AhTvOLMkThm0IoEfLaiVQZwBwyJ5puCkO3AUCWrmcoePjp2mbFocKy4SQ==", + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "20.19.25", + "resolved": "https://pkgs.dev.azure.com/mseng/PipelineTools/_packaging/PipelineTools_PublicPackages/npm/registry/@types/node/-/node-20.19.25.tgz", + "integrity": "sha1-Rn2pSi/ZZrV8w5w1ckfWgEdhEZA=", + "license": "MIT", + "dependencies": { + "undici-types": "~6.21.0" + } + }, + "node_modules/@types/q": { + "version": "1.5.8", + "resolved": "https://registry.npmjs.org/@types/q/-/q-1.5.8.tgz", + "integrity": "sha512-hroOstUScF6zhIi+5+x0dzqrHA1EJi+Irri6b1fxolMTqqHIV/Cg77EtnQcZqZCu8hR3mX2BzIxN4/GzI68Kfw==", + "license": "MIT" + }, + "node_modules/adm-zip": { + "version": "0.5.16", + "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.5.16.tgz", + "integrity": "sha512-TGw5yVi4saajsSEgz25grObGHEUaDrniwvA2qwSC060KfqGPdglhvPMA2lPIoxs3PQIItj2iag35fONcQqgUaQ==", + "license": "MIT", + "engines": { + "node": ">=12.0" + } + }, + "node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "license": "MIT", + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/azure-pipelines-task-lib": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/azure-pipelines-task-lib/-/azure-pipelines-task-lib-5.2.2.tgz", + "integrity": "sha512-McTb45c4oP1ma0evhXBe+y1Gy4gQihYnb+2Kr1tnBYhIv2xzK8iAIfwqhlyhHloCBVDHNrToFQcAC0UH1Gd32g==", + "license": "MIT", + "dependencies": { + "adm-zip": "^0.5.10", + "minimatch": "3.0.5", + "nodejs-file-downloader": "^4.11.1", + "q": "^1.5.1", + "semver": "^5.7.2", + "shelljs": "^0.8.5", + "uuid": "^3.0.1" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "license": "MIT" + }, + "node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "license": "MIT" + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/follow-redirects": { + "version": "1.15.11", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.11.tgz", + "integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "license": "MIT", + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "license": "ISC" + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "license": "MIT", + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "license": "ISC", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "license": "ISC" + }, + "node_modules/interpret": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz", + "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==", + "license": "MIT", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/is-core-module": { + "version": "2.16.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", + "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", + "license": "MIT", + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/minimatch": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.5.tgz", + "integrity": "sha512-tUpxzX0VAzJHjLu0xUfFv1gwVp9ba3IOuRAVH2EGuRW8a5emA2FlACLqiT/lDVtS1W+TGNwqz3sWaNyLgDJWuw==", + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/nodejs-file-downloader": { + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/nodejs-file-downloader/-/nodejs-file-downloader-4.13.0.tgz", + "integrity": "sha512-nI2fKnmJWWFZF6SgMPe1iBodKhfpztLKJTtCtNYGhm/9QXmWa/Pk9Sv00qHgzEvNLe1x7hjGDRor7gcm/ChaIQ==", + "license": "ISC", + "dependencies": { + "follow-redirects": "^1.15.6", + "https-proxy-agent": "^5.0.0", + "mime-types": "^2.1.27", + "sanitize-filename": "^1.6.3" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "license": "MIT" + }, + "node_modules/q": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", + "integrity": "sha512-kV/CThkXo6xyFEZUugw/+pIOywXcDbFYgSct5cT3gqlbkBE1SJdwy6UQoZvodiWF/ckQLZyDE/Bu1M6gVu5lVw==", + "deprecated": "You or someone you depend on is using Q, the JavaScript Promise library that gave JavaScript developers strong feelings about promises. They can almost certainly migrate to the native JavaScript promise now. Thank you literally everyone for joining me in this bet against the odds. Be excellent to each other.\n\n(For a CapTP with native promises, see @endo/eventual-send and @endo/captp)", + "license": "MIT", + "engines": { + "node": ">=0.6.0", + "teleport": ">=0.2.0" + } + }, + "node_modules/rechoir": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", + "integrity": "sha512-HFM8rkZ+i3zrV+4LQjwQ0W+ez98pApMGM3HUrN04j3CqzPOzl9nmP15Y8YXNm8QHGv/eacOVEjqhmWpkRV0NAw==", + "dependencies": { + "resolve": "^1.1.6" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/resolve": { + "version": "1.22.11", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.11.tgz", + "integrity": "sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==", + "license": "MIT", + "dependencies": { + "is-core-module": "^2.16.1", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/sanitize-filename": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/sanitize-filename/-/sanitize-filename-1.6.3.tgz", + "integrity": "sha512-y/52Mcy7aw3gRm7IrcGDFx/bCk4AhRh2eI9luHOQM86nZsqwiRkkq2GekHXBBD+SmPidc8i2PqtYZl+pWJ8Oeg==", + "license": "WTFPL OR ISC", + "dependencies": { + "truncate-utf8-bytes": "^1.0.0" + } + }, + "node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "license": "ISC", + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/shelljs": { + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.5.tgz", + "integrity": "sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow==", + "license": "BSD-3-Clause", + "dependencies": { + "glob": "^7.0.0", + "interpret": "^1.0.0", + "rechoir": "^0.6.2" + }, + "bin": { + "shjs": "bin/shjs" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/truncate-utf8-bytes": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/truncate-utf8-bytes/-/truncate-utf8-bytes-1.0.2.tgz", + "integrity": "sha512-95Pu1QXQvruGEhv62XCMO3Mm90GscOCClvrIUwCM0PYOXK3kaF3l3sIHxx71ThJfcbM2O5Au6SO3AWCSEfW4mQ==", + "license": "WTFPL", + "dependencies": { + "utf8-byte-length": "^1.0.1" + } + }, + "node_modules/typescript": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.1.6.tgz", + "integrity": "sha512-zaWCozRZ6DLEWAWFrVDz1H6FVXzUSfTy5FUMWsQlU8Ym5JP9eO4xkTIROFCQvhQf61z6O/G6ugw3SgAnvvm+HA==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/undici-types": { + "version": "6.21.0", + "resolved": "https://pkgs.dev.azure.com/mseng/PipelineTools/_packaging/PipelineTools_PublicPackages/npm/registry/undici-types/-/undici-types-6.21.0.tgz", + "integrity": "sha1-aR0ArzkJvpOn+qE75hs6W1DvEss=", + "license": "MIT" + }, + "node_modules/utf8-byte-length": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/utf8-byte-length/-/utf8-byte-length-1.0.5.tgz", + "integrity": "sha512-Xn0w3MtiQ6zoz2vFyUVruaCL53O/DwUvkEeOvj+uulMm0BkUGYWmBYVyElqZaSLhY6ZD0ulfU3aBra2aVT4xfA==", + "license": "(WTFPL OR MIT)" + }, + "node_modules/uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", + "license": "MIT", + "bin": { + "uuid": "bin/uuid" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "license": "ISC" + } + } +} diff --git a/Tasks/BicepDeployV0/package.json b/Tasks/BicepDeployV0/package.json new file mode 100644 index 000000000000..4a1e2f3eba69 --- /dev/null +++ b/Tasks/BicepDeployV0/package.json @@ -0,0 +1,28 @@ +{ + "name": "bicepdeploy", + "main": "main.js", + "scripts": { + "build": "node ../../make.js build --task BicepDeployV0", + "serverBuild": "node ../../make.js serverBuild --task BicepDeployV0" + }, + "repository": { + "type": "git", + "url": "git+ssh://git@github.com/Microsoft/azure-pipelines-tasks.git" + }, + "author": "Microsoft Corporation", + "license": "MIT", + "bugs": { + "url": "https://github.com/Microsoft/azure-pipelines-tasks/issues" + }, + "homepage": "https://github.com/Microsoft/azure-pipelines-tasks#readme", + "dependencies": { + "@azure/bicep-deploy-common": "^0.0.2-dev", + "@types/mocha": "^5.2.7", + "@types/node": "^20.3.1", + "@types/q": "^1.5.8", + "azure-pipelines-task-lib": "^5.2.2" + }, + "devDependencies": { + "typescript": "5.1.6" + } +} diff --git a/Tasks/BicepDeployV0/task.json b/Tasks/BicepDeployV0/task.json new file mode 100644 index 000000000000..d8a9c816982d --- /dev/null +++ b/Tasks/BicepDeployV0/task.json @@ -0,0 +1,399 @@ +{ + "id": "7c8f9a3b-2d4e-4f1a-9b6c-8e5d3a1f7c2b", + "name": "BicepDeploy", + "friendlyName": "Bicep Deploy", + "description": "Deploy and Manage Azure Resources using Bicep Files", + "helpMarkDown": "[Learn more about this task](https://aka.ms/bicepdeploytaskreadme)", + "category": "Deploy", + "visibility": ["Build", "Release"], + "author": "Microsoft Corporation", + "version": { + "Major": 0, + "Minor": 0, + "Patch": 0 + }, + "minimumAgentVersion": "2.144.0", + "instanceNameFormat": "Bicep $(operation) $(name)", + "groups": [ + { + "name": "AzureDetails", + "displayName": "Azure Details", + "isExpanded": true + }, + { + "name": "Template", + "displayName": "Template", + "isExpanded": true + }, + { + "name": "DeploymentStack", + "displayName": "Deployment Stack Options", + "isExpanded": false, + "visibleRule": "type = deploymentStack" + }, + { + "name": "Advanced", + "displayName": "Advanced", + "isExpanded": false + } + ], + "inputs": [ + { + "name": "type", + "type": "pickList", + "label": "Execution type", + "defaultValue": "deployment", + "required": true, + "groupName": "AzureDetails", + "helpMarkDown": "Specifies the execution type, deployment or deploymentStack.", + "options": { + "deployment": "Deployment", + "deploymentStack": "Deployment Stack" + } + }, + { + "name": "operation", + "type": "pickList", + "label": "Operation", + "defaultValue": "create", + "required": true, + "groupName": "AzureDetails", + "helpMarkDown": "Specifies the operation to perform.", + "options": { + "create": "Create or update", + "validate": "Validate", + "whatIf": "What-If (preview changes)", + "delete": "Delete" + }, + "visibleRule": "type = deployment || (type = deploymentStack && operation != whatIf)", + "properties": { + "EditableOptions": "False" + } + }, + { + "name": "scope", + "type": "pickList", + "label": "Deployment scope", + "defaultValue": "resourceGroup", + "required": true, + "groupName": "AzureDetails", + "helpMarkDown": "Specifies the scope at which resources are deployed.", + "options": { + "resourceGroup": "Resource Group", + "subscription": "Subscription", + "managementGroup": "Management Group", + "tenant": "Tenant" + } + }, + { + "name": "name", + "type": "string", + "label": "Deployment name", + "defaultValue": "", + "required": false, + "groupName": "AzureDetails", + "helpMarkDown": "Specifies the name of the deployment or deployment stack. If not provided, a default name will be generated." + }, + { + "name": "ConnectedServiceName", + "aliases": [ + "azureResourceManagerConnection" + ], + "type": "connectedService:AzureRM", + "label": "Azure Resource Manager connection", + "defaultValue": "", + "required": true, + "groupName": "AzureDetails", + "helpMarkDown": "Select the Azure Resource Manager service connection.", + "properties": { + "EndpointFilterRule": "ScopeLevel >= scope" + } + }, + { + "name": "subscriptionId", + "type": "pickList", + "label": "Subscription", + "required": true, + "groupName": "AzureDetails", + "helpMarkDown": "Select the Azure subscription. Required if scope is subscription or resourceGroup.", + "properties": { + "EditableOptions": "True" + }, + "visibleRule": "scope != tenant && scope != managementGroup" + }, + { + "name": "resourceGroupName", + "type": "pickList", + "label": "Resource group", + "required": true, + "groupName": "AzureDetails", + "helpMarkDown": "Provide the name of the resource group.", + "properties": { + "EditableOptions": "True" + }, + "visibleRule": "scope = resourceGroup" + }, + { + "name": "location", + "type": "pickList", + "label": "Location", + "required": false, + "groupName": "AzureDetails", + "helpMarkDown": "Location to store deployment metadata. Required for subscription, managementGroup, and tenant scopes.", + "properties": { + "EditableOptions": "True" + }, + "visibleRule": "scope != resourceGroup" + }, + { + "name": "tenantId", + "type": "string", + "label": "Tenant ID", + "required": true, + "groupName": "AzureDetails", + "helpMarkDown": "Specifies the tenant ID. Required if scope is tenant.", + "visibleRule": "scope = tenant" + }, + { + "name": "managementGroupId", + "type": "string", + "label": "Management group ID", + "required": true, + "groupName": "AzureDetails", + "helpMarkDown": "Specifies the management group ID. Required if scope is managementGroup.", + "visibleRule": "scope = managementGroup" + }, + { + "name": "templateFile", + "type": "filePath", + "label": "Template file", + "defaultValue": "", + "required": false, + "groupName": "Template", + "helpMarkDown": "Specify the path to the Bicep template file (.bicep)." + }, + { + "name": "parametersFile", + "type": "filePath", + "label": "Parameters file", + "defaultValue": "", + "required": false, + "groupName": "Template", + "helpMarkDown": "Specify the path to the parameters file (.json or .bicepparam)." + }, + { + "name": "parameters", + "type": "multiLine", + "label": "Override parameters", + "defaultValue": "", + "required": false, + "groupName": "Template", + "helpMarkDown": "Specify inline parameters as a JSON or YAML object. Example: {\"param1\": \"value1\", \"param2\": \"value2\"}" + }, + { + "name": "actionOnUnmanageResources", + "type": "pickList", + "label": "Action on unmanaged resources", + "defaultValue": "detach", + "required": true, + "groupName": "DeploymentStack", + "helpMarkDown": "Specifies the action to take on resources not defined in the template.", + "options": { + "delete": "Delete", + "detach": "Detach" + }, + "visibleRule": "type = deploymentStack" + }, + { + "name": "actionOnUnmanageResourceGroups", + "type": "pickList", + "label": "Action on unmanaged resource groups", + "defaultValue": "", + "required": false, + "groupName": "DeploymentStack", + "helpMarkDown": "Specifies the action to take on resource groups not defined in the template.", + "options": { + "delete": "Delete", + "detach": "Detach" + }, + "visibleRule": "type = deploymentStack" + }, + { + "name": "actionOnUnmanageManagementGroups", + "type": "pickList", + "label": "Action on unmanaged management groups", + "defaultValue": "", + "required": false, + "groupName": "DeploymentStack", + "helpMarkDown": "Specifies the action to take on management groups not defined in the template.", + "options": { + "delete": "Delete", + "detach": "Detach" + }, + "visibleRule": "type = deploymentStack" + }, + { + "name": "denySettingsMode", + "type": "pickList", + "label": "Deny settings mode", + "defaultValue": "none", + "required": true, + "groupName": "DeploymentStack", + "helpMarkDown": "Specifies the mode of the deny settings to prevent unauthorized changes.", + "options": { + "none": "None", + "denyDelete": "Deny Delete", + "denyWriteAndDelete": "Deny Write and Delete" + }, + "visibleRule": "type = deploymentStack" + }, + { + "name": "denySettingsExcludedActions", + "type": "string", + "label": "Deny settings excluded actions", + "defaultValue": "", + "required": false, + "groupName": "DeploymentStack", + "helpMarkDown": "Comma-separated list of actions to exclude from deny settings.", + "visibleRule": "type = deploymentStack && denySettingsMode != none" + }, + { + "name": "denySettingsExcludedPrincipals", + "type": "string", + "label": "Deny settings excluded principals", + "defaultValue": "", + "required": false, + "groupName": "DeploymentStack", + "helpMarkDown": "Comma-separated list of principal IDs to exclude from deny settings.", + "visibleRule": "type = deploymentStack && denySettingsMode != none" + }, + { + "name": "denySettingsApplyToChildScopes", + "type": "boolean", + "label": "Apply deny settings to child scopes", + "defaultValue": "false", + "required": false, + "groupName": "DeploymentStack", + "helpMarkDown": "When enabled, deny settings also apply to child scopes of managed resources.", + "visibleRule": "type = deploymentStack && denySettingsMode != none" + }, + { + "name": "bypassStackOutOfSyncError", + "type": "boolean", + "label": "Bypass stack out of sync error", + "defaultValue": "false", + "required": false, + "groupName": "DeploymentStack", + "helpMarkDown": "Bypass errors when the deployment stack is out of sync.", + "visibleRule": "type = deploymentStack" + }, + { + "name": "description", + "type": "string", + "label": "Description", + "defaultValue": "", + "required": false, + "groupName": "Advanced", + "helpMarkDown": "Description for the deployment or deployment stack." + }, + { + "name": "tags", + "type": "multiLine", + "label": "Tags", + "defaultValue": "", + "required": false, + "groupName": "Advanced", + "helpMarkDown": "Tags as JSON or YAML object. Example: {\"Environment\": \"Development\", \"Owner\": \"TeamName\"}", + "visibleRule": "type = deploymentStack" + }, + { + "name": "bicepVersion", + "type": "string", + "label": "Bicep version", + "defaultValue": "", + "required": false, + "groupName": "Advanced", + "helpMarkDown": "Specify the version of Bicep to use (e.g., '0.38.5'). If not provided, the latest version will be used." + }, + { + "name": "maskedOutputs", + "type": "string", + "label": "Masked outputs", + "defaultValue": "", + "required": false, + "groupName": "Advanced", + "helpMarkDown": "Comma-separated list of output names to mask values for (e.g., secrets)." + }, + { + "name": "environment", + "type": "pickList", + "label": "Azure environment", + "defaultValue": "azureCloud", + "required": false, + "groupName": "Advanced", + "helpMarkDown": "Specifies the Azure environment to use.", + "options": { + "azureCloud": "Azure Cloud", + "azureChinaCloud": "Azure China Cloud", + "azureGermanCloud": "Azure German Cloud", + "azureUSGovernment": "Azure US Government" + } + }, + { + "name": "whatIfExcludeChangeTypes", + "type": "string", + "label": "What-If exclude change types", + "defaultValue": "", + "required": false, + "groupName": "Advanced", + "helpMarkDown": "Comma-separated list of change types to exclude from What-If operation (e.g., noChange, ignore).", + "visibleRule": "operation = whatIf" + }, + { + "name": "validationLevel", + "type": "pickList", + "label": "Validation level", + "defaultValue": "", + "required": false, + "groupName": "Advanced", + "helpMarkDown": "Validation level for deployment operations.", + "options": { + "provider": "Provider", + "template": "Template", + "providerNoRbac": "Provider (No RBAC)" + }, + "visibleRule": "type = deployment && (operation = validate || operation = whatIf)" + } + ], + "messages": { + "CreateFailed": "Create failed", + "ValidationFailed": "Validation failed", + "OperationFailed": "Operation failed", + "RequestFailedCorrelation": "Request failed. CorrelationId: %s", + "InputMustBeBoolean": "Input '%s' must be a boolean value", + "InputRequired": "Input '%s' is required but not provided", + "InputMustBeEnum": "Input '%s' must be one of the following values: '%s'", + "InputMustBeValidObject": "Input '%s' must be a valid JSON or YAML object", + "InputMustBeStringObject": "Input '%s' must be a valid JSON or YAML object containing only string values", + "LocationRequired": "Location is required", + "FailedToDetermineScope": "Failed to determine deployment scope from Bicep file.", + "UnsupportedParametersFile": "Unsupported parameters file type: %s", + "UnsupportedTemplateFile": "Unsupported template file type: %s", + "TemplateFileRequired": "Template file is required", + "InvalidChangeType": "Invalid ChangeType: %s", + "UnknownPropertyChangeType": "Unknown property change type: %s.", + "InvalidJsonValue": "Invalid JSON value: %s", + "DiagnosticsReturned": "Diagnostics returned by the API", + "BicepVersionInstalled": "Installed Bicep version %s to %s", + "TaskConfig": "Task config: %s", + "OperationSucceeded": "Operation completed successfully" + }, + "execution": { + "Node16": { + "target": "main.js" + }, + "Node20_1": { + "target": "main.js" + } + } +} \ No newline at end of file diff --git a/Tasks/BicepDeployV0/task.loc.json b/Tasks/BicepDeployV0/task.loc.json new file mode 100644 index 000000000000..104ca2a8282d --- /dev/null +++ b/Tasks/BicepDeployV0/task.loc.json @@ -0,0 +1,402 @@ +{ + "id": "7c8f9a3b-2d4e-4f1a-9b6c-8e5d3a1f7c2b", + "name": "BicepDeploy", + "friendlyName": "ms-resource:loc.friendlyName", + "description": "ms-resource:loc.description", + "helpMarkDown": "ms-resource:loc.helpMarkDown", + "category": "Deploy", + "visibility": [ + "Build", + "Release" + ], + "author": "Microsoft Corporation", + "version": { + "Major": 0, + "Minor": 0, + "Patch": 0 + }, + "minimumAgentVersion": "2.144.0", + "instanceNameFormat": "ms-resource:loc.instanceNameFormat", + "groups": [ + { + "name": "AzureDetails", + "displayName": "ms-resource:loc.group.displayName.AzureDetails", + "isExpanded": true + }, + { + "name": "Template", + "displayName": "ms-resource:loc.group.displayName.Template", + "isExpanded": true + }, + { + "name": "DeploymentStack", + "displayName": "ms-resource:loc.group.displayName.DeploymentStack", + "isExpanded": false, + "visibleRule": "type = deploymentStack" + }, + { + "name": "Advanced", + "displayName": "ms-resource:loc.group.displayName.Advanced", + "isExpanded": false + } + ], + "inputs": [ + { + "name": "type", + "type": "pickList", + "label": "ms-resource:loc.input.label.type", + "defaultValue": "deployment", + "required": true, + "groupName": "AzureDetails", + "helpMarkDown": "ms-resource:loc.input.help.type", + "options": { + "deployment": "Deployment", + "deploymentStack": "Deployment Stack" + } + }, + { + "name": "operation", + "type": "pickList", + "label": "ms-resource:loc.input.label.operation", + "defaultValue": "create", + "required": true, + "groupName": "AzureDetails", + "helpMarkDown": "ms-resource:loc.input.help.operation", + "options": { + "create": "Create or update", + "validate": "Validate", + "whatIf": "What-If (preview changes)", + "delete": "Delete" + }, + "visibleRule": "type = deployment || (type = deploymentStack && operation != whatIf)", + "properties": { + "EditableOptions": "False" + } + }, + { + "name": "scope", + "type": "pickList", + "label": "ms-resource:loc.input.label.scope", + "defaultValue": "resourceGroup", + "required": true, + "groupName": "AzureDetails", + "helpMarkDown": "ms-resource:loc.input.help.scope", + "options": { + "resourceGroup": "Resource Group", + "subscription": "Subscription", + "managementGroup": "Management Group", + "tenant": "Tenant" + } + }, + { + "name": "name", + "type": "string", + "label": "ms-resource:loc.input.label.name", + "defaultValue": "", + "required": false, + "groupName": "AzureDetails", + "helpMarkDown": "ms-resource:loc.input.help.name" + }, + { + "name": "ConnectedServiceName", + "aliases": [ + "azureResourceManagerConnection" + ], + "type": "connectedService:AzureRM", + "label": "ms-resource:loc.input.label.ConnectedServiceName", + "defaultValue": "", + "required": true, + "groupName": "AzureDetails", + "helpMarkDown": "ms-resource:loc.input.help.ConnectedServiceName", + "properties": { + "EndpointFilterRule": "ScopeLevel >= scope" + } + }, + { + "name": "subscriptionId", + "type": "pickList", + "label": "ms-resource:loc.input.label.subscriptionId", + "required": true, + "groupName": "AzureDetails", + "helpMarkDown": "ms-resource:loc.input.help.subscriptionId", + "properties": { + "EditableOptions": "True" + }, + "visibleRule": "scope != tenant && scope != managementGroup" + }, + { + "name": "resourceGroupName", + "type": "pickList", + "label": "ms-resource:loc.input.label.resourceGroupName", + "required": true, + "groupName": "AzureDetails", + "helpMarkDown": "ms-resource:loc.input.help.resourceGroupName", + "properties": { + "EditableOptions": "True" + }, + "visibleRule": "scope = resourceGroup" + }, + { + "name": "location", + "type": "pickList", + "label": "ms-resource:loc.input.label.location", + "required": false, + "groupName": "AzureDetails", + "helpMarkDown": "ms-resource:loc.input.help.location", + "properties": { + "EditableOptions": "True" + }, + "visibleRule": "scope != resourceGroup" + }, + { + "name": "tenantId", + "type": "string", + "label": "ms-resource:loc.input.label.tenantId", + "required": true, + "groupName": "AzureDetails", + "helpMarkDown": "ms-resource:loc.input.help.tenantId", + "visibleRule": "scope = tenant" + }, + { + "name": "managementGroupId", + "type": "string", + "label": "ms-resource:loc.input.label.managementGroupId", + "required": true, + "groupName": "AzureDetails", + "helpMarkDown": "ms-resource:loc.input.help.managementGroupId", + "visibleRule": "scope = managementGroup" + }, + { + "name": "templateFile", + "type": "filePath", + "label": "ms-resource:loc.input.label.templateFile", + "defaultValue": "", + "required": false, + "groupName": "Template", + "helpMarkDown": "ms-resource:loc.input.help.templateFile" + }, + { + "name": "parametersFile", + "type": "filePath", + "label": "ms-resource:loc.input.label.parametersFile", + "defaultValue": "", + "required": false, + "groupName": "Template", + "helpMarkDown": "ms-resource:loc.input.help.parametersFile" + }, + { + "name": "parameters", + "type": "multiLine", + "label": "ms-resource:loc.input.label.parameters", + "defaultValue": "", + "required": false, + "groupName": "Template", + "helpMarkDown": "ms-resource:loc.input.help.parameters" + }, + { + "name": "actionOnUnmanageResources", + "type": "pickList", + "label": "ms-resource:loc.input.label.actionOnUnmanageResources", + "defaultValue": "detach", + "required": true, + "groupName": "DeploymentStack", + "helpMarkDown": "ms-resource:loc.input.help.actionOnUnmanageResources", + "options": { + "delete": "Delete", + "detach": "Detach" + }, + "visibleRule": "type = deploymentStack" + }, + { + "name": "actionOnUnmanageResourceGroups", + "type": "pickList", + "label": "ms-resource:loc.input.label.actionOnUnmanageResourceGroups", + "defaultValue": "", + "required": false, + "groupName": "DeploymentStack", + "helpMarkDown": "ms-resource:loc.input.help.actionOnUnmanageResourceGroups", + "options": { + "delete": "Delete", + "detach": "Detach" + }, + "visibleRule": "type = deploymentStack" + }, + { + "name": "actionOnUnmanageManagementGroups", + "type": "pickList", + "label": "ms-resource:loc.input.label.actionOnUnmanageManagementGroups", + "defaultValue": "", + "required": false, + "groupName": "DeploymentStack", + "helpMarkDown": "ms-resource:loc.input.help.actionOnUnmanageManagementGroups", + "options": { + "delete": "Delete", + "detach": "Detach" + }, + "visibleRule": "type = deploymentStack" + }, + { + "name": "denySettingsMode", + "type": "pickList", + "label": "ms-resource:loc.input.label.denySettingsMode", + "defaultValue": "none", + "required": true, + "groupName": "DeploymentStack", + "helpMarkDown": "ms-resource:loc.input.help.denySettingsMode", + "options": { + "none": "None", + "denyDelete": "Deny Delete", + "denyWriteAndDelete": "Deny Write and Delete" + }, + "visibleRule": "type = deploymentStack" + }, + { + "name": "denySettingsExcludedActions", + "type": "string", + "label": "ms-resource:loc.input.label.denySettingsExcludedActions", + "defaultValue": "", + "required": false, + "groupName": "DeploymentStack", + "helpMarkDown": "ms-resource:loc.input.help.denySettingsExcludedActions", + "visibleRule": "type = deploymentStack && denySettingsMode != none" + }, + { + "name": "denySettingsExcludedPrincipals", + "type": "string", + "label": "ms-resource:loc.input.label.denySettingsExcludedPrincipals", + "defaultValue": "", + "required": false, + "groupName": "DeploymentStack", + "helpMarkDown": "ms-resource:loc.input.help.denySettingsExcludedPrincipals", + "visibleRule": "type = deploymentStack && denySettingsMode != none" + }, + { + "name": "denySettingsApplyToChildScopes", + "type": "boolean", + "label": "ms-resource:loc.input.label.denySettingsApplyToChildScopes", + "defaultValue": "false", + "required": false, + "groupName": "DeploymentStack", + "helpMarkDown": "ms-resource:loc.input.help.denySettingsApplyToChildScopes", + "visibleRule": "type = deploymentStack && denySettingsMode != none" + }, + { + "name": "bypassStackOutOfSyncError", + "type": "boolean", + "label": "ms-resource:loc.input.label.bypassStackOutOfSyncError", + "defaultValue": "false", + "required": false, + "groupName": "DeploymentStack", + "helpMarkDown": "ms-resource:loc.input.help.bypassStackOutOfSyncError", + "visibleRule": "type = deploymentStack" + }, + { + "name": "description", + "type": "string", + "label": "ms-resource:loc.input.label.description", + "defaultValue": "", + "required": false, + "groupName": "Advanced", + "helpMarkDown": "ms-resource:loc.input.help.description" + }, + { + "name": "tags", + "type": "multiLine", + "label": "ms-resource:loc.input.label.tags", + "defaultValue": "", + "required": false, + "groupName": "Advanced", + "helpMarkDown": "ms-resource:loc.input.help.tags", + "visibleRule": "type = deploymentStack" + }, + { + "name": "bicepVersion", + "type": "string", + "label": "ms-resource:loc.input.label.bicepVersion", + "defaultValue": "", + "required": false, + "groupName": "Advanced", + "helpMarkDown": "ms-resource:loc.input.help.bicepVersion" + }, + { + "name": "maskedOutputs", + "type": "string", + "label": "ms-resource:loc.input.label.maskedOutputs", + "defaultValue": "", + "required": false, + "groupName": "Advanced", + "helpMarkDown": "ms-resource:loc.input.help.maskedOutputs" + }, + { + "name": "environment", + "type": "pickList", + "label": "ms-resource:loc.input.label.environment", + "defaultValue": "azureCloud", + "required": false, + "groupName": "Advanced", + "helpMarkDown": "ms-resource:loc.input.help.environment", + "options": { + "azureCloud": "Azure Cloud", + "azureChinaCloud": "Azure China Cloud", + "azureGermanCloud": "Azure German Cloud", + "azureUSGovernment": "Azure US Government" + } + }, + { + "name": "whatIfExcludeChangeTypes", + "type": "string", + "label": "ms-resource:loc.input.label.whatIfExcludeChangeTypes", + "defaultValue": "", + "required": false, + "groupName": "Advanced", + "helpMarkDown": "ms-resource:loc.input.help.whatIfExcludeChangeTypes", + "visibleRule": "operation = whatIf" + }, + { + "name": "validationLevel", + "type": "pickList", + "label": "ms-resource:loc.input.label.validationLevel", + "defaultValue": "", + "required": false, + "groupName": "Advanced", + "helpMarkDown": "ms-resource:loc.input.help.validationLevel", + "options": { + "provider": "Provider", + "template": "Template", + "providerNoRbac": "Provider (No RBAC)" + }, + "visibleRule": "type = deployment && (operation = validate || operation = whatIf)" + } + ], + "messages": { + "CreateFailed": "ms-resource:loc.messages.CreateFailed", + "ValidationFailed": "ms-resource:loc.messages.ValidationFailed", + "OperationFailed": "ms-resource:loc.messages.OperationFailed", + "RequestFailedCorrelation": "ms-resource:loc.messages.RequestFailedCorrelation", + "InputMustBeBoolean": "ms-resource:loc.messages.InputMustBeBoolean", + "InputRequired": "ms-resource:loc.messages.InputRequired", + "InputMustBeEnum": "ms-resource:loc.messages.InputMustBeEnum", + "InputMustBeValidObject": "ms-resource:loc.messages.InputMustBeValidObject", + "InputMustBeStringObject": "ms-resource:loc.messages.InputMustBeStringObject", + "LocationRequired": "ms-resource:loc.messages.LocationRequired", + "FailedToDetermineScope": "ms-resource:loc.messages.FailedToDetermineScope", + "UnsupportedParametersFile": "ms-resource:loc.messages.UnsupportedParametersFile", + "UnsupportedTemplateFile": "ms-resource:loc.messages.UnsupportedTemplateFile", + "TemplateFileRequired": "ms-resource:loc.messages.TemplateFileRequired", + "InvalidChangeType": "ms-resource:loc.messages.InvalidChangeType", + "UnknownPropertyChangeType": "ms-resource:loc.messages.UnknownPropertyChangeType", + "InvalidJsonValue": "ms-resource:loc.messages.InvalidJsonValue", + "DiagnosticsReturned": "ms-resource:loc.messages.DiagnosticsReturned", + "BicepVersionInstalled": "ms-resource:loc.messages.BicepVersionInstalled", + "TaskConfig": "ms-resource:loc.messages.TaskConfig", + "OperationSucceeded": "ms-resource:loc.messages.OperationSucceeded" + }, + "execution": { + "Node16": { + "target": "main.js" + }, + "Node20_1": { + "target": "main.js" + } + } +} \ No newline at end of file diff --git a/Tasks/BicepDeployV0/taskIO.ts b/Tasks/BicepDeployV0/taskIO.ts new file mode 100644 index 000000000000..a9d50cdf06bd --- /dev/null +++ b/Tasks/BicepDeployV0/taskIO.ts @@ -0,0 +1,52 @@ +import { InputParameterNames, InputReader, OutputSetter } from '@azure/bicep-deploy-common'; +import tl = require('azure-pipelines-task-lib/task'); + +export class TaskInputReader implements InputReader { + getInput(inputName: string): string | undefined { + return tl.getInput(inputName, false); + } +} + +export class TaskOutputSetter implements OutputSetter { + setOutput(name: string, value: any): void { + tl.setVariable(name, value); + } + + setFailed(message: string): void { + tl.setResult(tl.TaskResult.Failed, message); + } + + setSecret(secret: string): void { + tl.setSecret(secret); + } +} + +export class TaskInputParameterNames implements InputParameterNames { + type = 'type'; + name = 'name'; + location = 'location'; + templateFile = 'templateFile'; + parametersFile = 'parametersFile'; + parameters = 'parameters'; + bicepVersion = 'bicepVersion'; + description = 'description'; + tags = 'tags'; + maskedOutputs = 'maskedOutputs'; + environment = 'environment'; + operation = 'operation'; + whatIfExcludeChangeTypes = 'whatIfExcludeChangeTypes'; + validationLevel = 'validationLevel'; + actionOnUnmanageResources = 'actionOnUnmanageResources'; + actionOnUnmanageResourceGroups = 'actionOnUnmanageResourceGroups'; + actionOnUnmanageManagementGroups = 'actionOnUnmanageManagementGroups'; + bypassStackOutOfSyncError = 'bypassStackOutOfSyncError'; + denySettingsMode = 'denySettingsMode'; + denySettingsExcludedActions = 'denySettingsExcludedActions'; + denySettingsExcludedPrincipals = 'denySettingsExcludedPrincipals'; + denySettingsApplyToChildScopes = 'denySettingsApplyToChildScopes'; + scope = 'scope'; + tenantId = 'tenantId'; + managementGroupId = 'managementGroupId'; + subscriptionId = 'subscriptionId'; + resourceGroupName = 'resourceGroupName'; +} \ No newline at end of file diff --git a/Tasks/BicepDeployV0/tsconfig.json b/Tasks/BicepDeployV0/tsconfig.json new file mode 100644 index 000000000000..79a868c8d1e3 --- /dev/null +++ b/Tasks/BicepDeployV0/tsconfig.json @@ -0,0 +1,9 @@ +{ + "compilerOptions": { + "target": "ES6", + "module": "commonjs" + }, + "exclude": [ + "node_modules" + ] +} \ No newline at end of file diff --git a/make-options.json b/make-options.json index 326941b00b3d..623879c14acd 100644 --- a/make-options.json +++ b/make-options.json @@ -57,6 +57,7 @@ "AzureVmssDeploymentV1", "BashV3", "BatchScriptV1", + "BicepDeployV0", "CacheBetaV0", "CacheBetaV1", "CacheV2", @@ -302,6 +303,7 @@ "AzureWebAppContainerV1", "AzureWebAppV1", "BashV3", + "BicepDeployV0", "CargoAuthenticateV0", "ChefKnifeV1", "ChefV1", From 56197dbdf5df54c140e639631726ac76e671bbe0 Mon Sep 17 00:00:00 2001 From: snehabandla Date: Fri, 5 Dec 2025 15:14:12 -0800 Subject: [PATCH 2/2] Updating code owners --- .github/CODEOWNERS | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index dbe4984fbaca..4de0b1e28a4d 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -94,6 +94,8 @@ Tasks/AzureResourceGroupDeploymentV2/ @microsoft/release-management-task-te Tasks/AzureResourceManagerTemplateDeploymentV3/ @microsoft/release-management-task-team @manolerazvan +Tasks/BicepDeployV0/ @azure/bicep-admins + # DRI rotation: App Service (Web Apps) Tasks/AzureRmWebAppDeploymentV3/ @jvano @dannysongg @microsoft/azure-app-service-pipelines-tasks @microsoft/release-management-task-team @manolerazvan