diff --git a/.CodeQL.yml b/.CodeQL.yml new file mode 100644 index 00000000000..71d797b7904 --- /dev/null +++ b/.CodeQL.yml @@ -0,0 +1,10 @@ +# This file configures CodeQL scanning path exclusions. +# For more information, see: +# https://eng.ms/docs/cloud-ai-platform/devdiv/one-engineering-system-1es/1es-docs/codeql/troubleshooting/bugs/generated-library-code + +path_classifiers: + refs: + # The playground and tests directories are not product code, + # so they don't need to be scanned by CodeQL. + - playground/** + - tests/** diff --git a/.github/workflows/auto-rerun-transient-ci-failures.js b/.github/workflows/auto-rerun-transient-ci-failures.js index 41a996ee9ac..83b4bb788a9 100644 --- a/.github/workflows/auto-rerun-transient-ci-failures.js +++ b/.github/workflows/auto-rerun-transient-ci-failures.js @@ -28,6 +28,11 @@ const ignoredFailureStepPatterns = [ /^Install dependencies$/i, ]; +const testExecutionFailureStepPatterns = [ + /^Run tests\b/i, + /^Run nuget dependent tests\b/i, +]; + const transientAnnotationPatterns = [ /The job was not acquired by Runner of type hosted even after multiple attempts/i, /The hosted runner lost communication with the server/i, @@ -72,25 +77,29 @@ const windowsProcessInitializationFailurePatterns = [ /\b0xC0000142\b/i, ]; -const feedNetworkFailureStepPatterns = [ - /^Install sdk for nuget based testing$/i, - /^Build test project$/i, - /^Build and archive test project$/i, - /^Build with packages$/i, - /^Build RID-specific packages\b/i, - /^Build .*validation image$/i, - /^Run .*SDK validation$/i, - /^Rebuild for Azure Functions project$/i, -]; - -const ignoredBuildFailureLogOverridePatterns = [ +const infrastructureNetworkFailureLogOverridePatterns = [ /Unable to load the service index for source https:\/\/(?:pkgs\.dev\.azure\.com\/dnceng|dnceng\.pkgs\.visualstudio\.com)\/public\/_packaging\//i, + /(timed out|failed to connect|could not resolve|ENOTFOUND|ECONNRESET|EPROTO|Bad Gateway|SSL connection could not be established).{0,160}https:\/\/(?:pkgs\.dev\.azure\.com\/dnceng|dnceng\.pkgs\.visualstudio\.com)\/public\/_packaging\//i, + /https:\/\/(?:pkgs\.dev\.azure\.com\/dnceng|dnceng\.pkgs\.visualstudio\.com)\/public\/_packaging\/.{0,160}(timed out|failed to connect|could not resolve|ENOTFOUND|ECONNRESET|EPROTO|Bad Gateway|SSL connection could not be established)/i, + /(timed out|failed to connect|could not resolve|ENOTFOUND|ECONNRESET|EPROTO|Bad Gateway|SSL connection could not be established).{0,160}builds\.dotnet\.microsoft\.com/i, + /builds\.dotnet\.microsoft\.com.{0,160}(timed out|failed to connect|could not resolve|ENOTFOUND|ECONNRESET|EPROTO|Bad Gateway|SSL connection could not be established)/i, + /(timed out|failed to connect|failed to respond|could not resolve|ENOTFOUND|ECONNRESET|EPROTO|Bad Gateway|SSL connection could not be established).{0,160}api\.github\.com/i, + /api\.github\.com.{0,160}(timed out|failed to connect|failed to respond|could not resolve|ENOTFOUND|ECONNRESET|EPROTO|Bad Gateway|SSL connection could not be established)/i, + /fatal: unable to access 'https:\/\/github\.com\/.*': The requested URL returned error:\s*(502|503|504)/i, + /Failed to connect to github\.com port/i, + /expected 'packfile'/i, + /\bRPC failed\b/i, + /\bRecv failure\b/i, ]; function matchesAny(value, patterns) { return patterns.some(pattern => pattern.test(value)); } +function findMatchingPattern(value, patterns) { + return patterns.find(pattern => pattern.test(value)) ?? null; +} + function parseCheckRunId(checkRunUrl) { if (typeof checkRunUrl !== 'string') { return null; @@ -154,16 +163,81 @@ function getFailureStepSignals(failedSteps) { }; } +function canUseInfrastructureNetworkLogOverride(failedSteps) { + return failedSteps.length > 0 && !failedSteps.some(step => matchesAny(step, testExecutionFailureStepPatterns)); +} + +function formatFailedStepLabel(failedSteps, failedStepText) { + const label = failedSteps.length === 1 ? 'Failed step' : 'Failed steps'; + return `${label} '${failedStepText}'`; +} + +function isSingleFailedStep(failedSteps) { + return failedSteps.length === 1; +} + +function getInfrastructureNetworkLogOverrideReason(failedStepText, matchedPattern) { + const patternText = matchedPattern ? ` Matched pattern: ${matchedPattern}.` : ''; + return `Failed step '${failedStepText}' will be retried because the job log shows a likely transient infrastructure network failure.${patternText}`; +} + +function getOutsideRetryRulesReason(failedSteps, failedStepText) { + return `${formatFailedStepLabel(failedSteps, failedStepText)} ${isSingleFailedStep(failedSteps) ? 'is' : 'are'} not covered by the retry-safe rerun rules.`; +} + +function getNoRetryMatchReason({ + failedSteps, + failedStepText, + hasRetryableStep, + hasIgnoredFailureStep, + hasTestExecutionFailureStep, + annotationsText, +}) { + const failedStepLabel = formatFailedStepLabel(failedSteps, failedStepText); + + if (hasTestExecutionFailureStep) { + return `${failedStepLabel} ${isSingleFailedStep(failedSteps) ? 'includes' : 'include'} a test execution failure, so the job was not retried without a high-confidence infrastructure override.`; + } + + if (hasIgnoredFailureStep) { + return `${failedStepLabel} ${isSingleFailedStep(failedSteps) ? 'is' : 'are'} only retried when the job shows a high-confidence infrastructure override, and none was found.`; + } + + if (hasRetryableStep) { + return `${failedStepLabel} did not include a retry-safe transient infrastructure signal in the job annotations.`; + } + + if (annotationsText) { + return 'The job annotations did not show a retry-safe transient infrastructure failure.'; + } + + return 'No retry-safe transient infrastructure signal was found in the job annotations or logs.'; +} + function classifyFailedJob(job, annotationsOrText, jobLogText = '') { const failedSteps = getFailedSteps(job); const failedStepText = failedSteps.join(' | '); const { hasRetryableStep, hasIgnoredFailureStep, shouldInspectAnnotations } = getFailureStepSignals(failedSteps); + const hasTestExecutionFailureStep = failedSteps.some(step => matchesAny(step, testExecutionFailureStepPatterns)); + const matchedInfrastructureNetworkLogOverridePattern = + !hasTestExecutionFailureStep + ? findMatchingPattern(jobLogText, infrastructureNetworkFailureLogOverridePatterns) + : null; + const matchesInfrastructureNetworkLogOverride = matchedInfrastructureNetworkLogOverridePattern !== null; if (!shouldInspectAnnotations) { + if (matchesInfrastructureNetworkLogOverride) { + return { + retryable: true, + failedSteps, + reason: getInfrastructureNetworkLogOverrideReason(failedStepText, matchedInfrastructureNetworkLogOverridePattern), + }; + } + return { retryable: false, failedSteps, - reason: 'Failed steps are outside the retry-safe allowlist.', + reason: getOutsideRetryRulesReason(failedSteps, failedStepText), }; } @@ -206,21 +280,25 @@ function classifyFailedJob(job, annotationsOrText, jobLogText = '') { }; } - const hasIgnoredBuildFailureStep = failedSteps.some(step => matchesAny(step, feedNetworkFailureStepPatterns)); - if (hasIgnoredBuildFailureStep && matchesAny(jobLogText, ignoredBuildFailureLogOverridePatterns)) { + if (matchesInfrastructureNetworkLogOverride) { return { retryable: true, failedSteps, - reason: `Ignored failed step '${failedStepText}' matched the feed network failure override allowlist.`, + reason: getInfrastructureNetworkLogOverrideReason(failedStepText, matchedInfrastructureNetworkLogOverridePattern), }; } return { retryable: false, failedSteps, - reason: annotationsText - ? 'Annotations did not match the transient allowlist.' - : 'No retry-safe step or annotation signature matched.', + reason: getNoRetryMatchReason({ + failedSteps, + failedStepText, + hasRetryableStep, + hasIgnoredFailureStep, + hasTestExecutionFailureStep, + annotationsText, + }), }; } @@ -243,7 +321,7 @@ async function analyzeFailedJobs({ jobs, getAnnotationsForJob, getJobLogTextForJ const shouldInspectLogs = !classification.retryable && getJobLogTextForJob && - failedSteps.some(step => matchesAny(step, feedNetworkFailureStepPatterns)); + canUseInfrastructureNetworkLogOverride(failedSteps); if (shouldInspectLogs) { classification = classifyFailedJob( @@ -276,6 +354,47 @@ function computeRerunEligibility({ dryRun, retryableCount, maxRetryableJobs = de return !dryRun && retryableCount > 0 && retryableCount <= maxRetryableJobs; } +function buildSummaryReference(url, text) { + return { url, text }; +} + +function addSummaryReference(summary, label, reference) { + summary.addRaw(`${label}: `); + + if (reference?.url) { + summary.addLink(reference.text, reference.url); + } + else { + summary.addRaw(reference?.text || 'not available'); + } + + return summary.addBreak(); +} + +function addSummaryCommentReferences(summary, postedComments) { + if (!postedComments?.length) { + summary.addRaw('Pull request comments: none posted').addBreak(); + return summary; + } + + summary.addRaw('Pull request comments:').addBreak(); + + for (const comment of postedComments) { + summary.addRaw('- '); + + if (comment.htmlUrl) { + summary.addLink(`PR #${comment.pullRequestNumber} comment`, comment.htmlUrl); + } + else { + summary.addRaw(`PR #${comment.pullRequestNumber} comment`); + } + + summary.addBreak(); + } + + return summary; +} + async function writeAnalysisSummary({ summary, failedJobs, @@ -285,9 +404,27 @@ async function writeAnalysisSummary({ dryRun, rerunEligible, sourceRunUrl, + sourceRunAttempt, }) { + const analyzedRunReference = buildSummaryReference( + buildWorkflowRunAttemptUrl(sourceRunUrl, sourceRunAttempt), + Number.isInteger(sourceRunAttempt) && sourceRunAttempt > 0 + ? `workflow run attempt ${sourceRunAttempt}` + : 'workflow run' + ); + const outcome = rerunEligible ? 'Rerun eligible' : 'Rerun skipped'; + const outcomeDetails = rerunEligible + ? `Matched ${retryableJobs.length} retry-safe job${retryableJobs.length === 1 ? '' : 's'} for rerun.` + : retryableJobs.length === 0 + ? 'No retry-safe jobs were found in the analyzed run.' + : dryRun + ? 'Dry run is enabled, so no rerun requests will be sent.' + : retryableJobs.length > maxRetryableJobs + ? `Matched ${retryableJobs.length} jobs, which exceeds the cap of ${maxRetryableJobs}.` + : 'The analyzed run did not satisfy the workflow safety rails for reruns.'; const summaryRows = [ [{ data: 'Category', header: true }, { data: 'Count', header: true }], + ['Outcome', outcome], ['Failed jobs inspected', String(failedJobs.length)], ['Retryable jobs', String(retryableJobs.length)], ['Skipped jobs', String(skippedJobs.length)], @@ -295,14 +432,15 @@ async function writeAnalysisSummary({ ['Dry run', String(dryRun)], ['Eligible to rerun', String(rerunEligible)], ]; - const sourceRunReference = sourceRunUrl - ? `[workflow run](${sourceRunUrl})` - : 'workflow run'; await summary - .addHeading('Transient CI rerun analysis') - .addTable(summaryRows) - .addRaw(`Source run: ${sourceRunReference}\n\n`); + .addHeading(outcome) + .addTable(summaryRows); + + addSummaryReference(summary, 'Analyzed run', analyzedRunReference) + .addRaw(outcomeDetails) + .addBreak() + .addBreak(); if (retryableJobs.length > 0) { await summary.addHeading('Retryable jobs', 2); @@ -320,12 +458,6 @@ async function writeAnalysisSummary({ ]); } - if (retryableJobs.length > maxRetryableJobs) { - await summary - .addHeading('Automatic rerun skipped', 2) - .addRaw(`Matched ${retryableJobs.length} jobs, which exceeds the cap of ${maxRetryableJobs}.`, true); - } - await summary.write(); } @@ -361,20 +493,17 @@ function buildWorkflowRunAttemptUrl(sourceRunUrl, runAttempt) { return `${sourceRunUrl.replace(/\/$/, '')}/attempts/${runAttempt}`; } -function buildWorkflowRunReferenceText(sourceRunUrl, runAttempt) { - const workflowRunUrl = buildWorkflowRunAttemptUrl(sourceRunUrl, runAttempt); - - if (!workflowRunUrl) { - return Number.isInteger(runAttempt) && runAttempt > 0 +function buildWorkflowRunReference(sourceRunUrl, runAttempt) { + return buildSummaryReference( + buildWorkflowRunAttemptUrl(sourceRunUrl, runAttempt), + Number.isInteger(runAttempt) && runAttempt > 0 ? `workflow run attempt ${runAttempt}` - : 'workflow run'; - } - - const label = Number.isInteger(runAttempt) && runAttempt > 0 - ? `workflow run attempt ${runAttempt}` - : 'workflow run'; + : 'workflow run' + ); +} - return `[${label}](${workflowRunUrl})`; +function formatMarkdownLink(text, url) { + return url ? `[${text}](${url})` : text; } async function getLatestRunAttempt({ github, owner, repo, runId }) { @@ -403,8 +532,8 @@ function buildPullRequestCommentBody({ retryableJobs, }) { return [ - `The transient CI rerun workflow requested reruns for the following jobs after analyzing [the failed attempt](${failedAttemptUrl}).`, - `GitHub's job rerun API also reruns dependent jobs, so the retry is being tracked in [the rerun attempt](${rerunAttemptUrl}).`, + `The transient CI rerun workflow requested reruns for the following jobs after analyzing ${formatMarkdownLink('the failed attempt', failedAttemptUrl)}.`, + `GitHub's job rerun API also reruns dependent jobs, so the retry is being tracked in ${formatMarkdownLink('the rerun attempt', rerunAttemptUrl)}.`, 'The job links below point to the failed attempt that matched the retry-safe transient failure rules.', '', ...retryableJobs.map(job => { @@ -418,14 +547,23 @@ function buildPullRequestCommentBody({ } async function addPullRequestComments({ github, owner, repo, pullRequestNumbers, body }) { + const postedComments = []; + for (const pullRequestNumber of pullRequestNumbers) { - await github.request('POST /repos/{owner}/{repo}/issues/{issue_number}/comments', { + const response = await github.request('POST /repos/{owner}/{repo}/issues/{issue_number}/comments', { owner, repo, issue_number: pullRequestNumber, body, }); + + postedComments.push({ + pullRequestNumber, + htmlUrl: response.data?.html_url || null, + }); } + + return postedComments; } async function rerunMatchedJobs({ @@ -451,9 +589,21 @@ async function rerunMatchedJobs({ }); if (pullRequestNumbers.length > 0 && openPullRequestNumbers.length === 0) { + const failedAttemptReference = buildWorkflowRunReference(sourceRunUrl, sourceRunAttempt); await summary - .addHeading('Automatic rerun skipped') - .addRaw('All associated pull requests are closed. No jobs were rerun.', true) + .addHeading('Rerun skipped'); + + addSummaryReference(summary, 'Analyzed run', failedAttemptReference) + .addRaw('All associated pull requests are closed. No jobs were rerun.') + .addBreak() + .addBreak(); + + await summary + .addHeading('Retryable jobs', 2) + .addTable([ + [{ data: 'Job', header: true }, { data: 'Reason', header: true }], + ...retryableJobs.map(job => [job.name, job.reason]), + ]) .write(); return; } @@ -480,41 +630,37 @@ async function rerunMatchedJobs({ ? latestRunAttempt : normalizedSourceRunAttempt ? normalizedSourceRunAttempt + 1 : null; const rerunAttemptUrl = buildWorkflowRunAttemptUrl(sourceRunUrl, rerunAttemptNumber); - const failedAttemptReference = buildWorkflowRunReferenceText(sourceRunUrl, normalizedSourceRunAttempt); - const rerunAttemptReference = buildWorkflowRunReferenceText(sourceRunUrl, rerunAttemptNumber); + const failedAttemptReference = buildWorkflowRunReference(sourceRunUrl, normalizedSourceRunAttempt); + const rerunAttemptReference = buildWorkflowRunReference(sourceRunUrl, rerunAttemptNumber); + let postedComments = []; if (openPullRequestNumbers.length > 0) { - await addPullRequestComments({ + postedComments = await addPullRequestComments({ github, owner, repo, pullRequestNumbers: openPullRequestNumbers, body: buildPullRequestCommentBody({ - failedAttemptUrl, - rerunAttemptUrl, + failedAttemptUrl: failedAttemptReference.url, + rerunAttemptUrl: rerunAttemptReference.url, retryableJobs, }), }); } - const commentedPullRequestsText = openPullRequestNumbers.length > 0 - ? openPullRequestNumbers.map(number => `#${number}`).join(', ') - : null; - const summaryBuilder = summary - .addHeading('Rerun requested') - .addRaw(`Failed attempt: ${failedAttemptReference}\nRerun attempt: ${rerunAttemptReference}\n\n`) + .addHeading('Rerun requested'); + + addSummaryReference(summaryBuilder, 'Failed attempt', failedAttemptReference); + addSummaryReference(summaryBuilder, 'Rerun attempt', rerunAttemptReference); + addSummaryCommentReferences(summaryBuilder, postedComments).addBreak(); + + summaryBuilder .addTable([ [{ data: 'Job', header: true }, { data: 'Reason', header: true }], ...retryableJobs.map(job => [job.name, job.reason]), ]); - if (commentedPullRequestsText) { - summaryBuilder - .addHeading('Pull request comments', 2) - .addRaw(`Posted rerun details to ${commentedPullRequestsText}.`, true); - } - await summaryBuilder.write(); } diff --git a/.github/workflows/auto-rerun-transient-ci-failures.yml b/.github/workflows/auto-rerun-transient-ci-failures.yml index 2613e71eb13..4f7b368b6e5 100644 --- a/.github/workflows/auto-rerun-transient-ci-failures.yml +++ b/.github/workflows/auto-rerun-transient-ci-failures.yml @@ -15,6 +15,11 @@ on: description: 'CI workflow run ID to inspect' required: true type: number + dry_run: + description: 'Inspect and summarize without requesting reruns' + required: false + default: false + type: boolean concurrency: group: ${{ github.workflow }}-${{ github.event_name == 'workflow_dispatch' && inputs.run_id || github.event.workflow_run.id }} @@ -57,6 +62,7 @@ jobs: env: GITHUB_TOKEN: ${{ github.token }} MANUAL_RUN_ID: ${{ inputs.run_id }} + MANUAL_DRY_RUN: ${{ inputs.dry_run }} with: script: | const rerunWorkflow = require('./.github/workflows/auto-rerun-transient-ci-failures.js'); @@ -103,6 +109,14 @@ jobs: return response.data; } + function parseManualDryRun() { + if (!isWorkflowDispatch) { + return false; + } + + return String(process.env.MANUAL_DRY_RUN).toLowerCase() === 'true'; + } + async function listJobsForAttempt(runId, attemptNumber) { return paginate( 'GET /repos/{owner}/{repo}/actions/runs/{run_id}/attempts/{attempt_number}/jobs', @@ -173,7 +187,7 @@ jobs: } const workflowRun = await getWorkflowRun(); - const dryRun = isWorkflowDispatch; + const dryRun = parseManualDryRun(); const sourceRunUrl = workflowRun.html_url || `https://github.com/${owner}/${repo}/actions/runs/${workflowRun.id}`; core.setOutput('source_run_id', String(workflowRun.id)); @@ -236,6 +250,7 @@ jobs: dryRun, rerunEligible, sourceRunUrl, + sourceRunAttempt: runAttempt, }); if (retryableJobs.length === 0) { @@ -243,11 +258,6 @@ jobs: return; } - if (dryRun) { - console.log('workflow_dispatch runs in dry-run mode. No jobs will be rerun.'); - return; - } - rerun-transient-failures: name: Rerun transient CI failures needs: [analyze-transient-failures] diff --git a/Aspire.slnx b/Aspire.slnx index 03ee4cce7bd..d341be34c8d 100644 --- a/Aspire.slnx +++ b/Aspire.slnx @@ -48,6 +48,7 @@ + @@ -383,6 +384,7 @@ + diff --git a/Directory.Packages.props b/Directory.Packages.props index 58f97e5297d..af7835183e6 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -211,6 +211,7 @@ + diff --git a/docs/ci/auto-rerun-transient-ci-failures.md b/docs/ci/auto-rerun-transient-ci-failures.md index 38bfb0aecdf..a6329136dd8 100644 --- a/docs/ci/auto-rerun-transient-ci-failures.md +++ b/docs/ci/auto-rerun-transient-ci-failures.md @@ -12,7 +12,7 @@ It is intentionally conservative: - it does not rerun every failed job in a run - it treats mixed deterministic failures plus transient post-step noise as non-retryable by default -- it keeps `workflow_dispatch` in dry-run mode for historical inspection and matcher tuning +- it keeps `workflow_dispatch` behind the same matcher and safety rails as automatic execution, with an optional dry-run mode for inspection-only runs ## Matcher behavior @@ -23,16 +23,18 @@ It is intentionally conservative: - Keep the mixed-failure veto: if an ignored step such as `Run tests*` failed, do not rerun the job based only on unrelated transient post-step noise. - Allow a narrow override when an ignored failed step is paired with a high-confidence job-level infrastructure annotation such as runner loss or action-download failure. - Allow a narrow override for Windows jobs whose failures are limited to post-test cleanup or upload steps when the annotations report process initialization failure `-1073741502` (`0xC0000142`). -- Allow a narrow log-based override for supported CI SDK bootstrap, build, package, and validation steps when the job log shows `Unable to load the service index` against the approved `dnceng` public feeds. +- Allow a narrow log-based override for non-test-execution failures when the job log shows high-confidence infrastructure network failures against approved `dnceng` public feeds, `builds.dotnet.microsoft.com`, `api.github.com`, or `github.com`. ## Safety rails -- `workflow_dispatch` remains dry-run only. It exists for historical inspection and matcher tuning, not for issuing reruns. +- `workflow_dispatch` can inspect any `CI` workflow run by ID and request reruns when the same retry-safety rules are satisfied. +- `workflow_dispatch` also exposes an optional `dry_run` input so manual runs can produce the analysis summary without sending rerun requests. - Automatic rerun requires at least one retryable job. - Automatic rerun is suppressed when matched jobs exceed the configured cap. - Before issuing reruns, the workflow confirms that at least one associated pull request is still open. - The workflow targets only the matched jobs when issuing rerun requests rather than rerunning the entire source run, although GitHub's job-rerun API also reruns dependent jobs automatically. -- The workflow summary links to the analyzed workflow run and, when reruns are requested, to both the failed attempt and the rerun attempt. +- The workflow summary clearly states whether reruns were skipped, are eligible, or were requested, and links to the analyzed workflow run. +- When reruns are requested, the rerun summary also links to both the failed attempt and the rerun attempt, plus any posted pull request comments. - After successful rerun requests, the workflow comments on the open associated pull request with links to the failed attempt, the rerun attempt, per-job failed-attempt links, and retry reasons. ## Tests @@ -44,4 +46,4 @@ Those tests are intentionally behavior-focused rather than regex-focused: - they use representative fixtures for each supported behavior - they keep representative job and step fixtures anchored to the current CI workflow names so matcher coverage does not drift from the implementation - they cover the mixed-failure veto and ignored-step override explicitly -- they keep only a minimal set of YAML contract checks for safety rails such as `workflow_dispatch` dry-run mode, first-attempt-only automatic reruns, and gating the rerun job on `rerun_eligible` +- they keep only a minimal set of YAML contract checks for safety rails such as first-attempt-only automatic reruns, the optional manual `dry_run` override, enabling manual reruns through `workflow_dispatch`, and gating the rerun job on `rerun_eligible` diff --git a/eng/Versions.props b/eng/Versions.props index 77366ba7476..0b7846af180 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -93,6 +93,7 @@ 10.0.3 10.0.3 10.0.3 + 10.0.3 10.0.3 diff --git a/eng/pipelines/azure-pipelines-unofficial.yml b/eng/pipelines/azure-pipelines-unofficial.yml index ef0ca001eb1..c58d13a6a86 100644 --- a/eng/pipelines/azure-pipelines-unofficial.yml +++ b/eng/pipelines/azure-pipelines-unofficial.yml @@ -39,13 +39,15 @@ resources: extends: template: v1/1ES.Unofficial.PipelineTemplate.yml@1ESPipelineTemplates parameters: + settings: + networkIsolationPolicy: Permissive,CFSClean2 featureFlags: autoEnablePREfastWithNewRuleset: false autoEnableRoslynWithNewRuleset: false sdl: sourceAnalysisPool: name: NetCore1ESPool-Internal - image: windows.vs2022preview.amd64 + image: windows.vs2026preview.scout.amd64 os: windows containers: linux_x64: @@ -135,7 +137,7 @@ extends: pool: name: NetCore1ESPool-Internal - image: windows.vs2022preview.amd64 + image: windows.vs2026preview.scout.amd64 os: windows variables: @@ -162,6 +164,40 @@ extends: script: | Get-ChildItem -Path "$(Build.SourcesDirectory)\artifacts\packages" -File -Recurse | Select-Object FullName, @{Name="Size(MB)";Expression={[math]::Round($_.Length/1MB,2)}} | Format-Table -AutoSize + - task: NodeTool@0 + displayName: 🟣Install node.js + inputs: + versionSpec: '20.x' + + - task: npmAuthenticate@0 + displayName: 🟣NPM authenticate + inputs: + workingFile: $(Build.SourcesDirectory)\.npmrc + + - task: PowerShell@2 + displayName: 🟣Set .npmrc environment + inputs: + targetType: 'inline' + script: Write-Host "##vso[task.setvariable variable=NPM_CONFIG_USERCONFIG]$(Build.SourcesDirectory)\.npmrc" + + - task: PowerShell@2 + displayName: 🟣Install yarn + inputs: + targetType: 'inline' + script: | + npm install -g yarn@1.22.22 + yarn --version + workingDirectory: '$(Build.SourcesDirectory)' + + - task: PowerShell@2 + displayName: 🟣Install vsce + inputs: + targetType: 'inline' + script: | + npm install -g @vscode/vsce@3.7.1 + vsce --version + workingDirectory: '$(Build.SourcesDirectory)' + - template: /eng/pipelines/templates/BuildAndTest.yml parameters: dotnetScript: $(Build.SourcesDirectory)/dotnet.cmd diff --git a/eng/pipelines/azure-pipelines.yml b/eng/pipelines/azure-pipelines.yml index 75d22b26e68..6512082521e 100644 --- a/eng/pipelines/azure-pipelines.yml +++ b/eng/pipelines/azure-pipelines.yml @@ -105,6 +105,8 @@ resources: extends: template: v1/1ES.Official.PipelineTemplate.yml@1ESPipelineTemplates parameters: + settings: + networkIsolationPolicy: Permissive,CFSClean2 featureFlags: autoEnablePREfastWithNewRuleset: false autoEnableRoslynWithNewRuleset: false diff --git a/extension/README.md b/extension/README.md index 0f2f490c3c3..21444ab588e 100644 --- a/extension/README.md +++ b/extension/README.md @@ -1,39 +1,72 @@ +# Aspire for Visual Studio Code -# Aspire VS Code Extension +The official Aspire extension for VS Code. Run, debug, and deploy your Aspire apps without leaving the editor. -The Aspire VS Code extension provides a set of commands and tools to help you work with Aspire and Aspire AppHost projects directly from Visual Studio Code. +Aspire helps you build distributed apps — things like microservices, databases, containers, and frontends — and wire them together in code. This extension lets you do all of that from VS Code, with debugging support for **C#, Python, Node.js**, and more. -## Commands +--- -The extension adds the following commands to VS Code: +## Table of Contents -| Command | Description | +- [Features at a Glance](#features-at-a-glance) +- [Prerequisites](#prerequisites) +- [Getting Started](#getting-started) +- [Running and Debugging](#running-and-debugging) +- [The Aspire Sidebar](#the-aspire-sidebar) +- [The Aspire Dashboard](#the-aspire-dashboard) +- [Commands](#commands) +- [Language and Debugger Support](#language-and-debugger-support) +- [Extension Settings](#extension-settings) +- [MCP Server Integration](#mcp-server-integration) +- [Feedback and Issues](#feedback-and-issues) +- [License](#license) + +--- + +## Features at a Glance + +| Feature | Description | |---------|-------------| -| Aspire: New Aspire project | Create a new Aspire apphost or starter app from a template. | -| Aspire: Initialize Aspire | Initialize Aspire in an existing project. | -| Aspire: Add an integration | Add a hosting integration (`Aspire.Hosting.*`) to the Aspire apphost. | -| Aspire: Update integrations | Update hosting integrations and Aspire SDK in the apphost. | -| Aspire: Publish deployment artifacts | Generate deployment artifacts for an Aspire apphost. | -| Aspire: Deploy app | Deploy the contents of an Aspire apphost to its defined deployment targets. | -| Aspire: Execute pipeline step (aspire do) | Execute a specific pipeline step and its dependencies. | -| Aspire: Configure launch.json file | Add the default Aspire debugger launch configuration to your workspace's `launch.json`. | -| Aspire: Extension settings | Open Aspire extension settings. | -| Aspire: Open local Aspire settings | Open the local `.aspire/settings.json` file for the current workspace. | -| Aspire: Open global Aspire settings | Open the global `~/.aspire/globalsettings.json` file. | -| Aspire: Open Aspire terminal | Open an Aspire VS Code terminal for working with Aspire projects. | +| **Run & debug** | Start your whole app and attach debuggers to every service with F5 | +| **Dashboard** | See your resources, endpoints, logs, traces, and metrics while your app runs | +| **Sidebar** | Browse running apphosts and resources in the Activity Bar | +| **Integrations** | Add databases, queues, and cloud services from the Command Palette | +| **Scaffolding** | Create new Aspire projects from templates | +| **Deploy** | Generate deployment artifacts or push to cloud targets | +| **MCP** | Let AI tools like GitHub Copilot see your running app via the Model Context Protocol | +| **Multi-language** | Debug C#, Python, Node.js, Azure Functions, and browser apps together | -All commands are available from the Command Palette (`Cmd+Shift+P` or `Ctrl+Shift+P`) and are grouped under the "Aspire" category. +--- -## Debugging +## Prerequisites + +### Aspire CLI + +The [Aspire CLI](https://aspire.dev/get-started/install-cli/) needs to be installed and on your PATH. You can install it directly from VS Code with the **Aspire: Install Aspire CLI (stable)** command, or follow the [installation guide](https://aspire.dev/get-started/install-cli/) for manual setup. + +### .NET -To run an Aspire application using the Aspire VS Code extension, you must be using Aspire 9.5 or higher. Some features are only available when certain VS Code extensions are installed and available. See the feature matrix below: +[.NET 10 or later](https://dotnet.microsoft.com/download) is required. -| Feature | Requirement | Notes | -|---------|-------------|-------| -| Debug C# projects | [C# Dev Kit](https://marketplace.visualstudio.com/items?itemName=ms-dotnettools.csdevkit) or [C# for Visual Studio Code](https://marketplace.visualstudio.com/items?itemName=ms-dotnettools.csharp) | The C# extension is required for debugging .NET projects. Apphosts will be built in VS Code if C# Dev Kit is available. | -| Debug Python projects | [Python extension](https://marketplace.visualstudio.com/items?itemName=ms-python.python) | Required for debugging Python projects | +### VS Code -To run and debug your Aspire application, add an entry to the workspace `launch.json`. You can change the apphost to run by setting the `program` field to an apphost project file based on the below example: +VS Code 1.98 or later is required. + +--- + +## Getting Started + +Open your Aspire project in VS Code, or create one with **Aspire: New Aspire project** from the Command Palette. Run **Aspire: Configure launch.json file** to set up the debug configuration, then press **F5**. The extension will build your apphost, start your services, attach debuggers, and open the dashboard. + +There's also a built-in walkthrough at **Help → Get Started → Get started with Aspire** that covers the basics step by step. + +--- + +## Running and Debugging + +### Launch configuration + +Add an entry to `.vscode/launch.json` pointing at your apphost project: ```json { @@ -44,7 +77,17 @@ To run and debug your Aspire application, add an entry to the workspace `launch. } ``` -You can also use the `command` property to run deploy, publish, or pipeline step commands with the debugger attached: +When you hit **F5**, the extension builds the apphost, starts all the resources (services, containers, databases) in the right order, hooks up debuggers based on each service's language, and opens the dashboard. + +You can also right-click an `apphost.cs`, `apphost.ts`, or `apphost.js` file in the Explorer and pick **Run Aspire apphost** or **Debug Aspire apphost**. + +### Deploy, publish, and pipeline steps + +The `command` property in the launch config lets you do more than just run: + +- **`deploy`** — push to your defined deployment targets. +- **`publish`** — generate deployment artifacts (manifests, Bicep files, etc.). +- **`do`** — run a specific pipeline step. Set `step` to the step name. ```json { @@ -56,75 +99,129 @@ You can also use the `command` property to run deploy, publish, or pipeline step } ``` -Supported values for `command` are `run` (default), `deploy`, `publish`, and `do`. When using `do`, you can optionally set the `step` property to specify the pipeline step to execute: +### Customizing debugger settings per language + +The `debuggers` property lets you pass debug config specific to a language. Use `project` for C#/.NET services, `python` for Python, and `apphost` for the apphost itself: ```json { "type": "aspire", "request": "launch", - "name": "Aspire: Run pipeline step", + "name": "Aspire: Launch MyAppHost", "program": "${workspaceFolder}/MyAppHost/MyAppHost.csproj", - "command": "do", - "step": "my-custom-step" + "debuggers": { + "project": { + "console": "integratedTerminal", + "logging": { "moduleLoad": false } + }, + "apphost": { + "stopAtEntry": true + } + } } ``` -## Requirements +--- -### Aspire CLI +## The Aspire Sidebar -The [Aspire CLI](https://aspire.dev/get-started/install-cli/) must be installed and available on the path. You can install using the following scripts. +The extension adds an **Aspire** panel to the Activity Bar. It shows a live tree of your resources. In **Workspace** mode you see resources from the apphost in your current workspace, updating in real time. Switch to **Global** mode with the toggle in the panel header to see every running apphost on your machine. -On Windows: +Right-click a resource to start, stop, or restart it, view its logs, run resource-specific commands, or open the dashboard. -```powershell -irm https://aspire.dev/install.ps1 | iex -``` +--- -On Linux or macOS: +## The Aspire Dashboard -```sh -curl -sSL https://aspire.dev/install.sh | bash -``` +The dashboard gives you a live view of your running app — all your resources and their health, endpoint URLs, console logs from every service, structured logs (via OpenTelemetry), distributed traces across services, and metrics. -### .NET +![Aspire Dashboard showing running resources](resources/aspire-dashboard-dark.png) -[.NET 8+](https://dotnet.microsoft.com/en-us/download) must be installed. +It opens automatically when you start your app. You can pick which browser it uses with the `aspire.dashboardBrowser` setting — system default browser, or Chrome, Edge, or Firefox as a debug session. When using a debug browser, the `aspire.closeDashboardOnDebugEnd` setting controls whether it closes automatically when you stop debugging. Firefox also requires the [Firefox Debugger](https://marketplace.visualstudio.com/items?itemName=firefox-devtools.vscode-firefox-debug) extension. + +--- + +## Commands + +All commands live in the Command Palette (`Cmd+Shift+P` / `Ctrl+Shift+P`) under **Aspire**. + +| Command | Description | +|---------|-------------| +| **New Aspire project** | Create a new apphost or starter app from a template | +| **Initialize Aspire in an existing codebase** | Add Aspire to an existing project | +| **Add an integration** | Add a hosting integration (`Aspire.Hosting.*`) | +| **Update integrations** | Update hosting integrations and the Aspire SDK | +| **Publish deployment artifacts** | Generate deployment manifests | +| **Deploy app** | Deploy to your defined targets | +| **Execute pipeline step** | Run a pipeline step and its dependencies (`aspire do`) | +| **Configure launch.json file** | Add the Aspire debug config to your workspace | +| **Extension settings** | Open Aspire settings | +| **Open local Aspire settings** | Open `.aspire/settings.json` for this workspace | +| **Open global Aspire settings** | Open `~/.aspire/globalsettings.json` | +| **Open Aspire terminal** | Open a terminal with the Aspire CLI ready | +| **Install Aspire CLI (stable)** | Install the latest stable CLI | +| **Install Aspire CLI (daily)** | Install the daily preview build | +| **Update Aspire CLI** | Update the CLI | +| **Verify Aspire CLI installation** | Check that the CLI works | + +--- + +## Language and Debugger Support + +The extension figures out what language each resource uses and attaches the right debugger. Some languages need a companion extension: + +| Language | Debugger | Extension needed | +|----------|----------|------------------| +| C# / .NET | coreclr | [C# Dev Kit](https://marketplace.visualstudio.com/items?itemName=ms-dotnettools.csdevkit) or [C#](https://marketplace.visualstudio.com/items?itemName=ms-dotnettools.csharp) | +| Python | debugpy | [Python](https://marketplace.visualstudio.com/items?itemName=ms-python.python) | +| Node.js | js-debug (built-in) | None | +| Browser apps | js-debug (built-in) | None | +| Azure Functions | varies by language | [Azure Functions](https://marketplace.visualstudio.com/items?itemName=ms-azuretools.vscode-azurefunctions) + language extension | + +Node.js and browser debugging just work — VS Code has a built-in JavaScript debugger. C# Dev Kit gives you richer build integration than the standalone C# extension, but either one works for debugging. Azure Functions debugging supports C#, JavaScript/TypeScript, and Python. + +--- + +## Extension Settings + +You can configure the extension under **Settings → Aspire**, or jump there with **Aspire: Extension settings**. The most commonly used: + +| Setting | Default | Description | +|---------|---------|-------------| +| `aspire.aspireCliExecutablePath` | `""` | Path to the Aspire CLI. Leave empty to use `aspire` from PATH. | +| `aspire.dashboardBrowser` | `openExternalBrowser` | Which browser to open the dashboard in — system default, or Chrome/Edge/Firefox as a debug session | +| `aspire.enableAspireDashboardAutoLaunch` | `launch` | Controls what happens with the dashboard when debugging starts: `launch` (auto-open), `notification` (show link), or `off` | +| `aspire.registerMcpServerInWorkspace` | `false` | Register the Aspire MCP server (see [below](#mcp-server-integration)) | + +There are more settings for things like verbose logging, startup prompts, and polling intervals — run **Aspire: Extension settings** from the Command Palette to see them all. + +The extension also gives you IntelliSense and validation when editing `.aspire/settings.json` (workspace-level config) and `~/.aspire/globalsettings.json` (user-level config). Use the **Open local/global Aspire settings** commands to open them. + +--- + +## MCP Server Integration + +The extension can register an Aspire [MCP](https://modelcontextprotocol.io/) server with VS Code. This lets AI tools — GitHub Copilot included — see your running app's resources, endpoints, and configuration, so they have better context when helping you write code or answer questions. + +Turn it on by setting `aspire.registerMcpServerInWorkspace` to `true`. When enabled, the extension registers the MCP server definition via the Aspire CLI whenever a workspace is open and the CLI is available. + +--- ## Feedback and Issues -Please report [issues](https://github.com/dotnet/aspire/issues/new?template=10_bug_report.yml&labels=area-extension) or [feature requests](https://github.com/dotnet/aspire/issues/new?template=20_feature-request.yml&labels=area-extension) on the Aspire [GitHub repository](https://github.com/dotnet/aspire/issues) using the label `area-extension`. +Found a bug or have an idea? File it on the [dotnet/aspire](https://github.com/dotnet/aspire/issues) repo: -## Customizing debugger attributes for resources +- [Report a bug](https://github.com/dotnet/aspire/issues/new?template=10_bug_report.yml&labels=area-extension) +- [Request a feature](https://github.com/dotnet/aspire/issues/new?template=20_feature-request.yml&labels=area-extension) -| Language | Debugger entry | -|----------|-----------------| -| C# | project | -| Python | python | +### Learn more -The debuggers property stores common debug configuration properties for different types of Aspire services. -C#-based services have common debugging properties under `project`. Python-based services have their common properties under `python`. -There is also a special entry for the apphost (`apphost`). For example: +- [Aspire docs](https://aspire.dev/docs/) +- [Integration gallery](https://aspire.dev/integrations/gallery/) +- [Dashboard overview](https://aspire.dev/dashboard/overview/) +- [Discord](https://discord.com/invite/raNPcaaSj8) -```json -{ - "type": "aspire", - "request": "launch", - "name": "Aspire: Launch MyAppHost", - "program": "${workspaceFolder}/MyAppHost/MyAppHost.csproj", - "debuggers": { - "project": { - "console": "integratedTerminal", - "logging": { - "moduleLoad": false - } - }, - "apphost": { - "stopAtEntry": true - } - } -} -``` +--- ## License diff --git a/extension/loc/xlf/aspire-vscode.xlf b/extension/loc/xlf/aspire-vscode.xlf index 5ad10af80d2..298109933ac 100644 --- a/extension/loc/xlf/aspire-vscode.xlf +++ b/extension/loc/xlf/aspire-vscode.xlf @@ -52,6 +52,9 @@ Authorization header must start with 'Bearer '. + + Automatically open the dashboard in the browser. + Build failed for project {0} with error: {1}. @@ -82,6 +85,9 @@ Configure launch.json file + + Controls what happens with the Aspire Dashboard when debugging starts. + Create a new project @@ -109,6 +115,9 @@ Dismiss + + Do nothing — the dashboard URL is still printed in the terminal. + Do you want to select the default apphost for this workspace? @@ -124,9 +133,6 @@ Enable apphost discovery on extension activation and prompt to setup .aspire/settings.json.appHostPath if it does not exist in the workspace. - - Enable automatic launch of the Aspire Dashboard when using the Aspire debugger. - Enable console debug logging for Aspire CLI commands executed by the extension. @@ -197,7 +203,7 @@ Include environment variables when logging debug session configurations. This can help diagnose environment-related issues but may expose sensitive information in logs. - Initialize Aspire + Initialize Aspire in an existing codebase Install Aspire CLI (daily) @@ -338,7 +344,7 @@ Run {0} - Running apphosts + Running AppHosts Scaffold a new Aspire project from a starter template. The template includes an apphost orchestrator, a sample API, and a web frontend. [Create new project](command:aspire-vscode.new) @@ -355,6 +361,9 @@ Select the default apphost to launch when starting an Aspire debug session + + Show a notification with a link to open the dashboard. + Show global apphosts @@ -380,7 +389,7 @@ The Aspire CLI creates, runs, and manages your applications. Install it using the commands in the panel, then verify your installation. [Verify installation](command:aspire-vscode.verifyCliInstalled) - The Aspire CLI is not installed or does not support this feature. Install or update the Aspire CLI to get started. [Update Aspire CLI](command:aspire-vscode.updateSelf) [Refresh](command:aspire-vscode.refreshRunningAppHosts) + The Aspire CLI is not installed or does not support this feature. Install or update the Aspire CLI and restart VS Code to get started. [Update Aspire CLI](command:aspire-vscode.updateSelf) [Refresh](command:aspire-vscode.refreshRunningAppHosts) The Aspire Dashboard shows your resources, endpoints, logs, traces, and metrics — all in one place. [Open dashboard](command:aspire-vscode.openDashboard) @@ -388,6 +397,9 @@ The apphost is not compatible. Consider upgrading the apphost or Aspire CLI. + + The apphost process has terminated. To view console output, select the apphost session from the debug console dropdown. + The browser to use when auto-launching the Aspire Dashboard. diff --git a/extension/package.json b/extension/package.json index 0c1355e59d2..c5a37e9d557 100644 --- a/extension/package.json +++ b/extension/package.json @@ -470,9 +470,15 @@ "scope": "window" }, "aspire.enableAspireDashboardAutoLaunch": { - "type": "boolean", - "default": true, + "type": "string", + "enum": ["launch", "notification", "off"], + "default": "launch", "description": "%configuration.aspire.enableAspireDashboardAutoLaunch%", + "enumDescriptions": [ + "%configuration.aspire.enableAspireDashboardAutoLaunch.launch%", + "%configuration.aspire.enableAspireDashboardAutoLaunch.notification%", + "%configuration.aspire.enableAspireDashboardAutoLaunch.off%" + ], "scope": "window" }, "aspire.dashboardBrowser": { diff --git a/extension/package.nls.json b/extension/package.nls.json index 78cf3480450..7bb56f0f28d 100644 --- a/extension/package.nls.json +++ b/extension/package.nls.json @@ -9,7 +9,7 @@ "extension.debug.defaultConfiguration.description": "Launch the effective Aspire apphost in your workspace", "command.add": "Add an integration", "command.new": "New Aspire project", - "command.init": "Initialize Aspire", + "command.init": "Initialize Aspire in an existing codebase", "command.publish": "Publish deployment artifacts", "command.update": "Update integrations", "command.updateSelf": "Update Aspire CLI", @@ -24,7 +24,10 @@ "configuration.aspire.aspireCliExecutablePath": "The path to the Aspire CLI executable. If not set, the extension will attempt to use 'aspire' from the system PATH.", "configuration.aspire.enableAspireCliDebugLogging": "Enable console debug logging for Aspire CLI commands executed by the extension.", "configuration.aspire.enableAspireDcpDebugLogging": "Enable Developer Control Plane (DCP) debug logging for Aspire applications. Logs will be stored in the workspace's .aspire/dcp/logs-{debugSessionId} folder.", - "configuration.aspire.enableAspireDashboardAutoLaunch": "Enable automatic launch of the Aspire Dashboard when using the Aspire debugger.", + "configuration.aspire.enableAspireDashboardAutoLaunch": "Controls what happens with the Aspire Dashboard when debugging starts.", + "configuration.aspire.enableAspireDashboardAutoLaunch.launch": "Automatically open the dashboard in the browser.", + "configuration.aspire.enableAspireDashboardAutoLaunch.notification": "Show a notification with a link to open the dashboard.", + "configuration.aspire.enableAspireDashboardAutoLaunch.off": "Do nothing — the dashboard URL is still printed in the terminal.", "configuration.aspire.dashboardBrowser": "The browser to use when auto-launching the Aspire Dashboard.", "configuration.aspire.dashboardBrowser.openExternalBrowser": "Use the system default browser (cannot auto-close).", "configuration.aspire.dashboardBrowser.debugChrome": "Launch Chrome as a debug session (auto-closes when debugging ends).", @@ -76,6 +79,7 @@ "aspire-vscode.strings.csharpSupportNotEnabled": "C# support is not enabled in this workspace. This project should have started through the Aspire CLI.", "aspire-vscode.strings.failedToStartProject": "Failed to start project: {0}.", "aspire-vscode.strings.dcpServerNotInitialized": "DCP server not initialized - cannot forward debug output.", + "aspire-vscode.strings.appHostSessionTerminated": "The apphost process has terminated. To view console output, select the apphost session from the debug console dropdown.", "aspire-vscode.strings.invalidTokenProvided": "Invalid token provided.", "aspire-vscode.strings.noWorkspaceFolder": "No workspace folder found.", "aspire-vscode.strings.aspireConfigExists": "Aspire launch configuration already exists in launch.json.", @@ -112,9 +116,9 @@ "aspire-vscode.strings.selectFileTitle": "Select file", "aspire-vscode.strings.enterPipelineStep": "Enter the pipeline step to execute", "viewsContainers.aspirePanel.title": "Aspire", - "views.runningAppHosts.name": "Running apphosts", + "views.runningAppHosts.name": "Running AppHosts", "views.runningAppHosts.welcome": "No running Aspire apphost detected in this workspace.\n[Refresh](command:aspire-vscode.refreshRunningAppHosts)", - "views.runningAppHosts.errorWelcome": "The Aspire CLI is not installed or does not support this feature. Install or update the Aspire CLI to get started.\n[Update Aspire CLI](command:aspire-vscode.updateSelf)\n[Refresh](command:aspire-vscode.refreshRunningAppHosts)", + "views.runningAppHosts.errorWelcome": "The Aspire CLI is not installed or does not support this feature. Install or update the Aspire CLI and restart VS Code to get started.\n[Update Aspire CLI](command:aspire-vscode.updateSelf)\n[Refresh](command:aspire-vscode.refreshRunningAppHosts)", "command.refreshRunningAppHosts": "Refresh running apphosts", "command.openDashboard": "Open Dashboard", "command.stopAppHost": "Stop", diff --git a/extension/src/debugger/AspireDebugSession.ts b/extension/src/debugger/AspireDebugSession.ts index 989d92a3521..0086995b014 100644 --- a/extension/src/debugger/AspireDebugSession.ts +++ b/extension/src/debugger/AspireDebugSession.ts @@ -6,8 +6,10 @@ import { AspireResourceExtendedDebugConfiguration, AspireResourceDebugSession, E import { extensionLogOutputChannel } from "../utils/logging"; import AspireDcpServer, { generateDcpIdPrefix } from "../dcp/AspireDcpServer"; import { spawnCliProcess } from "./languages/cli"; -import { disconnectingFromSession, launchingWithAppHost, launchingWithDirectory, processExceptionOccurred, processExitedWithCode, aspireDashboard } from "../loc/strings"; +import { disconnectingFromSession, launchingWithAppHost, launchingWithDirectory, processExceptionOccurred, processExitedWithCode, aspireDashboard, appHostSessionTerminated } from "../loc/strings"; import { projectDebuggerExtension } from "./languages/dotnet"; +import { AnsiColors } from "../utils/AspireTerminalProvider"; +import { applyTextStyle } from "../utils/strings"; import { nodeDebuggerExtension } from "./languages/node"; import { cleanupRun } from "./runCleanupRegistry"; import AspireRpcServer from "../server/AspireRpcServer"; @@ -239,13 +241,16 @@ export class AspireDebugSession implements vscode.DebugAdapter { // When the user clicks "restart" on the app host child session, // we suppress VS Code's automatic child restart and restart the // entire Aspire debug session instead. - this.createDebugAdapterTrackerCore(debuggerExtension.debugAdapter, (debugSessionId) => { - if (debugSessionId === this.debugSessionId) { - this._appHostRestartRequested = true; - return true; // suppress VS Code's child restart + this.createDebugAdapterTrackerCore( + debuggerExtension.debugAdapter, + (debugSessionId) => { + if (debugSessionId === this.debugSessionId) { + this._appHostRestartRequested = true; + return true; // suppress VS Code's child restart + } + return false; } - return false; - }); + ); let appHostArgs: string[]; let launchConfig; @@ -290,6 +295,10 @@ export class AspireDebugSession implements vscode.DebugAdapter { const disposable = vscode.debug.onDidTerminateDebugSession(async session => { if (this._appHostDebugSession && session.id === this._appHostDebugSession.id) { + if (!this._appHostRestartRequested) { + this.sendMessageWithEmoji("ℹ️", applyTextStyle(appHostSessionTerminated, AnsiColors.Yellow)); + } + // Only restart the Aspire session when the user explicitly clicked // "restart" on the app host debug toolbar (detected via DAP tracker). // All other cases (user stop, process crash/exit) just dispose. diff --git a/extension/src/debugger/languages/dotnet.ts b/extension/src/debugger/languages/dotnet.ts index 2009733dfcb..4bcf7da8f57 100644 --- a/extension/src/debugger/languages/dotnet.ts +++ b/extension/src/debugger/languages/dotnet.ts @@ -56,60 +56,6 @@ class DotNetService implements IDotNetService { } async buildDotNetProject(projectFile: string): Promise { - const isDevKitEnabled = await this.getAndActivateDevKit(); - if (isDevKitEnabled) { - this.writeToDebugConsole(lookingForDevkitBuildTask, 'stdout', true); - - const tasks = await vscode.tasks.fetchTasks(); - const buildTask = tasks.find(t => t.source === "dotnet" && t.name?.includes('build')); - - // The build task may not be registered if there are is no solution in the workspace or if there are no C# projects - // with .csproj files. - if (buildTask) { - // Modify the task to target the specific project - const projectName = path.basename(projectFile, '.csproj'); - - // Create a modified task definition with just the project file - const modifiedDefinition = { - ...buildTask.definition, - file: projectFile // This will make it build the specific project directly - }; - - // Create a new task with the modified definition - const modifiedTask = new vscode.Task( - modifiedDefinition, - buildTask.scope || vscode.TaskScope.Workspace, - `build ${projectName}`, - buildTask.source, - buildTask.execution, - buildTask.problemMatchers - ); - - extensionLogOutputChannel.info(`Executing build task: ${modifiedTask.name} for project: ${projectFile}`); - await vscode.tasks.executeTask(modifiedTask); - - let disposable: vscode.Disposable = { dispose: () => {} }; - return new Promise((resolve, reject) => { - disposable = vscode.tasks.onDidEndTaskProcess(async e => { - if (e.execution.task === modifiedTask) { - if (e.exitCode !== 0) { - reject(new Error(buildFailedWithExitCode(e.exitCode ?? 'unknown'))); - } - else { - return resolve(); - } - } - }); - }).finally(() => disposable.dispose()); - } - else { - this.writeToDebugConsole(noCsharpBuildTask, 'stdout', true); - } - } - else { - this.writeToDebugConsole(csharpDevKitNotInstalled, 'stdout', true); - } - return new Promise((resolve, reject) => { extensionLogOutputChannel.info(`Building .NET project: ${projectFile} using dotnet CLI`); @@ -325,10 +271,9 @@ export function createProjectDebuggerExtension(dotNetServiceProducer: (debugSess const runApiOutput = await dotNetService.getDotNetRunApiOutput(projectPath); const runApiConfig = getRunApiConfigFromOutput(runApiOutput); - // Build if the executable doesn't exist or forceBuild is requested - if ((!(await doesFileExist(runApiConfig.executablePath)) || launchOptions.forceBuild)) { - await dotNetService.buildDotNetProject(projectPath); - } + // There may be an older cached version of the file-based app, so we + // should force a build. + await dotNetService.buildDotNetProject(projectPath); debugConfiguration.program = runApiConfig.executablePath; diff --git a/extension/src/loc/strings.ts b/extension/src/loc/strings.ts index 6759c733e1c..d65d03d95f7 100644 --- a/extension/src/loc/strings.ts +++ b/extension/src/loc/strings.ts @@ -9,6 +9,7 @@ export const codespacesUrl = (url: string) => vscode.l10n.t('Codespaces: {0}', u export const directLink = vscode.l10n.t('Open local URL'); export const codespacesLink = vscode.l10n.t('Open codespaces URL'); export const openAspireDashboard = vscode.l10n.t('Launch Aspire Dashboard'); +export const settingsLabel = vscode.l10n.t('Settings'); export const aspireDashboard = vscode.l10n.t('Aspire Dashboard'); export const noWorkspaceOpen = vscode.l10n.t('No workspace is open. Please open a folder or workspace before running this command.'); export const failedToShowPromptEmpty = vscode.l10n.t('Failed to show prompt, text was empty.'); @@ -42,6 +43,7 @@ export const failedToStartPythonProgram = (errorMessage: string) => vscode.l10n. export const csharpSupportNotEnabled = vscode.l10n.t('C# support is not enabled in this workspace. This project should have started through the Aspire CLI.'); export const failedToStartProject = (errorMessage: string) => vscode.l10n.t('Failed to start project: {0}.', errorMessage); export const dcpServerNotInitialized = vscode.l10n.t('DCP server not initialized - cannot forward debug output.'); +export const appHostSessionTerminated = vscode.l10n.t('The apphost process has terminated. To view console output, select the apphost session from the debug console dropdown.'); export const invalidTokenProvided = vscode.l10n.t('Invalid token provided.'); export const noWorkspaceFolder = vscode.l10n.t('No workspace folder found.'); export const aspireConfigExists = vscode.l10n.t('Aspire launch configuration already exists in launch.json.'); diff --git a/extension/src/server/interactionService.ts b/extension/src/server/interactionService.ts index a546a1401b6..7cdbd04e08a 100644 --- a/extension/src/server/interactionService.ts +++ b/extension/src/server/interactionService.ts @@ -2,7 +2,7 @@ import { MessageConnection } from 'vscode-jsonrpc'; import * as vscode from 'vscode'; import * as fs from 'fs/promises'; import { getRelativePathToWorkspace, isFolderOpenInWorkspace } from '../utils/workspace'; -import { yesLabel, noLabel, directLink, codespacesLink, openAspireDashboard, failedToShowPromptEmpty, incompatibleAppHostError, aspireHostingSdkVersion, aspireCliVersion, requiredCapability, fieldRequired, aspireDebugSessionNotInitialized, errorMessage, failedToStartDebugSession, dashboard, codespaces, selectDirectoryTitle, selectFileTitle } from '../loc/strings'; +import { yesLabel, noLabel, directLink, codespacesLink, openAspireDashboard, settingsLabel, failedToShowPromptEmpty, incompatibleAppHostError, aspireHostingSdkVersion, aspireCliVersion, requiredCapability, fieldRequired, aspireDebugSessionNotInitialized, errorMessage, failedToStartDebugSession, dashboard, codespaces, selectDirectoryTitle, selectFileTitle } from '../loc/strings'; import { ICliRpcClient } from './rpcClient'; import { ProgressNotifier } from './progressNotifier'; import { applyTextStyle, formatText } from '../utils/strings'; @@ -334,11 +334,27 @@ export class InteractionService implements IInteractionService { this.writeDebugSessionMessage(codespacesUrl, true, AnsiColors.Blue); } - // If aspire.enableAspireDashboardAutoLaunch is true, the dashboard will be launched automatically and we do not need - // to show an information message. + // Refresh the Aspire panel so it picks up dashboard URLs for the running app host + vscode.commands.executeCommand('aspire-vscode.refreshRunningAppHosts'); + + // If aspire.enableAspireDashboardAutoLaunch is 'launch', the dashboard will be launched automatically. + // If 'notification', a notification is shown with a link. If 'off', do nothing. const aspireConfig = vscode.workspace.getConfiguration('aspire'); - const enableDashboardAutoLaunch = aspireConfig.get('enableAspireDashboardAutoLaunch', true); - if (enableDashboardAutoLaunch) { + const rawDashboardAutoLaunch = aspireConfig.get('enableAspireDashboardAutoLaunch', 'launch'); + + // Handle legacy boolean values from before this setting was changed to an enum + let dashboardAutoLaunch: 'launch' | 'notification' | 'off'; + if (rawDashboardAutoLaunch === true) { + dashboardAutoLaunch = 'launch'; + } else if (rawDashboardAutoLaunch === false) { + dashboardAutoLaunch = 'notification'; + } else if (rawDashboardAutoLaunch === 'launch' || rawDashboardAutoLaunch === 'notification' || rawDashboardAutoLaunch === 'off') { + dashboardAutoLaunch = rawDashboardAutoLaunch; + } else { + dashboardAutoLaunch = 'launch'; + } + + if (dashboardAutoLaunch === 'launch') { // Open the dashboard URL in the configured browser. Prefer codespaces URL if available. const urlToOpen = codespacesUrl || baseUrl; const debugSession = this._getAspireDebugSession(); @@ -349,6 +365,10 @@ export class InteractionService implements IInteractionService { return; } + if (dashboardAutoLaunch === 'off') { + return; + } + const actions: vscode.MessageItem[] = [ { title: directLink } ]; @@ -357,6 +377,8 @@ export class InteractionService implements IInteractionService { actions.push({ title: codespacesLink }); } + actions.push({ title: settingsLabel }); + // Delay 1 second to allow a slight pause between progress notification and message setTimeout(() => { // Don't await - fire and forget to avoid blocking @@ -376,6 +398,9 @@ export class InteractionService implements IInteractionService { else if (selected.title === codespacesLink && codespacesUrl) { vscode.env.openExternal(vscode.Uri.parse(codespacesUrl)); } + else if (selected.title === settingsLabel) { + vscode.commands.executeCommand('workbench.action.openSettings', 'aspire.enableAspireDashboardAutoLaunch'); + } }); }, 1000); } diff --git a/extension/src/test/appHostTreeView.test.ts b/extension/src/test/appHostTreeView.test.ts index 2fa15746210..43aad8b5ae0 100644 --- a/extension/src/test/appHostTreeView.test.ts +++ b/extension/src/test/appHostTreeView.test.ts @@ -4,7 +4,7 @@ import { getResourceContextValue, getResourceIcon } from '../views/AspireAppHost import type { ResourceJson } from '../views/AppHostDataRepository'; function makeResource(overrides: Partial = {}): ResourceJson { - return { + const base: ResourceJson = { name: 'my-service', displayName: null, resourceType: 'Project', @@ -14,8 +14,9 @@ function makeResource(overrides: Partial = {}): ResourceJson { dashboardUrl: null, urls: null, commands: null, - ...overrides, + properties: null, }; + return { ...base, ...overrides } as ResourceJson; } suite('shortenPath', () => { @@ -97,6 +98,7 @@ suite('getResourceContextValue', () => { })); assert.strictEqual(result, 'resource:canRestart'); }); + }); suite('getResourceIcon', () => { diff --git a/extension/src/test/rpc/interactionServiceTests.test.ts b/extension/src/test/rpc/interactionServiceTests.test.ts index f2b073aa7c9..e8de2f7b703 100644 --- a/extension/src/test/rpc/interactionServiceTests.test.ts +++ b/extension/src/test/rpc/interactionServiceTests.test.ts @@ -189,11 +189,11 @@ suite('InteractionService endpoints', () => { stub.restore(); }); - test("displayDashboardUrls writes URLs to output channel and shows info message when autoLaunch disabled", async () => { + test("displayDashboardUrls writes URLs to output channel and shows info message when autoLaunch is notification", async () => { const stub = sinon.stub(extensionLogOutputChannel, 'info'); const showInformationMessageStub = sinon.stub(vscode.window, 'showInformationMessage').resolves(); const getConfigurationStub = sinon.stub(vscode.workspace, 'getConfiguration').returns({ - get: (key: string, defaultValue?: any) => key === 'enableAspireDashboardAutoLaunch' ? false : defaultValue + get: (key: string, defaultValue?: any) => key === 'enableAspireDashboardAutoLaunch' ? 'notification' : defaultValue } as any); const testInfo = await createTestRpcServer(); @@ -212,17 +212,17 @@ suite('InteractionService endpoints', () => { assert.ok(outputLines.some(line => line.includes(baseUrl)), 'Output should contain base URL'); assert.ok(outputLines.some(line => line.includes(codespacesUrl)), 'Output should contain codespaces URL'); - assert.equal(showInformationMessageStub.callCount, 1, 'Should show info message when autoLaunch is disabled'); + assert.equal(showInformationMessageStub.callCount, 1, 'Should show info message when autoLaunch is notification'); stub.restore(); showInformationMessageStub.restore(); getConfigurationStub.restore(); }); - test("displayDashboardUrls writes URLs but does not show info message when autoLaunch enabled", async () => { + test("displayDashboardUrls writes URLs but does not show info message when autoLaunch is launch", async () => { const stub = sinon.stub(extensionLogOutputChannel, 'info'); const showInformationMessageStub = sinon.stub(vscode.window, 'showInformationMessage').resolves(); const getConfigurationStub = sinon.stub(vscode.workspace, 'getConfiguration').returns({ - get: (key: string, defaultValue?: any) => key === 'enableAspireDashboardAutoLaunch' ? true : defaultValue + get: (key: string, defaultValue?: any) => key === 'enableAspireDashboardAutoLaunch' ? 'launch' : defaultValue } as any); const testInfo = await createTestRpcServer(); @@ -239,7 +239,7 @@ suite('InteractionService endpoints', () => { // No need to wait since no setTimeout should be called when autoLaunch is enabled assert.ok(outputLines.some(line => line.includes(baseUrl)), 'Output should contain base URL'); assert.ok(outputLines.some(line => line.includes(codespacesUrl)), 'Output should contain codespaces URL'); - assert.equal(showInformationMessageStub.callCount, 0, 'Should not show info message when autoLaunch is enabled'); + assert.equal(showInformationMessageStub.callCount, 0, 'Should not show info message when autoLaunch is launch'); stub.restore(); showInformationMessageStub.restore(); getConfigurationStub.restore(); diff --git a/extension/src/utils/AspireTerminalProvider.ts b/extension/src/utils/AspireTerminalProvider.ts index edd482ca16e..e91ce4a2c04 100644 --- a/extension/src/utils/AspireTerminalProvider.ts +++ b/extension/src/utils/AspireTerminalProvider.ts @@ -10,6 +10,7 @@ import path from 'path'; export const enum AnsiColors { Green = '\x1b[32m', + Yellow = '\x1b[33m', Blue = '\x1b[34m', } diff --git a/extension/src/views/AppHostDataRepository.ts b/extension/src/views/AppHostDataRepository.ts index 97098feb359..4bc63101fdf 100644 --- a/extension/src/views/AppHostDataRepository.ts +++ b/extension/src/views/AppHostDataRepository.ts @@ -27,6 +27,7 @@ export interface ResourceJson { dashboardUrl: string | null; urls: ResourceUrlJson[] | null; commands: Record | null; + properties: Record | null; } export interface AppHostDisplayInfo { @@ -64,7 +65,7 @@ export class AppHostDataRepository { private _describeRestarting = false; private _describeRestartDelay = 5000; private _describeRestartTimer: ReturnType | undefined; - private static readonly _maxDescribeRestartDelay = 60000; + private _describeReceivedData = false; // ── Global mode state (ps polling) ── private _appHosts: AppHostDisplayInfo[] = []; @@ -145,6 +146,7 @@ export class AppHostDataRepository { refresh(): void { this._stopDescribeWatch(); this._workspaceResources.clear(); + this._setError(undefined); this._updateWorkspaceContext(); this._describeRestartDelay = 5000; this._startDescribeWatch(); @@ -257,6 +259,7 @@ export class AppHostDataRepository { extensionLogOutputChannel.info('Starting aspire describe --follow for workspace resources'); + this._describeReceivedData = false; this._describeProcess = spawnCliProcess(this._terminalProvider, cliPath, args, { noExtensionVariables: true, lineCallback: (line) => { @@ -267,20 +270,29 @@ export class AppHostDataRepository { this._describeProcess = undefined; if (!this._disposed && !this._describeRestarting) { - this._workspaceResources.clear(); - this._setError(undefined); - this._updateWorkspaceContext(); - - // Auto-restart with exponential backoff - const delay = this._describeRestartDelay; - this._describeRestartDelay = Math.min(this._describeRestartDelay * 2, AppHostDataRepository._maxDescribeRestartDelay); - extensionLogOutputChannel.info(`Restarting describe --follow in ${delay}ms`); - this._describeRestartTimer = setTimeout(() => { - this._describeRestartTimer = undefined; - if (!this._disposed) { - this._startDescribeWatch(); - } - }, delay); + if (!this._describeReceivedData && code !== 0) { + // The process exited with a non-zero code without ever producing valid data. + // This likely means the CLI does not support the describe command. + extensionLogOutputChannel.warn('aspire describe --follow exited without producing data; the installed Aspire CLI may not support this feature.'); + this._workspaceResources.clear(); + this._setError(errorFetchingAppHosts(`exit code ${code}`)); + this._updateWorkspaceContext(); + } else { + this._workspaceResources.clear(); + this._setError(undefined); + this._updateWorkspaceContext(); + + // Auto-restart with exponential backoff + const delay = this._describeRestartDelay; + this._describeRestartDelay = Math.min(this._describeRestartDelay * 2, this._getPollingIntervalMs()); + extensionLogOutputChannel.info(`Restarting describe --follow in ${delay}ms`); + this._describeRestartTimer = setTimeout(() => { + this._describeRestartTimer = undefined; + if (!this._disposed) { + this._startDescribeWatch(); + } + }, delay); + } } this._describeRestarting = false; }, @@ -320,6 +332,7 @@ export class AppHostDataRepository { const resource: ResourceJson = JSON.parse(trimmed); if (resource.name) { this._workspaceResources.set(resource.name, resource); + this._describeReceivedData = true; this._setError(undefined); this._describeRestartDelay = 5000; // Reset backoff on successful data this._updateWorkspaceContext(); diff --git a/extension/src/views/AspireAppHostTreeProvider.ts b/extension/src/views/AspireAppHostTreeProvider.ts index bc80b18ff78..b98fc02ef5d 100644 --- a/extension/src/views/AspireAppHostTreeProvider.ts +++ b/extension/src/views/AspireAppHostTreeProvider.ts @@ -25,6 +25,14 @@ import { type TreeElement = AppHostItem | DetailItem | ResourcesGroupItem | ResourceItem | WorkspaceResourcesItem; +function sortResources(resources: ResourceJson[]): ResourceJson[] { + return [...resources].sort((a, b) => { + const nameA = (a.displayName ?? a.name).toLowerCase(); + const nameB = (b.displayName ?? b.name).toLowerCase(); + return nameA.localeCompare(nameB); + }); +} + function appHostIcon(path?: string): vscode.ThemeIcon { const icon = path?.endsWith('.csproj') ? 'server-process' : 'file-code'; return new vscode.ThemeIcon(icon, new vscode.ThemeColor('aspire.brandPurple')); @@ -71,12 +79,19 @@ class ResourcesGroupItem extends vscode.TreeItem { } } +function getParentResourceName(resource: ResourceJson): string | null { + return resource.properties?.['resource.parentName'] ?? null; +} + class ResourceItem extends vscode.TreeItem { - constructor(public readonly resource: ResourceJson, public readonly appHostPid: number | null) { + constructor(public readonly resource: ResourceJson, public readonly appHostPid: number | null, hasChildren: boolean) { const state = resource.state ?? ''; const label = state ? resourceStateLabel(resource.displayName ?? resource.name, state) : (resource.displayName ?? resource.name); const hasUrls = resource.urls && resource.urls.filter(u => !u.isInternal).length > 0; - super(label, hasUrls ? vscode.TreeItemCollapsibleState.Collapsed : vscode.TreeItemCollapsibleState.None); + const collapsible = hasChildren + ? vscode.TreeItemCollapsibleState.Expanded + : hasUrls ? vscode.TreeItemCollapsibleState.Collapsed : vscode.TreeItemCollapsibleState.None; + super(label, collapsible); this.id = appHostPid !== null ? `resource:${appHostPid}:${resource.name}` : `resource:workspace:${resource.name}`; this.iconPath = getResourceIcon(resource); this.description = resource.resourceType; @@ -220,14 +235,17 @@ export class AspireAppHostTreeProvider implements vscode.TreeDataProvider !getParentResourceName(r)); + for (const resource of sortResources(topLevel)) { + const hasChildren = element.resources.some(r => getParentResourceName(r) === resource.name); + items.push(new ResourceItem(resource, null, hasChildren)); } return items; } if (element instanceof ResourceItem) { - return this._getUrlChildren(element); + return this._getResourceChildren(element, [...this._repository.workspaceResources]); } return []; @@ -277,16 +295,39 @@ export class AspireAppHostTreeProvider implements vscode.TreeDataProvider new ResourceItem(r, element.appHostPid)); + const topLevel = element.resources.filter(r => !getParentResourceName(r)); + return sortResources(topLevel).map(r => { + const hasChildren = element.resources.some(c => getParentResourceName(c) === r.name); + return new ResourceItem(r, element.appHostPid, hasChildren); + }); } if (element instanceof ResourceItem) { - return this._getUrlChildren(element); + const allResources = this._repository.viewMode === 'workspace' + ? [...this._repository.workspaceResources] + : this._repository.appHosts.find(a => a.appHostPid === element.appHostPid)?.resources ?? []; + return this._getResourceChildren(element, allResources); } return []; } + private _getResourceChildren(element: ResourceItem, allResources: readonly ResourceJson[]): TreeElement[] { + const items: TreeElement[] = []; + + // Add child resources + const children = allResources.filter(r => getParentResourceName(r) === element.resource.name); + for (const child of sortResources(children)) { + const hasChildren = allResources.some(r => getParentResourceName(r) === child.name); + items.push(new ResourceItem(child, element.appHostPid, hasChildren)); + } + + // Add URL children + items.push(...this._getUrlChildren(element)); + + return items; + } + private _getUrlChildren(element: ResourceItem): TreeElement[] { const urls = element.resource.urls?.filter(u => !u.isInternal) ?? []; return urls.map(url => new DetailItem( diff --git a/playground/AzureFunctionsEndToEnd/AzureFunctionsEndToEnd.AppHost/Program.cs b/playground/AzureFunctionsEndToEnd/AzureFunctionsEndToEnd.AppHost/AppHost.cs similarity index 100% rename from playground/AzureFunctionsEndToEnd/AzureFunctionsEndToEnd.AppHost/Program.cs rename to playground/AzureFunctionsEndToEnd/AzureFunctionsEndToEnd.AppHost/AppHost.cs diff --git a/playground/TypeScriptAppHost/.modules/aspire.ts b/playground/TypeScriptAppHost/.modules/aspire.ts index 8ade3448ce5..2a1032125cf 100644 --- a/playground/TypeScriptAppHost/.modules/aspire.ts +++ b/playground/TypeScriptAppHost/.modules/aspire.ts @@ -8,6 +8,7 @@ import { AspireClient as AspireClientRpc, Handle, MarshalledHandle, + AppHostUsageError, CapabilityError, registerCallback, wrapIfHandle, @@ -239,6 +240,7 @@ export enum EndpointProperty { Scheme = "Scheme", TargetPort = "TargetPort", HostAndPort = "HostAndPort", + TlsEnabled = "TlsEnabled", } /** Enum type for IconVariant */ @@ -876,6 +878,16 @@ export class EndpointReference { }, }; + /** Gets the TlsEnabled property */ + tlsEnabled = { + get: async (): Promise => { + return await this._client.invokeCapability( + 'Aspire.Hosting.ApplicationModel/EndpointReference.tlsEnabled', + { context: this._handle } + ); + }, + }; + /** Gets the Port property */ port = { get: async (): Promise => { @@ -937,6 +949,15 @@ export class EndpointReference { ); } + /** Gets a conditional expression that resolves to the enabledValue when TLS is enabled on the endpoint, or to the disabledValue otherwise. */ + async getTlsValue(enabledValue: ReferenceExpression, disabledValue: ReferenceExpression): Promise { + const rpcArgs: Record = { context: this._handle, enabledValue, disabledValue }; + return await this._client.invokeCapability( + 'Aspire.Hosting.ApplicationModel/EndpointReference.getTlsValue', + rpcArgs + ); + } + } /** @@ -957,6 +978,11 @@ export class EndpointReferencePromise implements PromiseLike return this._promise.then(obj => obj.getValueAsync(options)); } + /** Gets a conditional expression that resolves to the enabledValue when TLS is enabled on the endpoint, or to the disabledValue otherwise. */ + getTlsValue(enabledValue: ReferenceExpression, disabledValue: ReferenceExpression): Promise { + return this._promise.then(obj => obj.getTlsValue(enabledValue, disabledValue)); + } + } // ============================================================================ @@ -3202,36 +3228,6 @@ export class ConnectionStringResource extends ResourceBuilderBase { - const rpcArgs: Record = { builder: this._handle, remoteImageName }; - const result = await this._client.invokeCapability( - 'Aspire.Hosting/withRemoteImageName', - rpcArgs - ); - return new ConnectionStringResource(result, this._client); - } - - /** Sets the remote image name for publishing */ - withRemoteImageName(remoteImageName: string): ConnectionStringResourcePromise { - return new ConnectionStringResourcePromise(this._withRemoteImageNameInternal(remoteImageName)); - } - - /** @internal */ - private async _withRemoteImageTagInternal(remoteImageTag: string): Promise { - const rpcArgs: Record = { builder: this._handle, remoteImageTag }; - const result = await this._client.invokeCapability( - 'Aspire.Hosting/withRemoteImageTag', - rpcArgs - ); - return new ConnectionStringResource(result, this._client); - } - - /** Sets the remote image tag for publishing */ - withRemoteImageTag(remoteImageTag: string): ConnectionStringResourcePromise { - return new ConnectionStringResourcePromise(this._withRemoteImageTagInternal(remoteImageTag)); - } - /** @internal */ private async _withPipelineStepFactoryInternal(stepName: string, callback: (arg: PipelineStepContext) => Promise, dependsOn?: string[], requiredBy?: string[], tags?: string[], description?: string): Promise { const callbackId = registerCallback(async (argData: unknown) => { @@ -3441,16 +3437,6 @@ export class ConnectionStringResourcePromise implements PromiseLike obj.excludeFromMcp())); } - /** Sets the remote image name for publishing */ - withRemoteImageName(remoteImageName: string): ConnectionStringResourcePromise { - return new ConnectionStringResourcePromise(this._promise.then(obj => obj.withRemoteImageName(remoteImageName))); - } - - /** Sets the remote image tag for publishing */ - withRemoteImageTag(remoteImageTag: string): ConnectionStringResourcePromise { - return new ConnectionStringResourcePromise(this._promise.then(obj => obj.withRemoteImageTag(remoteImageTag))); - } - /** Adds a pipeline step to the resource */ withPipelineStepFactory(stepName: string, callback: (arg: PipelineStepContext) => Promise, options?: WithPipelineStepFactoryOptions): ConnectionStringResourcePromise { return new ConnectionStringResourcePromise(this._promise.then(obj => obj.withPipelineStepFactory(stepName, callback, options))); @@ -3755,36 +3741,6 @@ export class ContainerRegistryResource extends ResourceBuilderBase { - const rpcArgs: Record = { builder: this._handle, remoteImageName }; - const result = await this._client.invokeCapability( - 'Aspire.Hosting/withRemoteImageName', - rpcArgs - ); - return new ContainerRegistryResource(result, this._client); - } - - /** Sets the remote image name for publishing */ - withRemoteImageName(remoteImageName: string): ContainerRegistryResourcePromise { - return new ContainerRegistryResourcePromise(this._withRemoteImageNameInternal(remoteImageName)); - } - - /** @internal */ - private async _withRemoteImageTagInternal(remoteImageTag: string): Promise { - const rpcArgs: Record = { builder: this._handle, remoteImageTag }; - const result = await this._client.invokeCapability( - 'Aspire.Hosting/withRemoteImageTag', - rpcArgs - ); - return new ContainerRegistryResource(result, this._client); - } - - /** Sets the remote image tag for publishing */ - withRemoteImageTag(remoteImageTag: string): ContainerRegistryResourcePromise { - return new ContainerRegistryResourcePromise(this._withRemoteImageTagInternal(remoteImageTag)); - } - /** @internal */ private async _withPipelineStepFactoryInternal(stepName: string, callback: (arg: PipelineStepContext) => Promise, dependsOn?: string[], requiredBy?: string[], tags?: string[], description?: string): Promise { const callbackId = registerCallback(async (argData: unknown) => { @@ -3959,16 +3915,6 @@ export class ContainerRegistryResourcePromise implements PromiseLike obj.excludeFromMcp())); } - /** Sets the remote image name for publishing */ - withRemoteImageName(remoteImageName: string): ContainerRegistryResourcePromise { - return new ContainerRegistryResourcePromise(this._promise.then(obj => obj.withRemoteImageName(remoteImageName))); - } - - /** Sets the remote image tag for publishing */ - withRemoteImageTag(remoteImageTag: string): ContainerRegistryResourcePromise { - return new ContainerRegistryResourcePromise(this._promise.then(obj => obj.withRemoteImageTag(remoteImageTag))); - } - /** Adds a pipeline step to the resource */ withPipelineStepFactory(stepName: string, callback: (arg: PipelineStepContext) => Promise, options?: WithPipelineStepFactoryOptions): ContainerRegistryResourcePromise { return new ContainerRegistryResourcePromise(this._promise.then(obj => obj.withPipelineStepFactory(stepName, callback, options))); @@ -8974,36 +8920,6 @@ export class DockerComposeEnvironmentResource extends ResourceBuilderBase { - const rpcArgs: Record = { builder: this._handle, remoteImageName }; - const result = await this._client.invokeCapability( - 'Aspire.Hosting/withRemoteImageName', - rpcArgs - ); - return new DockerComposeEnvironmentResource(result, this._client); - } - - /** Sets the remote image name for publishing */ - withRemoteImageName(remoteImageName: string): DockerComposeEnvironmentResourcePromise { - return new DockerComposeEnvironmentResourcePromise(this._withRemoteImageNameInternal(remoteImageName)); - } - - /** @internal */ - private async _withRemoteImageTagInternal(remoteImageTag: string): Promise { - const rpcArgs: Record = { builder: this._handle, remoteImageTag }; - const result = await this._client.invokeCapability( - 'Aspire.Hosting/withRemoteImageTag', - rpcArgs - ); - return new DockerComposeEnvironmentResource(result, this._client); - } - - /** Sets the remote image tag for publishing */ - withRemoteImageTag(remoteImageTag: string): DockerComposeEnvironmentResourcePromise { - return new DockerComposeEnvironmentResourcePromise(this._withRemoteImageTagInternal(remoteImageTag)); - } - /** @internal */ private async _withPipelineStepFactoryInternal(stepName: string, callback: (arg: PipelineStepContext) => Promise, dependsOn?: string[], requiredBy?: string[], tags?: string[], description?: string): Promise { const callbackId = registerCallback(async (argData: unknown) => { @@ -9235,16 +9151,6 @@ export class DockerComposeEnvironmentResourcePromise implements PromiseLike obj.excludeFromMcp())); } - /** Sets the remote image name for publishing */ - withRemoteImageName(remoteImageName: string): DockerComposeEnvironmentResourcePromise { - return new DockerComposeEnvironmentResourcePromise(this._promise.then(obj => obj.withRemoteImageName(remoteImageName))); - } - - /** Sets the remote image tag for publishing */ - withRemoteImageTag(remoteImageTag: string): DockerComposeEnvironmentResourcePromise { - return new DockerComposeEnvironmentResourcePromise(this._promise.then(obj => obj.withRemoteImageTag(remoteImageTag))); - } - /** Adds a pipeline step to the resource */ withPipelineStepFactory(stepName: string, callback: (arg: PipelineStepContext) => Promise, options?: WithPipelineStepFactoryOptions): DockerComposeEnvironmentResourcePromise { return new DockerComposeEnvironmentResourcePromise(this._promise.then(obj => obj.withPipelineStepFactory(stepName, callback, options))); @@ -9585,36 +9491,6 @@ export class DockerComposeServiceResource extends ResourceBuilderBase { - const rpcArgs: Record = { builder: this._handle, remoteImageName }; - const result = await this._client.invokeCapability( - 'Aspire.Hosting/withRemoteImageName', - rpcArgs - ); - return new DockerComposeServiceResource(result, this._client); - } - - /** Sets the remote image name for publishing */ - withRemoteImageName(remoteImageName: string): DockerComposeServiceResourcePromise { - return new DockerComposeServiceResourcePromise(this._withRemoteImageNameInternal(remoteImageName)); - } - - /** @internal */ - private async _withRemoteImageTagInternal(remoteImageTag: string): Promise { - const rpcArgs: Record = { builder: this._handle, remoteImageTag }; - const result = await this._client.invokeCapability( - 'Aspire.Hosting/withRemoteImageTag', - rpcArgs - ); - return new DockerComposeServiceResource(result, this._client); - } - - /** Sets the remote image tag for publishing */ - withRemoteImageTag(remoteImageTag: string): DockerComposeServiceResourcePromise { - return new DockerComposeServiceResourcePromise(this._withRemoteImageTagInternal(remoteImageTag)); - } - /** @internal */ private async _withPipelineStepFactoryInternal(stepName: string, callback: (arg: PipelineStepContext) => Promise, dependsOn?: string[], requiredBy?: string[], tags?: string[], description?: string): Promise { const callbackId = registerCallback(async (argData: unknown) => { @@ -9789,16 +9665,6 @@ export class DockerComposeServiceResourcePromise implements PromiseLike obj.excludeFromMcp())); } - /** Sets the remote image name for publishing */ - withRemoteImageName(remoteImageName: string): DockerComposeServiceResourcePromise { - return new DockerComposeServiceResourcePromise(this._promise.then(obj => obj.withRemoteImageName(remoteImageName))); - } - - /** Sets the remote image tag for publishing */ - withRemoteImageTag(remoteImageTag: string): DockerComposeServiceResourcePromise { - return new DockerComposeServiceResourcePromise(this._promise.then(obj => obj.withRemoteImageTag(remoteImageTag))); - } - /** Adds a pipeline step to the resource */ withPipelineStepFactory(stepName: string, callback: (arg: PipelineStepContext) => Promise, options?: WithPipelineStepFactoryOptions): DockerComposeServiceResourcePromise { return new DockerComposeServiceResourcePromise(this._promise.then(obj => obj.withPipelineStepFactory(stepName, callback, options))); @@ -13073,36 +12939,6 @@ export class ExternalServiceResource extends ResourceBuilderBase { - const rpcArgs: Record = { builder: this._handle, remoteImageName }; - const result = await this._client.invokeCapability( - 'Aspire.Hosting/withRemoteImageName', - rpcArgs - ); - return new ExternalServiceResource(result, this._client); - } - - /** Sets the remote image name for publishing */ - withRemoteImageName(remoteImageName: string): ExternalServiceResourcePromise { - return new ExternalServiceResourcePromise(this._withRemoteImageNameInternal(remoteImageName)); - } - - /** @internal */ - private async _withRemoteImageTagInternal(remoteImageTag: string): Promise { - const rpcArgs: Record = { builder: this._handle, remoteImageTag }; - const result = await this._client.invokeCapability( - 'Aspire.Hosting/withRemoteImageTag', - rpcArgs - ); - return new ExternalServiceResource(result, this._client); - } - - /** Sets the remote image tag for publishing */ - withRemoteImageTag(remoteImageTag: string): ExternalServiceResourcePromise { - return new ExternalServiceResourcePromise(this._withRemoteImageTagInternal(remoteImageTag)); - } - /** @internal */ private async _withPipelineStepFactoryInternal(stepName: string, callback: (arg: PipelineStepContext) => Promise, dependsOn?: string[], requiredBy?: string[], tags?: string[], description?: string): Promise { const callbackId = registerCallback(async (argData: unknown) => { @@ -13282,16 +13118,6 @@ export class ExternalServiceResourcePromise implements PromiseLike obj.excludeFromMcp())); } - /** Sets the remote image name for publishing */ - withRemoteImageName(remoteImageName: string): ExternalServiceResourcePromise { - return new ExternalServiceResourcePromise(this._promise.then(obj => obj.withRemoteImageName(remoteImageName))); - } - - /** Sets the remote image tag for publishing */ - withRemoteImageTag(remoteImageTag: string): ExternalServiceResourcePromise { - return new ExternalServiceResourcePromise(this._promise.then(obj => obj.withRemoteImageTag(remoteImageTag))); - } - /** Adds a pipeline step to the resource */ withPipelineStepFactory(stepName: string, callback: (arg: PipelineStepContext) => Promise, options?: WithPipelineStepFactoryOptions): ExternalServiceResourcePromise { return new ExternalServiceResourcePromise(this._promise.then(obj => obj.withPipelineStepFactory(stepName, callback, options))); @@ -16823,36 +16649,6 @@ export class ParameterResource extends ResourceBuilderBase { - const rpcArgs: Record = { builder: this._handle, remoteImageName }; - const result = await this._client.invokeCapability( - 'Aspire.Hosting/withRemoteImageName', - rpcArgs - ); - return new ParameterResource(result, this._client); - } - - /** Sets the remote image name for publishing */ - withRemoteImageName(remoteImageName: string): ParameterResourcePromise { - return new ParameterResourcePromise(this._withRemoteImageNameInternal(remoteImageName)); - } - - /** @internal */ - private async _withRemoteImageTagInternal(remoteImageTag: string): Promise { - const rpcArgs: Record = { builder: this._handle, remoteImageTag }; - const result = await this._client.invokeCapability( - 'Aspire.Hosting/withRemoteImageTag', - rpcArgs - ); - return new ParameterResource(result, this._client); - } - - /** Sets the remote image tag for publishing */ - withRemoteImageTag(remoteImageTag: string): ParameterResourcePromise { - return new ParameterResourcePromise(this._withRemoteImageTagInternal(remoteImageTag)); - } - /** @internal */ private async _withPipelineStepFactoryInternal(stepName: string, callback: (arg: PipelineStepContext) => Promise, dependsOn?: string[], requiredBy?: string[], tags?: string[], description?: string): Promise { const callbackId = registerCallback(async (argData: unknown) => { @@ -17032,16 +16828,6 @@ export class ParameterResourcePromise implements PromiseLike return new ParameterResourcePromise(this._promise.then(obj => obj.excludeFromMcp())); } - /** Sets the remote image name for publishing */ - withRemoteImageName(remoteImageName: string): ParameterResourcePromise { - return new ParameterResourcePromise(this._promise.then(obj => obj.withRemoteImageName(remoteImageName))); - } - - /** Sets the remote image tag for publishing */ - withRemoteImageTag(remoteImageTag: string): ParameterResourcePromise { - return new ParameterResourcePromise(this._promise.then(obj => obj.withRemoteImageTag(remoteImageTag))); - } - /** Adds a pipeline step to the resource */ withPipelineStepFactory(stepName: string, callback: (arg: PipelineStepContext) => Promise, options?: WithPipelineStepFactoryOptions): ParameterResourcePromise { return new ParameterResourcePromise(this._promise.then(obj => obj.withPipelineStepFactory(stepName, callback, options))); @@ -20971,36 +20757,6 @@ export class PostgresDatabaseResource extends ResourceBuilderBase { - const rpcArgs: Record = { builder: this._handle, remoteImageName }; - const result = await this._client.invokeCapability( - 'Aspire.Hosting/withRemoteImageName', - rpcArgs - ); - return new PostgresDatabaseResource(result, this._client); - } - - /** Sets the remote image name for publishing */ - withRemoteImageName(remoteImageName: string): PostgresDatabaseResourcePromise { - return new PostgresDatabaseResourcePromise(this._withRemoteImageNameInternal(remoteImageName)); - } - - /** @internal */ - private async _withRemoteImageTagInternal(remoteImageTag: string): Promise { - const rpcArgs: Record = { builder: this._handle, remoteImageTag }; - const result = await this._client.invokeCapability( - 'Aspire.Hosting/withRemoteImageTag', - rpcArgs - ); - return new PostgresDatabaseResource(result, this._client); - } - - /** Sets the remote image tag for publishing */ - withRemoteImageTag(remoteImageTag: string): PostgresDatabaseResourcePromise { - return new PostgresDatabaseResourcePromise(this._withRemoteImageTagInternal(remoteImageTag)); - } - /** @internal */ private async _withPipelineStepFactoryInternal(stepName: string, callback: (arg: PipelineStepContext) => Promise, dependsOn?: string[], requiredBy?: string[], tags?: string[], description?: string): Promise { const callbackId = registerCallback(async (argData: unknown) => { @@ -21224,16 +20980,6 @@ export class PostgresDatabaseResourcePromise implements PromiseLike obj.excludeFromMcp())); } - /** Sets the remote image name for publishing */ - withRemoteImageName(remoteImageName: string): PostgresDatabaseResourcePromise { - return new PostgresDatabaseResourcePromise(this._promise.then(obj => obj.withRemoteImageName(remoteImageName))); - } - - /** Sets the remote image tag for publishing */ - withRemoteImageTag(remoteImageTag: string): PostgresDatabaseResourcePromise { - return new PostgresDatabaseResourcePromise(this._promise.then(obj => obj.withRemoteImageTag(remoteImageTag))); - } - /** Adds a pipeline step to the resource */ withPipelineStepFactory(stepName: string, callback: (arg: PipelineStepContext) => Promise, options?: WithPipelineStepFactoryOptions): PostgresDatabaseResourcePromise { return new PostgresDatabaseResourcePromise(this._promise.then(obj => obj.withPipelineStepFactory(stepName, callback, options))); @@ -30152,12 +29898,6 @@ export class RedisResource extends ResourceBuilderBase { { context: this._handle } ); }, - set: async (value: boolean): Promise => { - await this._client.invokeCapability( - 'Aspire.Hosting.ApplicationModel/RedisResource.setTlsEnabled', - { context: this._handle, value } - ); - } }; /** Gets the ConnectionStringExpression property */ @@ -33889,6 +33629,36 @@ export class ComputeResource extends ResourceBuilderBase super(handle, client); } + /** @internal */ + private async _withRemoteImageNameInternal(remoteImageName: string): Promise { + const rpcArgs: Record = { builder: this._handle, remoteImageName }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withRemoteImageName', + rpcArgs + ); + return new ComputeResource(result, this._client); + } + + /** Sets the remote image name for publishing */ + withRemoteImageName(remoteImageName: string): ComputeResourcePromise { + return new ComputeResourcePromise(this._withRemoteImageNameInternal(remoteImageName)); + } + + /** @internal */ + private async _withRemoteImageTagInternal(remoteImageTag: string): Promise { + const rpcArgs: Record = { builder: this._handle, remoteImageTag }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withRemoteImageTag', + rpcArgs + ); + return new ComputeResource(result, this._client); + } + + /** Sets the remote image tag for publishing */ + withRemoteImageTag(remoteImageTag: string): ComputeResourcePromise { + return new ComputeResourcePromise(this._withRemoteImageTagInternal(remoteImageTag)); + } + /** @internal */ private async _publishAsDockerComposeServiceInternal(configure: (arg1: DockerComposeServiceResource, arg2: Service) => Promise): Promise { const configureId = registerCallback(async (argsData: unknown) => { @@ -33929,6 +33699,16 @@ export class ComputeResourcePromise implements PromiseLike { return this._promise.then(onfulfilled, onrejected); } + /** Sets the remote image name for publishing */ + withRemoteImageName(remoteImageName: string): ComputeResourcePromise { + return new ComputeResourcePromise(this._promise.then(obj => obj.withRemoteImageName(remoteImageName))); + } + + /** Sets the remote image tag for publishing */ + withRemoteImageTag(remoteImageTag: string): ComputeResourcePromise { + return new ComputeResourcePromise(this._promise.then(obj => obj.withRemoteImageTag(remoteImageTag))); + } + /** Publishes the resource as a Docker Compose service with custom service configuration */ publishAsDockerComposeService(configure: (arg1: DockerComposeServiceResource, arg2: Service) => Promise): ComputeResourcePromise { return new ComputeResourcePromise(this._promise.then(obj => obj.publishAsDockerComposeService(configure))); @@ -34266,36 +34046,6 @@ export class Resource extends ResourceBuilderBase { return new ResourcePromise(this._excludeFromMcpInternal()); } - /** @internal */ - private async _withRemoteImageNameInternal(remoteImageName: string): Promise { - const rpcArgs: Record = { builder: this._handle, remoteImageName }; - const result = await this._client.invokeCapability( - 'Aspire.Hosting/withRemoteImageName', - rpcArgs - ); - return new Resource(result, this._client); - } - - /** Sets the remote image name for publishing */ - withRemoteImageName(remoteImageName: string): ResourcePromise { - return new ResourcePromise(this._withRemoteImageNameInternal(remoteImageName)); - } - - /** @internal */ - private async _withRemoteImageTagInternal(remoteImageTag: string): Promise { - const rpcArgs: Record = { builder: this._handle, remoteImageTag }; - const result = await this._client.invokeCapability( - 'Aspire.Hosting/withRemoteImageTag', - rpcArgs - ); - return new Resource(result, this._client); - } - - /** Sets the remote image tag for publishing */ - withRemoteImageTag(remoteImageTag: string): ResourcePromise { - return new ResourcePromise(this._withRemoteImageTagInternal(remoteImageTag)); - } - /** @internal */ private async _withPipelineStepFactoryInternal(stepName: string, callback: (arg: PipelineStepContext) => Promise, dependsOn?: string[], requiredBy?: string[], tags?: string[], description?: string): Promise { const callbackId = registerCallback(async (argData: unknown) => { @@ -34470,16 +34220,6 @@ export class ResourcePromise implements PromiseLike { return new ResourcePromise(this._promise.then(obj => obj.excludeFromMcp())); } - /** Sets the remote image name for publishing */ - withRemoteImageName(remoteImageName: string): ResourcePromise { - return new ResourcePromise(this._promise.then(obj => obj.withRemoteImageName(remoteImageName))); - } - - /** Sets the remote image tag for publishing */ - withRemoteImageTag(remoteImageTag: string): ResourcePromise { - return new ResourcePromise(this._promise.then(obj => obj.withRemoteImageTag(remoteImageTag))); - } - /** Adds a pipeline step to the resource */ withPipelineStepFactory(stepName: string, callback: (arg: PipelineStepContext) => Promise, options?: WithPipelineStepFactoryOptions): ResourcePromise { return new ResourcePromise(this._promise.then(obj => obj.withPipelineStepFactory(stepName, callback, options))); @@ -35668,7 +35408,7 @@ export async function createBuilder(options?: CreateBuilderOptions): Promise { const error = reason instanceof Error ? reason : new Error(String(reason)); - if (reason instanceof CapabilityError) { + if (reason instanceof AppHostUsageError) { + console.error(`\n❌ AppHost Error: ${error.message}`); + } else if (reason instanceof CapabilityError) { console.error(`\n❌ Capability Error: ${error.message}`); console.error(` Code: ${(reason as CapabilityError).code}`); if ((reason as CapabilityError).capability) { @@ -35699,8 +35441,12 @@ process.on('unhandledRejection', (reason: unknown) => { }); process.on('uncaughtException', (error: Error) => { - console.error(`\n❌ Uncaught Exception: ${error.message}`); - if (error.stack) { + if (error instanceof AppHostUsageError) { + console.error(`\n❌ AppHost Error: ${error.message}`); + } else { + console.error(`\n❌ Uncaught Exception: ${error.message}`); + } + if (!(error instanceof AppHostUsageError) && error.stack) { console.error(error.stack); } process.exit(1); diff --git a/playground/TypeScriptAppHost/.modules/base.ts b/playground/TypeScriptAppHost/.modules/base.ts index 7778b0f1737..6256537c773 100644 --- a/playground/TypeScriptAppHost/.modules/base.ts +++ b/playground/TypeScriptAppHost/.modules/base.ts @@ -1,5 +1,5 @@ // aspire.ts - Core Aspire types: base classes, ReferenceExpression -import { Handle, AspireClient, MarshalledHandle } from './transport.js'; +import { Handle, AspireClient, MarshalledHandle, registerCancellation, registerHandleWrapper, unregisterCancellation } from './transport.js'; // Re-export transport types for convenience export { Handle, AspireClient, CapabilityError, registerCallback, unregisterCallback, registerCancellation, unregisterCancellation } from './transport.js'; @@ -43,22 +43,46 @@ export class ReferenceExpression { private readonly _format?: string; private readonly _valueProviders?: unknown[]; + // Conditional mode fields + private readonly _condition?: unknown; + private readonly _whenTrue?: ReferenceExpression; + private readonly _whenFalse?: ReferenceExpression; + private readonly _matchValue?: string; + // Handle mode fields (when wrapping a server-returned handle) private readonly _handle?: Handle; private readonly _client?: AspireClient; constructor(format: string, valueProviders: unknown[]); constructor(handle: Handle, client: AspireClient); - constructor(handleOrFormat: Handle | string, clientOrValueProviders: AspireClient | unknown[]) { - if (typeof handleOrFormat === 'string') { - this._format = handleOrFormat; - this._valueProviders = clientOrValueProviders as unknown[]; + constructor(condition: unknown, matchValue: string, whenTrue: ReferenceExpression, whenFalse: ReferenceExpression); + constructor( + handleOrFormatOrCondition: Handle | string | unknown, + clientOrValueProvidersOrMatchValue: AspireClient | unknown[] | string, + whenTrueOrWhenFalse?: ReferenceExpression, + whenFalse?: ReferenceExpression + ) { + if (typeof handleOrFormatOrCondition === 'string') { + this._format = handleOrFormatOrCondition; + this._valueProviders = clientOrValueProvidersOrMatchValue as unknown[]; + } else if (handleOrFormatOrCondition instanceof Handle) { + this._handle = handleOrFormatOrCondition; + this._client = clientOrValueProvidersOrMatchValue as AspireClient; } else { - this._handle = handleOrFormat; - this._client = clientOrValueProviders as AspireClient; + this._condition = handleOrFormatOrCondition; + this._matchValue = (clientOrValueProvidersOrMatchValue as string) ?? 'True'; + this._whenTrue = whenTrueOrWhenFalse; + this._whenFalse = whenFalse; } } + /** + * Gets whether this reference expression is conditional. + */ + get isConditional(): boolean { + return this._condition !== undefined; + } + /** * Creates a reference expression from a tagged template literal. * @@ -82,16 +106,46 @@ export class ReferenceExpression { return new ReferenceExpression(format, valueProviders); } + /** + * Creates a conditional reference expression from its constituent parts. + * + * @param condition - A value provider whose result is compared to matchValue + * @param whenTrue - The expression to use when the condition matches + * @param whenFalse - The expression to use when the condition does not match + * @param matchValue - The value to compare the condition against (defaults to "True") + * @returns A ReferenceExpression instance in conditional mode + */ + static createConditional( + condition: unknown, + matchValue: string, + whenTrue: ReferenceExpression, + whenFalse: ReferenceExpression + ): ReferenceExpression { + return new ReferenceExpression(condition, matchValue, whenTrue, whenFalse); + } + /** * Serializes the reference expression for JSON-RPC transport. - * In template-literal mode, uses the $expr format. + * In expression mode, uses the $expr format with format + valueProviders. + * In conditional mode, uses the $expr format with condition + whenTrue + whenFalse. * In handle mode, delegates to the handle's serialization. */ - toJSON(): { $expr: { format: string; valueProviders?: unknown[] } } | MarshalledHandle { + toJSON(): { $expr: { format: string; valueProviders?: unknown[] } | { condition: unknown; whenTrue: unknown; whenFalse: unknown; matchValue: string } } | MarshalledHandle { if (this._handle) { return this._handle.toJSON(); } + if (this.isConditional) { + return { + $expr: { + condition: this._condition instanceof Handle ? this._condition.toJSON() : this._condition, + whenTrue: this._whenTrue!.toJSON(), + whenFalse: this._whenFalse!.toJSON(), + matchValue: this._matchValue! + } + }; + } + return { $expr: { format: this._format!, @@ -100,6 +154,30 @@ export class ReferenceExpression { }; } + /** + * Resolves the expression to its string value on the server. + * Only available on server-returned ReferenceExpression instances (handle mode). + * + * @param cancellationToken - Optional AbortSignal for cancellation support + * @returns The resolved string value, or null if the expression resolves to null + */ + async getValue(cancellationToken?: AbortSignal): Promise { + if (!this._handle || !this._client) { + throw new Error('getValue is only available on server-returned ReferenceExpression instances'); + } + const cancellationTokenId = registerCancellation(cancellationToken); + try { + const rpcArgs: Record = { context: this._handle }; + if (cancellationTokenId !== undefined) rpcArgs.cancellationToken = cancellationTokenId; + return await this._client.invokeCapability( + 'Aspire.Hosting.ApplicationModel/getValue', + rpcArgs + ); + } finally { + unregisterCancellation(cancellationTokenId); + } + } + /** * String representation for debugging. */ @@ -107,10 +185,17 @@ export class ReferenceExpression { if (this._handle) { return `ReferenceExpression(handle)`; } + if (this.isConditional) { + return `ReferenceExpression(conditional)`; + } return `ReferenceExpression(${this._format})`; } } +registerHandleWrapper('Aspire.Hosting/Aspire.Hosting.ApplicationModel.ReferenceExpression', (handle, client) => + new ReferenceExpression(handle, client) +); + /** * Extracts a value for use in reference expressions. * Supports handles (objects) and string literals. diff --git a/playground/TypeScriptAppHost/.modules/transport.ts b/playground/TypeScriptAppHost/.modules/transport.ts index 7bddd74beff..7ee1ba87e3f 100644 --- a/playground/TypeScriptAppHost/.modules/transport.ts +++ b/playground/TypeScriptAppHost/.modules/transport.ts @@ -213,6 +213,75 @@ export class CapabilityError extends Error { } } +/** + * Error thrown when the AppHost script uses the generated SDK incorrectly. + */ +export class AppHostUsageError extends Error { + constructor(message: string) { + super(message); + this.name = 'AppHostUsageError'; + } +} + +function isPromiseLike(value: unknown): value is PromiseLike { + return ( + value !== null && + (typeof value === 'object' || typeof value === 'function') && + 'then' in value && + typeof (value as { then?: unknown }).then === 'function' + ); +} + +function validateCapabilityArgs( + capabilityId: string, + args?: Record +): void { + if (!args) { + return; + } + + const seen = new Set(); + + const validateValue = (value: unknown, path: string): void => { + if (value === null || value === undefined) { + return; + } + + if (isPromiseLike(value)) { + throw new AppHostUsageError( + `Argument '${path}' passed to capability '${capabilityId}' is a Promise-like value. ` + + `This usually means an async builder call was not awaited. ` + + `Did you forget 'await' on a call like builder.addPostgres(...) or resource.addDatabase(...)?` + ); + } + + if (typeof value !== 'object') { + return; + } + + if (seen.has(value)) { + return; + } + + seen.add(value); + + if (Array.isArray(value)) { + for (let i = 0; i < value.length; i++) { + validateValue(value[i], `${path}[${i}]`); + } + return; + } + + for (const [key, nestedValue] of Object.entries(value)) { + validateValue(nestedValue, `${path}.${key}`); + } + }; + + for (const [key, value] of Object.entries(args)) { + validateValue(value, key); + } +} + // ============================================================================ // Callback Registry // ============================================================================ @@ -533,6 +602,8 @@ export class AspireClient { throw new Error('Not connected to AppHost'); } + validateCapabilityArgs(capabilityId, args); + // Ref counting: The vscode-jsonrpc socket keeps Node's event loop alive. // We ref() during RPC calls so the process doesn't exit mid-call, and // unref() when idle so the process can exit naturally after all work completes. diff --git a/playground/TypeScriptApps/AzureFunctionsSample/.vscode/launch.json b/playground/TypeScriptApps/AzureFunctionsSample/.vscode/launch.json new file mode 100644 index 00000000000..94e0ef19952 --- /dev/null +++ b/playground/TypeScriptApps/AzureFunctionsSample/.vscode/launch.json @@ -0,0 +1,11 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "type": "aspire", + "request": "launch", + "name": "Aspire: Launch default apphost", + "program": "${workspaceFolder}" + } + ] +} \ No newline at end of file diff --git a/playground/TypeScriptApps/AzureFunctionsSample/AppHost/.modules/.codegen-hash b/playground/TypeScriptApps/AzureFunctionsSample/AppHost/.modules/.codegen-hash new file mode 100644 index 00000000000..8f28713a500 --- /dev/null +++ b/playground/TypeScriptApps/AzureFunctionsSample/AppHost/.modules/.codegen-hash @@ -0,0 +1 @@ +02C050302BF2388A87AE0E8B5C0E64E0146DBFA457409DA99D8EBF1DD30A95B6 \ No newline at end of file diff --git a/playground/TypeScriptApps/AzureFunctionsSample/AppHost/.modules/aspire.ts b/playground/TypeScriptApps/AzureFunctionsSample/AppHost/.modules/aspire.ts new file mode 100644 index 00000000000..0262e7bb436 --- /dev/null +++ b/playground/TypeScriptApps/AzureFunctionsSample/AppHost/.modules/aspire.ts @@ -0,0 +1,33955 @@ +// aspire.ts - Capability-based Aspire SDK +// This SDK uses the ATS (Aspire Type System) capability API. +// Capabilities are endpoints like 'Aspire.Hosting/createBuilder'. +// +// GENERATED CODE - DO NOT EDIT + +import { + AspireClient as AspireClientRpc, + Handle, + MarshalledHandle, + AppHostUsageError, + CapabilityError, + registerCallback, + wrapIfHandle, + registerHandleWrapper +} from './transport.js'; + +import { + ResourceBuilderBase, + ReferenceExpression, + refExpr, + AspireDict, + AspireList +} from './base.js'; + +// ============================================================================ +// Handle Type Aliases (Internal - not exported to users) +// ============================================================================ + +/** Handle to AzureEventHubConsumerGroupResource */ +type AzureEventHubConsumerGroupResourceHandle = Handle<'Aspire.Hosting.Azure.EventHubs/Aspire.Hosting.Azure.AzureEventHubConsumerGroupResource'>; + +/** Handle to AzureEventHubResource */ +type AzureEventHubResourceHandle = Handle<'Aspire.Hosting.Azure.EventHubs/Aspire.Hosting.Azure.AzureEventHubResource'>; + +/** Handle to AzureEventHubsEmulatorResource */ +type AzureEventHubsEmulatorResourceHandle = Handle<'Aspire.Hosting.Azure.EventHubs/Aspire.Hosting.Azure.AzureEventHubsEmulatorResource'>; + +/** Handle to AzureEventHubsResource */ +type AzureEventHubsResourceHandle = Handle<'Aspire.Hosting.Azure.EventHubs/Aspire.Hosting.Azure.AzureEventHubsResource'>; + +/** Handle to AzureBlobStorageContainerResource */ +type AzureBlobStorageContainerResourceHandle = Handle<'Aspire.Hosting.Azure.Storage/Aspire.Hosting.Azure.AzureBlobStorageContainerResource'>; + +/** Handle to AzureBlobStorageResource */ +type AzureBlobStorageResourceHandle = Handle<'Aspire.Hosting.Azure.Storage/Aspire.Hosting.Azure.AzureBlobStorageResource'>; + +/** Handle to AzureDataLakeStorageFileSystemResource */ +type AzureDataLakeStorageFileSystemResourceHandle = Handle<'Aspire.Hosting.Azure.Storage/Aspire.Hosting.Azure.AzureDataLakeStorageFileSystemResource'>; + +/** Handle to AzureDataLakeStorageResource */ +type AzureDataLakeStorageResourceHandle = Handle<'Aspire.Hosting.Azure.Storage/Aspire.Hosting.Azure.AzureDataLakeStorageResource'>; + +/** Handle to AzureQueueStorageQueueResource */ +type AzureQueueStorageQueueResourceHandle = Handle<'Aspire.Hosting.Azure.Storage/Aspire.Hosting.Azure.AzureQueueStorageQueueResource'>; + +/** Handle to AzureQueueStorageResource */ +type AzureQueueStorageResourceHandle = Handle<'Aspire.Hosting.Azure.Storage/Aspire.Hosting.Azure.AzureQueueStorageResource'>; + +/** Handle to AzureStorageEmulatorResource */ +type AzureStorageEmulatorResourceHandle = Handle<'Aspire.Hosting.Azure.Storage/Aspire.Hosting.Azure.AzureStorageEmulatorResource'>; + +/** Handle to AzureStorageResource */ +type AzureStorageResourceHandle = Handle<'Aspire.Hosting.Azure.Storage/Aspire.Hosting.Azure.AzureStorageResource'>; + +/** Handle to AzureTableStorageResource */ +type AzureTableStorageResourceHandle = Handle<'Aspire.Hosting.Azure.Storage/Aspire.Hosting.Azure.AzureTableStorageResource'>; + +/** Handle to IAzureResource */ +type IAzureResourceHandle = Handle<'Aspire.Hosting.Azure/Aspire.Hosting.ApplicationModel.IAzureResource'>; + +/** Handle to AzureBicepResource */ +type AzureBicepResourceHandle = Handle<'Aspire.Hosting.Azure/Aspire.Hosting.Azure.AzureBicepResource'>; + +/** Handle to AzureEnvironmentResource */ +type AzureEnvironmentResourceHandle = Handle<'Aspire.Hosting.Azure/Aspire.Hosting.Azure.AzureEnvironmentResource'>; + +/** Handle to AzureProvisioningResource */ +type AzureProvisioningResourceHandle = Handle<'Aspire.Hosting.Azure/Aspire.Hosting.Azure.AzureProvisioningResource'>; + +/** Handle to AzureResourceInfrastructure */ +type AzureResourceInfrastructureHandle = Handle<'Aspire.Hosting.Azure/Aspire.Hosting.Azure.AzureResourceInfrastructure'>; + +/** Handle to AzureUserAssignedIdentityResource */ +type AzureUserAssignedIdentityResourceHandle = Handle<'Aspire.Hosting.Azure/Aspire.Hosting.Azure.AzureUserAssignedIdentityResource'>; + +/** Handle to BicepOutputReference */ +type BicepOutputReferenceHandle = Handle<'Aspire.Hosting.Azure/Aspire.Hosting.Azure.BicepOutputReference'>; + +/** Handle to IAzureKeyVaultSecretReference */ +type IAzureKeyVaultSecretReferenceHandle = Handle<'Aspire.Hosting.Azure/Aspire.Hosting.Azure.IAzureKeyVaultSecretReference'>; + +/** Handle to JavaScriptAppResource */ +type JavaScriptAppResourceHandle = Handle<'Aspire.Hosting.JavaScript/Aspire.Hosting.JavaScript.JavaScriptAppResource'>; + +/** Handle to NodeAppResource */ +type NodeAppResourceHandle = Handle<'Aspire.Hosting.JavaScript/Aspire.Hosting.JavaScript.NodeAppResource'>; + +/** Handle to ViteAppResource */ +type ViteAppResourceHandle = Handle<'Aspire.Hosting.JavaScript/Aspire.Hosting.JavaScript.ViteAppResource'>; + +/** Handle to CommandLineArgsCallbackContext */ +type CommandLineArgsCallbackContextHandle = Handle<'Aspire.Hosting/Aspire.Hosting.ApplicationModel.CommandLineArgsCallbackContext'>; + +/** Handle to ContainerRegistryResource */ +type ContainerRegistryResourceHandle = Handle<'Aspire.Hosting/Aspire.Hosting.ApplicationModel.ContainerRegistryResource'>; + +/** Handle to ContainerResource */ +type ContainerResourceHandle = Handle<'Aspire.Hosting/Aspire.Hosting.ApplicationModel.ContainerResource'>; + +/** Handle to CSharpAppResource */ +type CSharpAppResourceHandle = Handle<'Aspire.Hosting/Aspire.Hosting.ApplicationModel.CSharpAppResource'>; + +/** Handle to DotnetToolResource */ +type DotnetToolResourceHandle = Handle<'Aspire.Hosting/Aspire.Hosting.ApplicationModel.DotnetToolResource'>; + +/** Handle to EndpointReference */ +type EndpointReferenceHandle = Handle<'Aspire.Hosting/Aspire.Hosting.ApplicationModel.EndpointReference'>; + +/** Handle to EndpointReferenceExpression */ +type EndpointReferenceExpressionHandle = Handle<'Aspire.Hosting/Aspire.Hosting.ApplicationModel.EndpointReferenceExpression'>; + +/** Handle to EnvironmentCallbackContext */ +type EnvironmentCallbackContextHandle = Handle<'Aspire.Hosting/Aspire.Hosting.ApplicationModel.EnvironmentCallbackContext'>; + +/** Handle to ExecutableResource */ +type ExecutableResourceHandle = Handle<'Aspire.Hosting/Aspire.Hosting.ApplicationModel.ExecutableResource'>; + +/** Handle to ExecuteCommandContext */ +type ExecuteCommandContextHandle = Handle<'Aspire.Hosting/Aspire.Hosting.ApplicationModel.ExecuteCommandContext'>; + +/** Handle to IComputeResource */ +type IComputeResourceHandle = Handle<'Aspire.Hosting/Aspire.Hosting.ApplicationModel.IComputeResource'>; + +/** Handle to IContainerFilesDestinationResource */ +type IContainerFilesDestinationResourceHandle = Handle<'Aspire.Hosting/Aspire.Hosting.ApplicationModel.IContainerFilesDestinationResource'>; + +/** Handle to IResource */ +type IResourceHandle = Handle<'Aspire.Hosting/Aspire.Hosting.ApplicationModel.IResource'>; + +/** Handle to IResourceWithArgs */ +type IResourceWithArgsHandle = Handle<'Aspire.Hosting/Aspire.Hosting.ApplicationModel.IResourceWithArgs'>; + +/** Handle to IResourceWithConnectionString */ +type IResourceWithConnectionStringHandle = Handle<'Aspire.Hosting/Aspire.Hosting.ApplicationModel.IResourceWithConnectionString'>; + +/** Handle to IResourceWithEndpoints */ +type IResourceWithEndpointsHandle = Handle<'Aspire.Hosting/Aspire.Hosting.ApplicationModel.IResourceWithEndpoints'>; + +/** Handle to IResourceWithEnvironment */ +type IResourceWithEnvironmentHandle = Handle<'Aspire.Hosting/Aspire.Hosting.ApplicationModel.IResourceWithEnvironment'>; + +/** Handle to IResourceWithWaitSupport */ +type IResourceWithWaitSupportHandle = Handle<'Aspire.Hosting/Aspire.Hosting.ApplicationModel.IResourceWithWaitSupport'>; + +/** Handle to ParameterResource */ +type ParameterResourceHandle = Handle<'Aspire.Hosting/Aspire.Hosting.ApplicationModel.ParameterResource'>; + +/** Handle to ProjectResource */ +type ProjectResourceHandle = Handle<'Aspire.Hosting/Aspire.Hosting.ApplicationModel.ProjectResource'>; + +/** Handle to ReferenceExpression */ +type ReferenceExpressionHandle = Handle<'Aspire.Hosting/Aspire.Hosting.ApplicationModel.ReferenceExpression'>; + +/** Handle to ReferenceExpressionBuilder */ +type ReferenceExpressionBuilderHandle = Handle<'Aspire.Hosting/Aspire.Hosting.ApplicationModel.ReferenceExpressionBuilder'>; + +/** Handle to ResourceLoggerService */ +type ResourceLoggerServiceHandle = Handle<'Aspire.Hosting/Aspire.Hosting.ApplicationModel.ResourceLoggerService'>; + +/** Handle to ResourceNotificationService */ +type ResourceNotificationServiceHandle = Handle<'Aspire.Hosting/Aspire.Hosting.ApplicationModel.ResourceNotificationService'>; + +/** Handle to ResourceUrlsCallbackContext */ +type ResourceUrlsCallbackContextHandle = Handle<'Aspire.Hosting/Aspire.Hosting.ApplicationModel.ResourceUrlsCallbackContext'>; + +/** Handle to ConnectionStringResource */ +type ConnectionStringResourceHandle = Handle<'Aspire.Hosting/Aspire.Hosting.ConnectionStringResource'>; + +/** Handle to DistributedApplication */ +type DistributedApplicationHandle = Handle<'Aspire.Hosting/Aspire.Hosting.DistributedApplication'>; + +/** Handle to DistributedApplicationExecutionContext */ +type DistributedApplicationExecutionContextHandle = Handle<'Aspire.Hosting/Aspire.Hosting.DistributedApplicationExecutionContext'>; + +/** Handle to DistributedApplicationEventSubscription */ +type DistributedApplicationEventSubscriptionHandle = Handle<'Aspire.Hosting/Aspire.Hosting.Eventing.DistributedApplicationEventSubscription'>; + +/** Handle to IDistributedApplicationEventing */ +type IDistributedApplicationEventingHandle = Handle<'Aspire.Hosting/Aspire.Hosting.Eventing.IDistributedApplicationEventing'>; + +/** Handle to ExternalServiceResource */ +type ExternalServiceResourceHandle = Handle<'Aspire.Hosting/Aspire.Hosting.ExternalServiceResource'>; + +/** Handle to IDistributedApplicationBuilder */ +type IDistributedApplicationBuilderHandle = Handle<'Aspire.Hosting/Aspire.Hosting.IDistributedApplicationBuilder'>; + +/** Handle to IResourceWithContainerFiles */ +type IResourceWithContainerFilesHandle = Handle<'Aspire.Hosting/Aspire.Hosting.IResourceWithContainerFiles'>; + +/** Handle to IResourceWithServiceDiscovery */ +type IResourceWithServiceDiscoveryHandle = Handle<'Aspire.Hosting/Aspire.Hosting.IResourceWithServiceDiscovery'>; + +/** Handle to PipelineConfigurationContext */ +type PipelineConfigurationContextHandle = Handle<'Aspire.Hosting/Aspire.Hosting.Pipelines.PipelineConfigurationContext'>; + +/** Handle to PipelineStep */ +type PipelineStepHandle = Handle<'Aspire.Hosting/Aspire.Hosting.Pipelines.PipelineStep'>; + +/** Handle to PipelineStepContext */ +type PipelineStepContextHandle = Handle<'Aspire.Hosting/Aspire.Hosting.Pipelines.PipelineStepContext'>; + +/** Handle to ProjectResourceOptions */ +type ProjectResourceOptionsHandle = Handle<'Aspire.Hosting/Aspire.Hosting.ProjectResourceOptions'>; + +/** Handle to Dict */ +type DictstringanyHandle = Handle<'Aspire.Hosting/Dict'>; + +/** Handle to List */ +type ListanyHandle = Handle<'Aspire.Hosting/List'>; + +/** Handle to IConfiguration */ +type IConfigurationHandle = Handle<'Microsoft.Extensions.Configuration.Abstractions/Microsoft.Extensions.Configuration.IConfiguration'>; + +/** Handle to IHostEnvironment */ +type IHostEnvironmentHandle = Handle<'Microsoft.Extensions.Hosting.Abstractions/Microsoft.Extensions.Hosting.IHostEnvironment'>; + +/** Handle to ILogger */ +type ILoggerHandle = Handle<'Microsoft.Extensions.Logging.Abstractions/Microsoft.Extensions.Logging.ILogger'>; + +/** Handle to string[] */ +type stringArrayHandle = Handle<'string[]'>; + +/** Handle to IServiceProvider */ +type IServiceProviderHandle = Handle<'System.ComponentModel/System.IServiceProvider'>; + +// ============================================================================ +// Enum Types +// ============================================================================ + +/** Enum type for AzureEventHubsRole */ +export enum AzureEventHubsRole { + AzureEventHubsDataOwner = "AzureEventHubsDataOwner", + AzureEventHubsDataReceiver = "AzureEventHubsDataReceiver", + AzureEventHubsDataSender = "AzureEventHubsDataSender", +} + +/** Enum type for AzureStorageRole */ +export enum AzureStorageRole { + ClassicStorageAccountContributor = "ClassicStorageAccountContributor", + ClassicStorageAccountKeyOperatorServiceRole = "ClassicStorageAccountKeyOperatorServiceRole", + StorageAccountBackupContributor = "StorageAccountBackupContributor", + StorageAccountContributor = "StorageAccountContributor", + StorageAccountKeyOperatorServiceRole = "StorageAccountKeyOperatorServiceRole", + StorageBlobDataContributor = "StorageBlobDataContributor", + StorageBlobDataOwner = "StorageBlobDataOwner", + StorageBlobDataReader = "StorageBlobDataReader", + StorageBlobDelegator = "StorageBlobDelegator", + StorageFileDataPrivilegedContributor = "StorageFileDataPrivilegedContributor", + StorageFileDataPrivilegedReader = "StorageFileDataPrivilegedReader", + StorageFileDataSmbShareContributor = "StorageFileDataSmbShareContributor", + StorageFileDataSmbShareReader = "StorageFileDataSmbShareReader", + StorageFileDataSmbShareElevatedContributor = "StorageFileDataSmbShareElevatedContributor", + StorageQueueDataContributor = "StorageQueueDataContributor", + StorageQueueDataReader = "StorageQueueDataReader", + StorageQueueDataMessageSender = "StorageQueueDataMessageSender", + StorageQueueDataMessageProcessor = "StorageQueueDataMessageProcessor", + StorageTableDataContributor = "StorageTableDataContributor", + StorageTableDataReader = "StorageTableDataReader", +} + +/** Enum type for CertificateTrustScope */ +export enum CertificateTrustScope { + None = "None", + Append = "Append", + Override = "Override", + System = "System", +} + +/** Enum type for ContainerLifetime */ +export enum ContainerLifetime { + Session = "Session", + Persistent = "Persistent", +} + +/** Enum type for DeploymentScope */ +export enum DeploymentScope { + ResourceGroup = "ResourceGroup", + Subscription = "Subscription", + ManagementGroup = "ManagementGroup", + Tenant = "Tenant", +} + +/** Enum type for DistributedApplicationOperation */ +export enum DistributedApplicationOperation { + Run = "Run", + Publish = "Publish", +} + +/** Enum type for EndpointProperty */ +export enum EndpointProperty { + Url = "Url", + Host = "Host", + IPV4Host = "IPV4Host", + Port = "Port", + Scheme = "Scheme", + TargetPort = "TargetPort", + HostAndPort = "HostAndPort", + TlsEnabled = "TlsEnabled", +} + +/** Enum type for IconVariant */ +export enum IconVariant { + Regular = "Regular", + Filled = "Filled", +} + +/** Enum type for ImagePullPolicy */ +export enum ImagePullPolicy { + Default = "Default", + Always = "Always", + Missing = "Missing", + Never = "Never", +} + +/** Enum type for OtlpProtocol */ +export enum OtlpProtocol { + Grpc = "Grpc", + HttpProtobuf = "HttpProtobuf", + HttpJson = "HttpJson", +} + +/** Enum type for ProbeType */ +export enum ProbeType { + Startup = "Startup", + Readiness = "Readiness", + Liveness = "Liveness", +} + +/** Enum type for ProtocolType */ +export enum ProtocolType { + IP = "IP", + IPv6HopByHopOptions = "IPv6HopByHopOptions", + Unspecified = "Unspecified", + Icmp = "Icmp", + Igmp = "Igmp", + Ggp = "Ggp", + IPv4 = "IPv4", + Tcp = "Tcp", + Pup = "Pup", + Udp = "Udp", + Idp = "Idp", + IPv6 = "IPv6", + IPv6RoutingHeader = "IPv6RoutingHeader", + IPv6FragmentHeader = "IPv6FragmentHeader", + IPSecEncapsulatingSecurityPayload = "IPSecEncapsulatingSecurityPayload", + IPSecAuthenticationHeader = "IPSecAuthenticationHeader", + IcmpV6 = "IcmpV6", + IPv6NoNextHeader = "IPv6NoNextHeader", + IPv6DestinationOptions = "IPv6DestinationOptions", + ND = "ND", + Raw = "Raw", + Ipx = "Ipx", + Spx = "Spx", + SpxII = "SpxII", + Unknown = "Unknown", +} + +/** Enum type for UrlDisplayLocation */ +export enum UrlDisplayLocation { + SummaryAndDetails = "SummaryAndDetails", + DetailsOnly = "DetailsOnly", +} + +/** Enum type for WaitBehavior */ +export enum WaitBehavior { + WaitOnResourceUnavailable = "WaitOnResourceUnavailable", + StopOnResourceUnavailable = "StopOnResourceUnavailable", +} + +// ============================================================================ +// DTO Interfaces +// ============================================================================ + +/** DTO interface for CommandOptions */ +export interface CommandOptions { + description?: string; + parameter?: any; + confirmationMessage?: string; + iconName?: string; + iconVariant?: IconVariant; + isHighlighted?: boolean; + updateState?: any; +} + +/** DTO interface for CreateBuilderOptions */ +export interface CreateBuilderOptions { + args?: string[]; + projectDirectory?: string; + appHostFilePath?: string; + containerRegistryOverride?: string; + disableDashboard?: boolean; + dashboardApplicationName?: string; + allowUnsecuredTransport?: boolean; + enableResourceLogging?: boolean; +} + +/** DTO interface for ExecuteCommandResult */ +export interface ExecuteCommandResult { + success?: boolean; + canceled?: boolean; + errorMessage?: string; +} + +/** DTO interface for ResourceEventDto */ +export interface ResourceEventDto { + resourceName?: string; + resourceId?: string; + state?: string; + stateStyle?: string; + healthStatus?: string; + exitCode?: number; +} + +/** DTO interface for ResourceUrlAnnotation */ +export interface ResourceUrlAnnotation { + url?: string; + displayText?: string; + endpoint?: EndpointReferenceHandle; + displayLocation?: UrlDisplayLocation; +} + +// ============================================================================ +// Options Interfaces +// ============================================================================ + +export interface AddBlobContainerOptions { + blobContainerName?: string; +} + +export interface AddConnectionStringOptions { + environmentVariableName?: string; +} + +export interface AddConsumerGroupOptions { + groupName?: string; +} + +export interface AddContainerRegistryOptions { + repository?: ParameterResource; +} + +export interface AddDataLakeFileSystemOptions { + dataLakeFileSystemName?: string; +} + +export interface AddDockerfileOptions { + dockerfilePath?: string; + stage?: string; +} + +export interface AddHubOptions { + hubName?: string; +} + +export interface AddJavaScriptAppOptions { + runScriptName?: string; +} + +export interface AddParameterFromConfigurationOptions { + secret?: boolean; +} + +export interface AddParameterOptions { + secret?: boolean; +} + +export interface AddQueueOptions { + queueName?: string; +} + +export interface AddViteAppOptions { + runScriptName?: string; +} + +export interface AppendFormattedOptions { + format?: string; +} + +export interface AppendValueProviderOptions { + format?: string; +} + +export interface GetValueAsyncOptions { + cancellationToken?: AbortSignal; +} + +export interface PublishAsDockerFileOptions { + configure?: (obj: ContainerResource) => Promise; +} + +export interface RunAsEmulator1Options { + configureContainer?: (obj: AzureStorageEmulatorResource) => Promise; +} + +export interface RunAsEmulatorOptions { + configureContainer?: (obj: AzureEventHubsEmulatorResource) => Promise; +} + +export interface RunOptions { + cancellationToken?: AbortSignal; +} + +export interface WaitForCompletionOptions { + exitCode?: number; +} + +export interface WithApiVersionCheckOptions { + enable?: boolean; +} + +export interface WithBindMountOptions { + isReadOnly?: boolean; +} + +export interface WithBrowserDebuggerOptions { + browser?: string; +} + +export interface WithBuildScriptOptions { + args?: string[]; +} + +export interface WithBunOptions { + install?: boolean; + installArgs?: string[]; +} + +export interface WithCommandOptions { + commandOptions?: CommandOptions; +} + +export interface WithDataBindMountOptions { + path?: string; + isReadOnly?: boolean; +} + +export interface WithDataVolumeOptions { + name?: string; + isReadOnly?: boolean; +} + +export interface WithDescriptionOptions { + enableMarkdown?: boolean; +} + +export interface WithDockerfileBaseImageOptions { + buildImage?: string; + runtimeImage?: string; +} + +export interface WithDockerfileOptions { + dockerfilePath?: string; + stage?: string; +} + +export interface WithEndpointOptions { + port?: number; + targetPort?: number; + scheme?: string; + name?: string; + env?: string; + isProxied?: boolean; + isExternal?: boolean; + protocol?: ProtocolType; +} + +export interface WithExternalServiceHttpHealthCheckOptions { + path?: string; + statusCode?: number; +} + +export interface WithHostPortOptions { + port?: number; +} + +export interface WithHttpEndpointOptions { + port?: number; + targetPort?: number; + name?: string; + env?: string; + isProxied?: boolean; +} + +export interface WithHttpHealthCheckOptions { + path?: string; + statusCode?: number; + endpointName?: string; +} + +export interface WithHttpProbeOptions { + path?: string; + initialDelaySeconds?: number; + periodSeconds?: number; + timeoutSeconds?: number; + failureThreshold?: number; + successThreshold?: number; + endpointName?: string; +} + +export interface WithHttpsDeveloperCertificateOptions { + password?: ParameterResource; +} + +export interface WithHttpsEndpointOptions { + port?: number; + targetPort?: number; + name?: string; + env?: string; + isProxied?: boolean; +} + +export interface WithIconNameOptions { + iconVariant?: IconVariant; +} + +export interface WithImageOptions { + tag?: string; +} + +export interface WithMcpServerOptions { + path?: string; + endpointName?: string; +} + +export interface WithNpmOptions { + install?: boolean; + installCommand?: string; + installArgs?: string[]; +} + +export interface WithPipelineStepFactoryOptions { + dependsOn?: string[]; + requiredBy?: string[]; + tags?: string[]; + description?: string; +} + +export interface WithPnpmOptions { + install?: boolean; + installArgs?: string[]; +} + +export interface WithReferenceOptions { + connectionName?: string; + optional?: boolean; +} + +export interface WithRequiredCommandOptions { + helpLink?: string; +} + +export interface WithRunScriptOptions { + args?: string[]; +} + +export interface WithUrlExpressionOptions { + displayText?: string; +} + +export interface WithUrlOptions { + displayText?: string; +} + +export interface WithVolumeOptions { + name?: string; + isReadOnly?: boolean; +} + +export interface WithYarnOptions { + install?: boolean; + installArgs?: string[]; +} + +// ============================================================================ +// AzureResourceInfrastructure +// ============================================================================ + +/** + * Type class for AzureResourceInfrastructure. + */ +export class AzureResourceInfrastructure { + constructor(private _handle: AzureResourceInfrastructureHandle, private _client: AspireClientRpc) {} + + /** Serialize for JSON-RPC transport */ + toJSON(): MarshalledHandle { return this._handle.toJSON(); } + + /** Gets the BicepName property */ + bicepName = { + get: async (): Promise => { + return await this._client.invokeCapability( + 'Aspire.Hosting.Azure/AzureResourceInfrastructure.bicepName', + { context: this._handle } + ); + }, + }; + + /** Gets the TargetScope property */ + targetScope = { + get: async (): Promise => { + return await this._client.invokeCapability( + 'Aspire.Hosting.Azure/AzureResourceInfrastructure.targetScope', + { context: this._handle } + ); + }, + set: async (value: DeploymentScope): Promise => { + await this._client.invokeCapability( + 'Aspire.Hosting.Azure/AzureResourceInfrastructure.setTargetScope', + { context: this._handle, value } + ); + } + }; + +} + +// ============================================================================ +// BicepOutputReference +// ============================================================================ + +/** + * Type class for BicepOutputReference. + */ +export class BicepOutputReference { + constructor(private _handle: BicepOutputReferenceHandle, private _client: AspireClientRpc) {} + + /** Serialize for JSON-RPC transport */ + toJSON(): MarshalledHandle { return this._handle.toJSON(); } + + /** Gets the Name property */ + name = { + get: async (): Promise => { + return await this._client.invokeCapability( + 'Aspire.Hosting.Azure/BicepOutputReference.name', + { context: this._handle } + ); + }, + }; + + /** Gets the Value property */ + value = { + get: async (): Promise => { + return await this._client.invokeCapability( + 'Aspire.Hosting.Azure/BicepOutputReference.value', + { context: this._handle } + ); + }, + }; + + /** Gets the ValueExpression property */ + valueExpression = { + get: async (): Promise => { + return await this._client.invokeCapability( + 'Aspire.Hosting.Azure/BicepOutputReference.valueExpression', + { context: this._handle } + ); + }, + }; + +} + +// ============================================================================ +// CommandLineArgsCallbackContext +// ============================================================================ + +/** + * Type class for CommandLineArgsCallbackContext. + */ +export class CommandLineArgsCallbackContext { + constructor(private _handle: CommandLineArgsCallbackContextHandle, private _client: AspireClientRpc) {} + + /** Serialize for JSON-RPC transport */ + toJSON(): MarshalledHandle { return this._handle.toJSON(); } + + /** Gets the Args property */ + private _args?: AspireList; + get args(): AspireList { + if (!this._args) { + this._args = new AspireList( + this._handle, + this._client, + 'Aspire.Hosting.ApplicationModel/CommandLineArgsCallbackContext.args', + 'Aspire.Hosting.ApplicationModel/CommandLineArgsCallbackContext.args' + ); + } + return this._args; + } + + /** Gets the CancellationToken property */ + cancellationToken = { + get: async (): Promise => { + return await this._client.invokeCapability( + 'Aspire.Hosting.ApplicationModel/CommandLineArgsCallbackContext.cancellationToken', + { context: this._handle } + ); + }, + }; + + /** Gets the ExecutionContext property */ + executionContext = { + get: async (): Promise => { + const handle = await this._client.invokeCapability( + 'Aspire.Hosting.ApplicationModel/CommandLineArgsCallbackContext.executionContext', + { context: this._handle } + ); + return new DistributedApplicationExecutionContext(handle, this._client); + }, + }; + +} + +// ============================================================================ +// DistributedApplication +// ============================================================================ + +/** + * Type class for DistributedApplication. + */ +export class DistributedApplication { + constructor(private _handle: DistributedApplicationHandle, private _client: AspireClientRpc) {} + + /** Serialize for JSON-RPC transport */ + toJSON(): MarshalledHandle { return this._handle.toJSON(); } + + /** Runs the distributed application */ + /** @internal */ + async _runInternal(cancellationToken?: AbortSignal): Promise { + const rpcArgs: Record = { context: this._handle }; + if (cancellationToken !== undefined) rpcArgs.cancellationToken = cancellationToken; + await this._client.invokeCapability( + 'Aspire.Hosting/run', + rpcArgs + ); + return this; + } + + run(options?: RunOptions): DistributedApplicationPromise { + const cancellationToken = options?.cancellationToken; + return new DistributedApplicationPromise(this._runInternal(cancellationToken)); + } + +} + +/** + * Thenable wrapper for DistributedApplication that enables fluent chaining. + */ +export class DistributedApplicationPromise implements PromiseLike { + constructor(private _promise: Promise) {} + + then( + onfulfilled?: ((value: DistributedApplication) => TResult1 | PromiseLike) | null, + onrejected?: ((reason: unknown) => TResult2 | PromiseLike) | null + ): PromiseLike { + return this._promise.then(onfulfilled, onrejected); + } + + /** Runs the distributed application */ + run(options?: RunOptions): DistributedApplicationPromise { + return new DistributedApplicationPromise(this._promise.then(obj => obj.run(options))); + } + +} + +// ============================================================================ +// DistributedApplicationExecutionContext +// ============================================================================ + +/** + * Type class for DistributedApplicationExecutionContext. + */ +export class DistributedApplicationExecutionContext { + constructor(private _handle: DistributedApplicationExecutionContextHandle, private _client: AspireClientRpc) {} + + /** Serialize for JSON-RPC transport */ + toJSON(): MarshalledHandle { return this._handle.toJSON(); } + + /** Gets the PublisherName property */ + publisherName = { + get: async (): Promise => { + return await this._client.invokeCapability( + 'Aspire.Hosting/DistributedApplicationExecutionContext.publisherName', + { context: this._handle } + ); + }, + set: async (value: string): Promise => { + await this._client.invokeCapability( + 'Aspire.Hosting/DistributedApplicationExecutionContext.setPublisherName', + { context: this._handle, value } + ); + } + }; + + /** Gets the Operation property */ + operation = { + get: async (): Promise => { + return await this._client.invokeCapability( + 'Aspire.Hosting/DistributedApplicationExecutionContext.operation', + { context: this._handle } + ); + }, + }; + + /** Gets the IsPublishMode property */ + isPublishMode = { + get: async (): Promise => { + return await this._client.invokeCapability( + 'Aspire.Hosting/DistributedApplicationExecutionContext.isPublishMode', + { context: this._handle } + ); + }, + }; + + /** Gets the IsRunMode property */ + isRunMode = { + get: async (): Promise => { + return await this._client.invokeCapability( + 'Aspire.Hosting/DistributedApplicationExecutionContext.isRunMode', + { context: this._handle } + ); + }, + }; + +} + +// ============================================================================ +// EndpointReference +// ============================================================================ + +/** + * Type class for EndpointReference. + */ +export class EndpointReference { + constructor(private _handle: EndpointReferenceHandle, private _client: AspireClientRpc) {} + + /** Serialize for JSON-RPC transport */ + toJSON(): MarshalledHandle { return this._handle.toJSON(); } + + /** Gets the EndpointName property */ + endpointName = { + get: async (): Promise => { + return await this._client.invokeCapability( + 'Aspire.Hosting.ApplicationModel/EndpointReference.endpointName', + { context: this._handle } + ); + }, + }; + + /** Gets the ErrorMessage property */ + errorMessage = { + get: async (): Promise => { + return await this._client.invokeCapability( + 'Aspire.Hosting.ApplicationModel/EndpointReference.errorMessage', + { context: this._handle } + ); + }, + set: async (value: string): Promise => { + await this._client.invokeCapability( + 'Aspire.Hosting.ApplicationModel/EndpointReference.setErrorMessage', + { context: this._handle, value } + ); + } + }; + + /** Gets the IsAllocated property */ + isAllocated = { + get: async (): Promise => { + return await this._client.invokeCapability( + 'Aspire.Hosting.ApplicationModel/EndpointReference.isAllocated', + { context: this._handle } + ); + }, + }; + + /** Gets the Exists property */ + exists = { + get: async (): Promise => { + return await this._client.invokeCapability( + 'Aspire.Hosting.ApplicationModel/EndpointReference.exists', + { context: this._handle } + ); + }, + }; + + /** Gets the IsHttp property */ + isHttp = { + get: async (): Promise => { + return await this._client.invokeCapability( + 'Aspire.Hosting.ApplicationModel/EndpointReference.isHttp', + { context: this._handle } + ); + }, + }; + + /** Gets the IsHttps property */ + isHttps = { + get: async (): Promise => { + return await this._client.invokeCapability( + 'Aspire.Hosting.ApplicationModel/EndpointReference.isHttps', + { context: this._handle } + ); + }, + }; + + /** Gets the TlsEnabled property */ + tlsEnabled = { + get: async (): Promise => { + return await this._client.invokeCapability( + 'Aspire.Hosting.ApplicationModel/EndpointReference.tlsEnabled', + { context: this._handle } + ); + }, + }; + + /** Gets the Port property */ + port = { + get: async (): Promise => { + return await this._client.invokeCapability( + 'Aspire.Hosting.ApplicationModel/EndpointReference.port', + { context: this._handle } + ); + }, + }; + + /** Gets the TargetPort property */ + targetPort = { + get: async (): Promise => { + return await this._client.invokeCapability( + 'Aspire.Hosting.ApplicationModel/EndpointReference.targetPort', + { context: this._handle } + ); + }, + }; + + /** Gets the Host property */ + host = { + get: async (): Promise => { + return await this._client.invokeCapability( + 'Aspire.Hosting.ApplicationModel/EndpointReference.host', + { context: this._handle } + ); + }, + }; + + /** Gets the Scheme property */ + scheme = { + get: async (): Promise => { + return await this._client.invokeCapability( + 'Aspire.Hosting.ApplicationModel/EndpointReference.scheme', + { context: this._handle } + ); + }, + }; + + /** Gets the Url property */ + url = { + get: async (): Promise => { + return await this._client.invokeCapability( + 'Aspire.Hosting.ApplicationModel/EndpointReference.url', + { context: this._handle } + ); + }, + }; + + /** Gets the URL of the endpoint asynchronously */ + async getValueAsync(options?: GetValueAsyncOptions): Promise { + const cancellationToken = options?.cancellationToken; + const rpcArgs: Record = { context: this._handle }; + if (cancellationToken !== undefined) rpcArgs.cancellationToken = cancellationToken; + return await this._client.invokeCapability( + 'Aspire.Hosting.ApplicationModel/getValueAsync', + rpcArgs + ); + } + + /** Gets a conditional expression that resolves to the enabledValue when TLS is enabled on the endpoint, or to the disabledValue otherwise. */ + async getTlsValue(enabledValue: ReferenceExpression, disabledValue: ReferenceExpression): Promise { + const rpcArgs: Record = { context: this._handle, enabledValue, disabledValue }; + return await this._client.invokeCapability( + 'Aspire.Hosting.ApplicationModel/EndpointReference.getTlsValue', + rpcArgs + ); + } + +} + +/** + * Thenable wrapper for EndpointReference that enables fluent chaining. + */ +export class EndpointReferencePromise implements PromiseLike { + constructor(private _promise: Promise) {} + + then( + onfulfilled?: ((value: EndpointReference) => TResult1 | PromiseLike) | null, + onrejected?: ((reason: unknown) => TResult2 | PromiseLike) | null + ): PromiseLike { + return this._promise.then(onfulfilled, onrejected); + } + + /** Gets the URL of the endpoint asynchronously */ + getValueAsync(options?: GetValueAsyncOptions): Promise { + return this._promise.then(obj => obj.getValueAsync(options)); + } + + /** Gets a conditional expression that resolves to the enabledValue when TLS is enabled on the endpoint, or to the disabledValue otherwise. */ + getTlsValue(enabledValue: ReferenceExpression, disabledValue: ReferenceExpression): Promise { + return this._promise.then(obj => obj.getTlsValue(enabledValue, disabledValue)); + } + +} + +// ============================================================================ +// EndpointReferenceExpression +// ============================================================================ + +/** + * Type class for EndpointReferenceExpression. + */ +export class EndpointReferenceExpression { + constructor(private _handle: EndpointReferenceExpressionHandle, private _client: AspireClientRpc) {} + + /** Serialize for JSON-RPC transport */ + toJSON(): MarshalledHandle { return this._handle.toJSON(); } + + /** Gets the Endpoint property */ + endpoint = { + get: async (): Promise => { + const handle = await this._client.invokeCapability( + 'Aspire.Hosting.ApplicationModel/EndpointReferenceExpression.endpoint', + { context: this._handle } + ); + return new EndpointReference(handle, this._client); + }, + }; + + /** Gets the Property property */ + property = { + get: async (): Promise => { + return await this._client.invokeCapability( + 'Aspire.Hosting.ApplicationModel/EndpointReferenceExpression.property', + { context: this._handle } + ); + }, + }; + + /** Gets the ValueExpression property */ + valueExpression = { + get: async (): Promise => { + return await this._client.invokeCapability( + 'Aspire.Hosting.ApplicationModel/EndpointReferenceExpression.valueExpression', + { context: this._handle } + ); + }, + }; + +} + +// ============================================================================ +// EnvironmentCallbackContext +// ============================================================================ + +/** + * Type class for EnvironmentCallbackContext. + */ +export class EnvironmentCallbackContext { + constructor(private _handle: EnvironmentCallbackContextHandle, private _client: AspireClientRpc) {} + + /** Serialize for JSON-RPC transport */ + toJSON(): MarshalledHandle { return this._handle.toJSON(); } + + /** Gets the EnvironmentVariables property */ + private _environmentVariables?: AspireDict; + get environmentVariables(): AspireDict { + if (!this._environmentVariables) { + this._environmentVariables = new AspireDict( + this._handle, + this._client, + 'Aspire.Hosting.ApplicationModel/EnvironmentCallbackContext.environmentVariables', + 'Aspire.Hosting.ApplicationModel/EnvironmentCallbackContext.environmentVariables' + ); + } + return this._environmentVariables; + } + + /** Gets the CancellationToken property */ + cancellationToken = { + get: async (): Promise => { + return await this._client.invokeCapability( + 'Aspire.Hosting.ApplicationModel/EnvironmentCallbackContext.cancellationToken', + { context: this._handle } + ); + }, + }; + + /** Gets the ExecutionContext property */ + executionContext = { + get: async (): Promise => { + const handle = await this._client.invokeCapability( + 'Aspire.Hosting.ApplicationModel/EnvironmentCallbackContext.executionContext', + { context: this._handle } + ); + return new DistributedApplicationExecutionContext(handle, this._client); + }, + }; + +} + +// ============================================================================ +// ExecuteCommandContext +// ============================================================================ + +/** + * Type class for ExecuteCommandContext. + */ +export class ExecuteCommandContext { + constructor(private _handle: ExecuteCommandContextHandle, private _client: AspireClientRpc) {} + + /** Serialize for JSON-RPC transport */ + toJSON(): MarshalledHandle { return this._handle.toJSON(); } + + /** Gets the ResourceName property */ + resourceName = { + get: async (): Promise => { + return await this._client.invokeCapability( + 'Aspire.Hosting.ApplicationModel/ExecuteCommandContext.resourceName', + { context: this._handle } + ); + }, + set: async (value: string): Promise => { + await this._client.invokeCapability( + 'Aspire.Hosting.ApplicationModel/ExecuteCommandContext.setResourceName', + { context: this._handle, value } + ); + } + }; + + /** Gets the CancellationToken property */ + cancellationToken = { + get: async (): Promise => { + return await this._client.invokeCapability( + 'Aspire.Hosting.ApplicationModel/ExecuteCommandContext.cancellationToken', + { context: this._handle } + ); + }, + set: async (value: AbortSignal): Promise => { + await this._client.invokeCapability( + 'Aspire.Hosting.ApplicationModel/ExecuteCommandContext.setCancellationToken', + { context: this._handle, value } + ); + } + }; + +} + +// ============================================================================ +// PipelineConfigurationContext +// ============================================================================ + +/** + * Type class for PipelineConfigurationContext. + */ +export class PipelineConfigurationContext { + constructor(private _handle: PipelineConfigurationContextHandle, private _client: AspireClientRpc) {} + + /** Serialize for JSON-RPC transport */ + toJSON(): MarshalledHandle { return this._handle.toJSON(); } + + /** Gets the Steps property */ + steps = { + get: async (): Promise => { + return await this._client.invokeCapability( + 'Aspire.Hosting.Pipelines/PipelineConfigurationContext.steps', + { context: this._handle } + ); + }, + set: async (value: PipelineStep[]): Promise => { + await this._client.invokeCapability( + 'Aspire.Hosting.Pipelines/PipelineConfigurationContext.setSteps', + { context: this._handle, value } + ); + } + }; + + /** Gets pipeline steps with the specified tag */ + async getStepsByTag(tag: string): Promise { + const rpcArgs: Record = { context: this._handle, tag }; + return await this._client.invokeCapability( + 'Aspire.Hosting.Pipelines/getStepsByTag', + rpcArgs + ); + } + +} + +/** + * Thenable wrapper for PipelineConfigurationContext that enables fluent chaining. + */ +export class PipelineConfigurationContextPromise implements PromiseLike { + constructor(private _promise: Promise) {} + + then( + onfulfilled?: ((value: PipelineConfigurationContext) => TResult1 | PromiseLike) | null, + onrejected?: ((reason: unknown) => TResult2 | PromiseLike) | null + ): PromiseLike { + return this._promise.then(onfulfilled, onrejected); + } + + /** Gets pipeline steps with the specified tag */ + getStepsByTag(tag: string): Promise { + return this._promise.then(obj => obj.getStepsByTag(tag)); + } + +} + +// ============================================================================ +// PipelineStep +// ============================================================================ + +/** + * Type class for PipelineStep. + */ +export class PipelineStep { + constructor(private _handle: PipelineStepHandle, private _client: AspireClientRpc) {} + + /** Serialize for JSON-RPC transport */ + toJSON(): MarshalledHandle { return this._handle.toJSON(); } + + /** Gets the Name property */ + name = { + get: async (): Promise => { + return await this._client.invokeCapability( + 'Aspire.Hosting.Pipelines/PipelineStep.name', + { context: this._handle } + ); + }, + set: async (value: string): Promise => { + await this._client.invokeCapability( + 'Aspire.Hosting.Pipelines/PipelineStep.setName', + { context: this._handle, value } + ); + } + }; + + /** Gets the Description property */ + description = { + get: async (): Promise => { + return await this._client.invokeCapability( + 'Aspire.Hosting.Pipelines/PipelineStep.description', + { context: this._handle } + ); + }, + set: async (value: string): Promise => { + await this._client.invokeCapability( + 'Aspire.Hosting.Pipelines/PipelineStep.setDescription', + { context: this._handle, value } + ); + } + }; + + /** Gets the DependsOnSteps property */ + private _dependsOnSteps?: AspireList; + get dependsOnSteps(): AspireList { + if (!this._dependsOnSteps) { + this._dependsOnSteps = new AspireList( + this._handle, + this._client, + 'Aspire.Hosting.Pipelines/PipelineStep.dependsOnSteps', + 'Aspire.Hosting.Pipelines/PipelineStep.dependsOnSteps' + ); + } + return this._dependsOnSteps; + } + + /** Gets the RequiredBySteps property */ + private _requiredBySteps?: AspireList; + get requiredBySteps(): AspireList { + if (!this._requiredBySteps) { + this._requiredBySteps = new AspireList( + this._handle, + this._client, + 'Aspire.Hosting.Pipelines/PipelineStep.requiredBySteps', + 'Aspire.Hosting.Pipelines/PipelineStep.requiredBySteps' + ); + } + return this._requiredBySteps; + } + + /** Gets the Tags property */ + private _tags?: AspireList; + get tags(): AspireList { + if (!this._tags) { + this._tags = new AspireList( + this._handle, + this._client, + 'Aspire.Hosting.Pipelines/PipelineStep.tags', + 'Aspire.Hosting.Pipelines/PipelineStep.tags' + ); + } + return this._tags; + } + + /** Adds a dependency on another step by name */ + /** @internal */ + async _dependsOnInternal(stepName: string): Promise { + const rpcArgs: Record = { context: this._handle, stepName }; + await this._client.invokeCapability( + 'Aspire.Hosting.Pipelines/dependsOn', + rpcArgs + ); + return this; + } + + dependsOn(stepName: string): PipelineStepPromise { + return new PipelineStepPromise(this._dependsOnInternal(stepName)); + } + + /** Specifies that another step requires this step by name */ + /** @internal */ + async _requiredByInternal(stepName: string): Promise { + const rpcArgs: Record = { context: this._handle, stepName }; + await this._client.invokeCapability( + 'Aspire.Hosting.Pipelines/requiredBy', + rpcArgs + ); + return this; + } + + requiredBy(stepName: string): PipelineStepPromise { + return new PipelineStepPromise(this._requiredByInternal(stepName)); + } + +} + +/** + * Thenable wrapper for PipelineStep that enables fluent chaining. + */ +export class PipelineStepPromise implements PromiseLike { + constructor(private _promise: Promise) {} + + then( + onfulfilled?: ((value: PipelineStep) => TResult1 | PromiseLike) | null, + onrejected?: ((reason: unknown) => TResult2 | PromiseLike) | null + ): PromiseLike { + return this._promise.then(onfulfilled, onrejected); + } + + /** Adds a dependency on another step by name */ + dependsOn(stepName: string): PipelineStepPromise { + return new PipelineStepPromise(this._promise.then(obj => obj.dependsOn(stepName))); + } + + /** Specifies that another step requires this step by name */ + requiredBy(stepName: string): PipelineStepPromise { + return new PipelineStepPromise(this._promise.then(obj => obj.requiredBy(stepName))); + } + +} + +// ============================================================================ +// PipelineStepContext +// ============================================================================ + +/** + * Type class for PipelineStepContext. + */ +export class PipelineStepContext { + constructor(private _handle: PipelineStepContextHandle, private _client: AspireClientRpc) {} + + /** Serialize for JSON-RPC transport */ + toJSON(): MarshalledHandle { return this._handle.toJSON(); } + + /** Gets the ExecutionContext property */ + executionContext = { + get: async (): Promise => { + const handle = await this._client.invokeCapability( + 'Aspire.Hosting.Pipelines/PipelineStepContext.executionContext', + { context: this._handle } + ); + return new DistributedApplicationExecutionContext(handle, this._client); + }, + }; + + /** Gets the CancellationToken property */ + cancellationToken = { + get: async (): Promise => { + return await this._client.invokeCapability( + 'Aspire.Hosting.Pipelines/PipelineStepContext.cancellationToken', + { context: this._handle } + ); + }, + }; + +} + +// ============================================================================ +// ProjectResourceOptions +// ============================================================================ + +/** + * Type class for ProjectResourceOptions. + */ +export class ProjectResourceOptions { + constructor(private _handle: ProjectResourceOptionsHandle, private _client: AspireClientRpc) {} + + /** Serialize for JSON-RPC transport */ + toJSON(): MarshalledHandle { return this._handle.toJSON(); } + + /** Gets the LaunchProfileName property */ + launchProfileName = { + get: async (): Promise => { + return await this._client.invokeCapability( + 'Aspire.Hosting/ProjectResourceOptions.launchProfileName', + { context: this._handle } + ); + }, + set: async (value: string): Promise => { + await this._client.invokeCapability( + 'Aspire.Hosting/ProjectResourceOptions.setLaunchProfileName', + { context: this._handle, value } + ); + } + }; + + /** Gets the ExcludeLaunchProfile property */ + excludeLaunchProfile = { + get: async (): Promise => { + return await this._client.invokeCapability( + 'Aspire.Hosting/ProjectResourceOptions.excludeLaunchProfile', + { context: this._handle } + ); + }, + set: async (value: boolean): Promise => { + await this._client.invokeCapability( + 'Aspire.Hosting/ProjectResourceOptions.setExcludeLaunchProfile', + { context: this._handle, value } + ); + } + }; + + /** Gets the ExcludeKestrelEndpoints property */ + excludeKestrelEndpoints = { + get: async (): Promise => { + return await this._client.invokeCapability( + 'Aspire.Hosting/ProjectResourceOptions.excludeKestrelEndpoints', + { context: this._handle } + ); + }, + set: async (value: boolean): Promise => { + await this._client.invokeCapability( + 'Aspire.Hosting/ProjectResourceOptions.setExcludeKestrelEndpoints', + { context: this._handle, value } + ); + } + }; + +} + +// ============================================================================ +// ReferenceExpressionBuilder +// ============================================================================ + +/** + * Type class for ReferenceExpressionBuilder. + */ +export class ReferenceExpressionBuilder { + constructor(private _handle: ReferenceExpressionBuilderHandle, private _client: AspireClientRpc) {} + + /** Serialize for JSON-RPC transport */ + toJSON(): MarshalledHandle { return this._handle.toJSON(); } + + /** Gets the IsEmpty property */ + isEmpty = { + get: async (): Promise => { + return await this._client.invokeCapability( + 'Aspire.Hosting.ApplicationModel/ReferenceExpressionBuilder.isEmpty', + { context: this._handle } + ); + }, + }; + + /** Appends a literal string to the reference expression */ + /** @internal */ + async _appendLiteralInternal(value: string): Promise { + const rpcArgs: Record = { context: this._handle, value }; + await this._client.invokeCapability( + 'Aspire.Hosting.ApplicationModel/appendLiteral', + rpcArgs + ); + return this; + } + + appendLiteral(value: string): ReferenceExpressionBuilderPromise { + return new ReferenceExpressionBuilderPromise(this._appendLiteralInternal(value)); + } + + /** Appends a formatted string value to the reference expression */ + /** @internal */ + async _appendFormattedInternal(value: string, format?: string): Promise { + const rpcArgs: Record = { context: this._handle, value }; + if (format !== undefined) rpcArgs.format = format; + await this._client.invokeCapability( + 'Aspire.Hosting.ApplicationModel/appendFormatted', + rpcArgs + ); + return this; + } + + appendFormatted(value: string, options?: AppendFormattedOptions): ReferenceExpressionBuilderPromise { + const format = options?.format; + return new ReferenceExpressionBuilderPromise(this._appendFormattedInternal(value, format)); + } + + /** Appends a value provider to the reference expression */ + /** @internal */ + async _appendValueProviderInternal(valueProvider: any, format?: string): Promise { + const rpcArgs: Record = { context: this._handle, valueProvider }; + if (format !== undefined) rpcArgs.format = format; + await this._client.invokeCapability( + 'Aspire.Hosting.ApplicationModel/appendValueProvider', + rpcArgs + ); + return this; + } + + appendValueProvider(valueProvider: any, options?: AppendValueProviderOptions): ReferenceExpressionBuilderPromise { + const format = options?.format; + return new ReferenceExpressionBuilderPromise(this._appendValueProviderInternal(valueProvider, format)); + } + + /** Builds the reference expression */ + async build(): Promise { + const rpcArgs: Record = { context: this._handle }; + return await this._client.invokeCapability( + 'Aspire.Hosting.ApplicationModel/build', + rpcArgs + ); + } + +} + +/** + * Thenable wrapper for ReferenceExpressionBuilder that enables fluent chaining. + */ +export class ReferenceExpressionBuilderPromise implements PromiseLike { + constructor(private _promise: Promise) {} + + then( + onfulfilled?: ((value: ReferenceExpressionBuilder) => TResult1 | PromiseLike) | null, + onrejected?: ((reason: unknown) => TResult2 | PromiseLike) | null + ): PromiseLike { + return this._promise.then(onfulfilled, onrejected); + } + + /** Appends a literal string to the reference expression */ + appendLiteral(value: string): ReferenceExpressionBuilderPromise { + return new ReferenceExpressionBuilderPromise(this._promise.then(obj => obj.appendLiteral(value))); + } + + /** Appends a formatted string value to the reference expression */ + appendFormatted(value: string, options?: AppendFormattedOptions): ReferenceExpressionBuilderPromise { + return new ReferenceExpressionBuilderPromise(this._promise.then(obj => obj.appendFormatted(value, options))); + } + + /** Appends a value provider to the reference expression */ + appendValueProvider(valueProvider: any, options?: AppendValueProviderOptions): ReferenceExpressionBuilderPromise { + return new ReferenceExpressionBuilderPromise(this._promise.then(obj => obj.appendValueProvider(valueProvider, options))); + } + + /** Builds the reference expression */ + build(): Promise { + return this._promise.then(obj => obj.build()); + } + +} + +// ============================================================================ +// ResourceUrlsCallbackContext +// ============================================================================ + +/** + * Type class for ResourceUrlsCallbackContext. + */ +export class ResourceUrlsCallbackContext { + constructor(private _handle: ResourceUrlsCallbackContextHandle, private _client: AspireClientRpc) {} + + /** Serialize for JSON-RPC transport */ + toJSON(): MarshalledHandle { return this._handle.toJSON(); } + + /** Gets the Urls property */ + private _urls?: AspireList; + get urls(): AspireList { + if (!this._urls) { + this._urls = new AspireList( + this._handle, + this._client, + 'Aspire.Hosting.ApplicationModel/ResourceUrlsCallbackContext.urls', + 'Aspire.Hosting.ApplicationModel/ResourceUrlsCallbackContext.urls' + ); + } + return this._urls; + } + + /** Gets the CancellationToken property */ + cancellationToken = { + get: async (): Promise => { + return await this._client.invokeCapability( + 'Aspire.Hosting.ApplicationModel/ResourceUrlsCallbackContext.cancellationToken', + { context: this._handle } + ); + }, + }; + + /** Gets the ExecutionContext property */ + executionContext = { + get: async (): Promise => { + const handle = await this._client.invokeCapability( + 'Aspire.Hosting.ApplicationModel/ResourceUrlsCallbackContext.executionContext', + { context: this._handle } + ); + return new DistributedApplicationExecutionContext(handle, this._client); + }, + }; + +} + +// ============================================================================ +// DistributedApplicationBuilder +// ============================================================================ + +/** + * Type class for DistributedApplicationBuilder. + */ +export class DistributedApplicationBuilder { + constructor(private _handle: IDistributedApplicationBuilderHandle, private _client: AspireClientRpc) {} + + /** Serialize for JSON-RPC transport */ + toJSON(): MarshalledHandle { return this._handle.toJSON(); } + + /** Gets the AppHostDirectory property */ + appHostDirectory = { + get: async (): Promise => { + return await this._client.invokeCapability( + 'Aspire.Hosting/IDistributedApplicationBuilder.appHostDirectory', + { context: this._handle } + ); + }, + }; + + /** Gets the Eventing property */ + eventing = { + get: async (): Promise => { + const handle = await this._client.invokeCapability( + 'Aspire.Hosting/IDistributedApplicationBuilder.eventing', + { context: this._handle } + ); + return new DistributedApplicationEventing(handle, this._client); + }, + }; + + /** Gets the ExecutionContext property */ + executionContext = { + get: async (): Promise => { + const handle = await this._client.invokeCapability( + 'Aspire.Hosting/IDistributedApplicationBuilder.executionContext', + { context: this._handle } + ); + return new DistributedApplicationExecutionContext(handle, this._client); + }, + }; + + /** Builds the distributed application */ + /** @internal */ + async _buildInternal(): Promise { + const rpcArgs: Record = { context: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/build', + rpcArgs + ); + return new DistributedApplication(result, this._client); + } + + build(): DistributedApplicationPromise { + return new DistributedApplicationPromise(this._buildInternal()); + } + + /** Adds a connection string with a builder callback */ + /** @internal */ + async _addConnectionStringBuilderInternal(name: string, connectionStringBuilder: (obj: ReferenceExpressionBuilder) => Promise): Promise { + const connectionStringBuilderId = registerCallback(async (objData: unknown) => { + const objHandle = wrapIfHandle(objData) as ReferenceExpressionBuilderHandle; + const obj = new ReferenceExpressionBuilder(objHandle, this._client); + await connectionStringBuilder(obj); + }); + const rpcArgs: Record = { builder: this._handle, name, connectionStringBuilder: connectionStringBuilderId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/addConnectionStringBuilder', + rpcArgs + ); + return new ConnectionStringResource(result, this._client); + } + + addConnectionStringBuilder(name: string, connectionStringBuilder: (obj: ReferenceExpressionBuilder) => Promise): ConnectionStringResourcePromise { + return new ConnectionStringResourcePromise(this._addConnectionStringBuilderInternal(name, connectionStringBuilder)); + } + + /** Adds a container registry resource */ + /** @internal */ + async _addContainerRegistryInternal(name: string, endpoint: ParameterResource, repository?: ParameterResource): Promise { + const rpcArgs: Record = { builder: this._handle, name, endpoint }; + if (repository !== undefined) rpcArgs.repository = repository; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/addContainerRegistry', + rpcArgs + ); + return new ContainerRegistryResource(result, this._client); + } + + addContainerRegistry(name: string, endpoint: ParameterResource, options?: AddContainerRegistryOptions): ContainerRegistryResourcePromise { + const repository = options?.repository; + return new ContainerRegistryResourcePromise(this._addContainerRegistryInternal(name, endpoint, repository)); + } + + /** Adds a container resource */ + /** @internal */ + async _addContainerInternal(name: string, image: string): Promise { + const rpcArgs: Record = { builder: this._handle, name, image }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/addContainer', + rpcArgs + ); + return new ContainerResource(result, this._client); + } + + addContainer(name: string, image: string): ContainerResourcePromise { + return new ContainerResourcePromise(this._addContainerInternal(name, image)); + } + + /** Adds a container resource built from a Dockerfile */ + /** @internal */ + async _addDockerfileInternal(name: string, contextPath: string, dockerfilePath?: string, stage?: string): Promise { + const rpcArgs: Record = { builder: this._handle, name, contextPath }; + if (dockerfilePath !== undefined) rpcArgs.dockerfilePath = dockerfilePath; + if (stage !== undefined) rpcArgs.stage = stage; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/addDockerfile', + rpcArgs + ); + return new ContainerResource(result, this._client); + } + + addDockerfile(name: string, contextPath: string, options?: AddDockerfileOptions): ContainerResourcePromise { + const dockerfilePath = options?.dockerfilePath; + const stage = options?.stage; + return new ContainerResourcePromise(this._addDockerfileInternal(name, contextPath, dockerfilePath, stage)); + } + + /** Adds a .NET tool resource */ + /** @internal */ + async _addDotnetToolInternal(name: string, packageId: string): Promise { + const rpcArgs: Record = { builder: this._handle, name, packageId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/addDotnetTool', + rpcArgs + ); + return new DotnetToolResource(result, this._client); + } + + addDotnetTool(name: string, packageId: string): DotnetToolResourcePromise { + return new DotnetToolResourcePromise(this._addDotnetToolInternal(name, packageId)); + } + + /** Adds an executable resource */ + /** @internal */ + async _addExecutableInternal(name: string, command: string, workingDirectory: string, args: string[]): Promise { + const rpcArgs: Record = { builder: this._handle, name, command, workingDirectory, args }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/addExecutable', + rpcArgs + ); + return new ExecutableResource(result, this._client); + } + + addExecutable(name: string, command: string, workingDirectory: string, args: string[]): ExecutableResourcePromise { + return new ExecutableResourcePromise(this._addExecutableInternal(name, command, workingDirectory, args)); + } + + /** Adds an external service resource */ + /** @internal */ + async _addExternalServiceInternal(name: string, url: string): Promise { + const rpcArgs: Record = { builder: this._handle, name, url }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/addExternalService', + rpcArgs + ); + return new ExternalServiceResource(result, this._client); + } + + addExternalService(name: string, url: string): ExternalServiceResourcePromise { + return new ExternalServiceResourcePromise(this._addExternalServiceInternal(name, url)); + } + + /** Adds a parameter resource */ + /** @internal */ + async _addParameterInternal(name: string, secret?: boolean): Promise { + const rpcArgs: Record = { builder: this._handle, name }; + if (secret !== undefined) rpcArgs.secret = secret; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/addParameter', + rpcArgs + ); + return new ParameterResource(result, this._client); + } + + addParameter(name: string, options?: AddParameterOptions): ParameterResourcePromise { + const secret = options?.secret; + return new ParameterResourcePromise(this._addParameterInternal(name, secret)); + } + + /** Adds a parameter sourced from configuration */ + /** @internal */ + async _addParameterFromConfigurationInternal(name: string, configurationKey: string, secret?: boolean): Promise { + const rpcArgs: Record = { builder: this._handle, name, configurationKey }; + if (secret !== undefined) rpcArgs.secret = secret; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/addParameterFromConfiguration', + rpcArgs + ); + return new ParameterResource(result, this._client); + } + + addParameterFromConfiguration(name: string, configurationKey: string, options?: AddParameterFromConfigurationOptions): ParameterResourcePromise { + const secret = options?.secret; + return new ParameterResourcePromise(this._addParameterFromConfigurationInternal(name, configurationKey, secret)); + } + + /** Adds a connection string resource */ + /** @internal */ + async _addConnectionStringInternal(name: string, environmentVariableName?: string): Promise { + const rpcArgs: Record = { builder: this._handle, name }; + if (environmentVariableName !== undefined) rpcArgs.environmentVariableName = environmentVariableName; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/addConnectionString', + rpcArgs + ); + return new ResourceWithConnectionString(result, this._client); + } + + addConnectionString(name: string, options?: AddConnectionStringOptions): ResourceWithConnectionStringPromise { + const environmentVariableName = options?.environmentVariableName; + return new ResourceWithConnectionStringPromise(this._addConnectionStringInternal(name, environmentVariableName)); + } + + /** Adds a .NET project resource */ + /** @internal */ + async _addProjectInternal(name: string, projectPath: string, launchProfileName: string): Promise { + const rpcArgs: Record = { builder: this._handle, name, projectPath, launchProfileName }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/addProject', + rpcArgs + ); + return new ProjectResource(result, this._client); + } + + addProject(name: string, projectPath: string, launchProfileName: string): ProjectResourcePromise { + return new ProjectResourcePromise(this._addProjectInternal(name, projectPath, launchProfileName)); + } + + /** Adds a project resource with configuration options */ + /** @internal */ + async _addProjectWithOptionsInternal(name: string, projectPath: string, configure: (obj: ProjectResourceOptions) => Promise): Promise { + const configureId = registerCallback(async (objData: unknown) => { + const objHandle = wrapIfHandle(objData) as ProjectResourceOptionsHandle; + const obj = new ProjectResourceOptions(objHandle, this._client); + await configure(obj); + }); + const rpcArgs: Record = { builder: this._handle, name, projectPath, configure: configureId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/addProjectWithOptions', + rpcArgs + ); + return new ProjectResource(result, this._client); + } + + addProjectWithOptions(name: string, projectPath: string, configure: (obj: ProjectResourceOptions) => Promise): ProjectResourcePromise { + return new ProjectResourcePromise(this._addProjectWithOptionsInternal(name, projectPath, configure)); + } + + /** Adds a C# application resource */ + /** @internal */ + async _addCSharpAppInternal(name: string, path: string): Promise { + const rpcArgs: Record = { builder: this._handle, name, path }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/addCSharpApp', + rpcArgs + ); + return new ProjectResource(result, this._client); + } + + addCSharpApp(name: string, path: string): ProjectResourcePromise { + return new ProjectResourcePromise(this._addCSharpAppInternal(name, path)); + } + + /** Adds a C# application resource with configuration options */ + /** @internal */ + async _addCSharpAppWithOptionsInternal(name: string, path: string, configure: (obj: ProjectResourceOptions) => Promise): Promise { + const configureId = registerCallback(async (objData: unknown) => { + const objHandle = wrapIfHandle(objData) as ProjectResourceOptionsHandle; + const obj = new ProjectResourceOptions(objHandle, this._client); + await configure(obj); + }); + const rpcArgs: Record = { builder: this._handle, name, path, configure: configureId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/addCSharpAppWithOptions', + rpcArgs + ); + return new CSharpAppResource(result, this._client); + } + + addCSharpAppWithOptions(name: string, path: string, configure: (obj: ProjectResourceOptions) => Promise): CSharpAppResourcePromise { + return new CSharpAppResourcePromise(this._addCSharpAppWithOptionsInternal(name, path, configure)); + } + + /** Adds an Azure Storage resource */ + /** @internal */ + async _addAzureStorageInternal(name: string): Promise { + const rpcArgs: Record = { builder: this._handle, name }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure.Storage/addAzureStorage', + rpcArgs + ); + return new AzureStorageResource(result, this._client); + } + + addAzureStorage(name: string): AzureStorageResourcePromise { + return new AzureStorageResourcePromise(this._addAzureStorageInternal(name)); + } + + /** Adds an Azure Event Hubs namespace resource */ + /** @internal */ + async _addAzureEventHubsInternal(name: string): Promise { + const rpcArgs: Record = { builder: this._handle, name }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure.EventHubs/addAzureEventHubs', + rpcArgs + ); + return new AzureEventHubsResource(result, this._client); + } + + addAzureEventHubs(name: string): AzureEventHubsResourcePromise { + return new AzureEventHubsResourcePromise(this._addAzureEventHubsInternal(name)); + } + + /** Adds a Node.js application resource */ + /** @internal */ + async _addNodeAppInternal(name: string, appDirectory: string, scriptPath: string): Promise { + const rpcArgs: Record = { builder: this._handle, name, appDirectory, scriptPath }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.JavaScript/addNodeApp', + rpcArgs + ); + return new NodeAppResource(result, this._client); + } + + addNodeApp(name: string, appDirectory: string, scriptPath: string): NodeAppResourcePromise { + return new NodeAppResourcePromise(this._addNodeAppInternal(name, appDirectory, scriptPath)); + } + + /** Adds a JavaScript application resource */ + /** @internal */ + async _addJavaScriptAppInternal(name: string, appDirectory: string, runScriptName?: string): Promise { + const rpcArgs: Record = { builder: this._handle, name, appDirectory }; + if (runScriptName !== undefined) rpcArgs.runScriptName = runScriptName; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.JavaScript/addJavaScriptApp', + rpcArgs + ); + return new JavaScriptAppResource(result, this._client); + } + + addJavaScriptApp(name: string, appDirectory: string, options?: AddJavaScriptAppOptions): JavaScriptAppResourcePromise { + const runScriptName = options?.runScriptName; + return new JavaScriptAppResourcePromise(this._addJavaScriptAppInternal(name, appDirectory, runScriptName)); + } + + /** Adds a Vite application resource */ + /** @internal */ + async _addViteAppInternal(name: string, appDirectory: string, runScriptName?: string): Promise { + const rpcArgs: Record = { builder: this._handle, name, appDirectory }; + if (runScriptName !== undefined) rpcArgs.runScriptName = runScriptName; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.JavaScript/addViteApp', + rpcArgs + ); + return new ViteAppResource(result, this._client); + } + + addViteApp(name: string, appDirectory: string, options?: AddViteAppOptions): ViteAppResourcePromise { + const runScriptName = options?.runScriptName; + return new ViteAppResourcePromise(this._addViteAppInternal(name, appDirectory, runScriptName)); + } + + /** Adds an Azure Bicep template resource from a file */ + /** @internal */ + async _addBicepTemplateInternal(name: string, bicepFile: string): Promise { + const rpcArgs: Record = { builder: this._handle, name, bicepFile }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure/addBicepTemplate', + rpcArgs + ); + return new AzureBicepResource(result, this._client); + } + + addBicepTemplate(name: string, bicepFile: string): AzureBicepResourcePromise { + return new AzureBicepResourcePromise(this._addBicepTemplateInternal(name, bicepFile)); + } + + /** Adds an Azure Bicep template resource from inline Bicep content */ + /** @internal */ + async _addBicepTemplateStringInternal(name: string, bicepContent: string): Promise { + const rpcArgs: Record = { builder: this._handle, name, bicepContent }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure/addBicepTemplateString', + rpcArgs + ); + return new AzureBicepResource(result, this._client); + } + + addBicepTemplateString(name: string, bicepContent: string): AzureBicepResourcePromise { + return new AzureBicepResourcePromise(this._addBicepTemplateStringInternal(name, bicepContent)); + } + + /** Adds an Azure provisioning resource to the application model */ + /** @internal */ + async _addAzureInfrastructureInternal(name: string, configureInfrastructure: (obj: AzureResourceInfrastructure) => Promise): Promise { + const configureInfrastructureId = registerCallback(async (objData: unknown) => { + const objHandle = wrapIfHandle(objData) as AzureResourceInfrastructureHandle; + const obj = new AzureResourceInfrastructure(objHandle, this._client); + await configureInfrastructure(obj); + }); + const rpcArgs: Record = { builder: this._handle, name, configureInfrastructure: configureInfrastructureId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure/addAzureInfrastructure', + rpcArgs + ); + return new AzureProvisioningResource(result, this._client); + } + + addAzureInfrastructure(name: string, configureInfrastructure: (obj: AzureResourceInfrastructure) => Promise): AzureProvisioningResourcePromise { + return new AzureProvisioningResourcePromise(this._addAzureInfrastructureInternal(name, configureInfrastructure)); + } + + /** Adds Azure provisioning services to the distributed application builder */ + /** @internal */ + async _addAzureProvisioningInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure/addAzureProvisioning', + rpcArgs + ); + return new DistributedApplicationBuilder(result, this._client); + } + + addAzureProvisioning(): DistributedApplicationBuilderPromise { + return new DistributedApplicationBuilderPromise(this._addAzureProvisioningInternal()); + } + + /** Adds the shared Azure environment resource to the application model */ + /** @internal */ + async _addAzureEnvironmentInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure/addAzureEnvironment', + rpcArgs + ); + return new AzureEnvironmentResource(result, this._client); + } + + addAzureEnvironment(): AzureEnvironmentResourcePromise { + return new AzureEnvironmentResourcePromise(this._addAzureEnvironmentInternal()); + } + + /** Adds an Azure user-assigned identity resource */ + /** @internal */ + async _addAzureUserAssignedIdentityInternal(name: string): Promise { + const rpcArgs: Record = { builder: this._handle, name }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure/addAzureUserAssignedIdentity', + rpcArgs + ); + return new AzureUserAssignedIdentityResource(result, this._client); + } + + addAzureUserAssignedIdentity(name: string): AzureUserAssignedIdentityResourcePromise { + return new AzureUserAssignedIdentityResourcePromise(this._addAzureUserAssignedIdentityInternal(name)); + } + +} + +/** + * Thenable wrapper for DistributedApplicationBuilder that enables fluent chaining. + */ +export class DistributedApplicationBuilderPromise implements PromiseLike { + constructor(private _promise: Promise) {} + + then( + onfulfilled?: ((value: DistributedApplicationBuilder) => TResult1 | PromiseLike) | null, + onrejected?: ((reason: unknown) => TResult2 | PromiseLike) | null + ): PromiseLike { + return this._promise.then(onfulfilled, onrejected); + } + + /** Builds the distributed application */ + build(): DistributedApplicationPromise { + return new DistributedApplicationPromise(this._promise.then(obj => obj.build())); + } + + /** Adds a connection string with a builder callback */ + addConnectionStringBuilder(name: string, connectionStringBuilder: (obj: ReferenceExpressionBuilder) => Promise): ConnectionStringResourcePromise { + return new ConnectionStringResourcePromise(this._promise.then(obj => obj.addConnectionStringBuilder(name, connectionStringBuilder))); + } + + /** Adds a container registry resource */ + addContainerRegistry(name: string, endpoint: ParameterResource, options?: AddContainerRegistryOptions): ContainerRegistryResourcePromise { + return new ContainerRegistryResourcePromise(this._promise.then(obj => obj.addContainerRegistry(name, endpoint, options))); + } + + /** Adds a container resource */ + addContainer(name: string, image: string): ContainerResourcePromise { + return new ContainerResourcePromise(this._promise.then(obj => obj.addContainer(name, image))); + } + + /** Adds a container resource built from a Dockerfile */ + addDockerfile(name: string, contextPath: string, options?: AddDockerfileOptions): ContainerResourcePromise { + return new ContainerResourcePromise(this._promise.then(obj => obj.addDockerfile(name, contextPath, options))); + } + + /** Adds a .NET tool resource */ + addDotnetTool(name: string, packageId: string): DotnetToolResourcePromise { + return new DotnetToolResourcePromise(this._promise.then(obj => obj.addDotnetTool(name, packageId))); + } + + /** Adds an executable resource */ + addExecutable(name: string, command: string, workingDirectory: string, args: string[]): ExecutableResourcePromise { + return new ExecutableResourcePromise(this._promise.then(obj => obj.addExecutable(name, command, workingDirectory, args))); + } + + /** Adds an external service resource */ + addExternalService(name: string, url: string): ExternalServiceResourcePromise { + return new ExternalServiceResourcePromise(this._promise.then(obj => obj.addExternalService(name, url))); + } + + /** Adds a parameter resource */ + addParameter(name: string, options?: AddParameterOptions): ParameterResourcePromise { + return new ParameterResourcePromise(this._promise.then(obj => obj.addParameter(name, options))); + } + + /** Adds a parameter sourced from configuration */ + addParameterFromConfiguration(name: string, configurationKey: string, options?: AddParameterFromConfigurationOptions): ParameterResourcePromise { + return new ParameterResourcePromise(this._promise.then(obj => obj.addParameterFromConfiguration(name, configurationKey, options))); + } + + /** Adds a connection string resource */ + addConnectionString(name: string, options?: AddConnectionStringOptions): ResourceWithConnectionStringPromise { + return new ResourceWithConnectionStringPromise(this._promise.then(obj => obj.addConnectionString(name, options))); + } + + /** Adds a .NET project resource */ + addProject(name: string, projectPath: string, launchProfileName: string): ProjectResourcePromise { + return new ProjectResourcePromise(this._promise.then(obj => obj.addProject(name, projectPath, launchProfileName))); + } + + /** Adds a project resource with configuration options */ + addProjectWithOptions(name: string, projectPath: string, configure: (obj: ProjectResourceOptions) => Promise): ProjectResourcePromise { + return new ProjectResourcePromise(this._promise.then(obj => obj.addProjectWithOptions(name, projectPath, configure))); + } + + /** Adds a C# application resource */ + addCSharpApp(name: string, path: string): ProjectResourcePromise { + return new ProjectResourcePromise(this._promise.then(obj => obj.addCSharpApp(name, path))); + } + + /** Adds a C# application resource with configuration options */ + addCSharpAppWithOptions(name: string, path: string, configure: (obj: ProjectResourceOptions) => Promise): CSharpAppResourcePromise { + return new CSharpAppResourcePromise(this._promise.then(obj => obj.addCSharpAppWithOptions(name, path, configure))); + } + + /** Adds an Azure Storage resource */ + addAzureStorage(name: string): AzureStorageResourcePromise { + return new AzureStorageResourcePromise(this._promise.then(obj => obj.addAzureStorage(name))); + } + + /** Adds an Azure Event Hubs namespace resource */ + addAzureEventHubs(name: string): AzureEventHubsResourcePromise { + return new AzureEventHubsResourcePromise(this._promise.then(obj => obj.addAzureEventHubs(name))); + } + + /** Adds a Node.js application resource */ + addNodeApp(name: string, appDirectory: string, scriptPath: string): NodeAppResourcePromise { + return new NodeAppResourcePromise(this._promise.then(obj => obj.addNodeApp(name, appDirectory, scriptPath))); + } + + /** Adds a JavaScript application resource */ + addJavaScriptApp(name: string, appDirectory: string, options?: AddJavaScriptAppOptions): JavaScriptAppResourcePromise { + return new JavaScriptAppResourcePromise(this._promise.then(obj => obj.addJavaScriptApp(name, appDirectory, options))); + } + + /** Adds a Vite application resource */ + addViteApp(name: string, appDirectory: string, options?: AddViteAppOptions): ViteAppResourcePromise { + return new ViteAppResourcePromise(this._promise.then(obj => obj.addViteApp(name, appDirectory, options))); + } + + /** Adds an Azure Bicep template resource from a file */ + addBicepTemplate(name: string, bicepFile: string): AzureBicepResourcePromise { + return new AzureBicepResourcePromise(this._promise.then(obj => obj.addBicepTemplate(name, bicepFile))); + } + + /** Adds an Azure Bicep template resource from inline Bicep content */ + addBicepTemplateString(name: string, bicepContent: string): AzureBicepResourcePromise { + return new AzureBicepResourcePromise(this._promise.then(obj => obj.addBicepTemplateString(name, bicepContent))); + } + + /** Adds an Azure provisioning resource to the application model */ + addAzureInfrastructure(name: string, configureInfrastructure: (obj: AzureResourceInfrastructure) => Promise): AzureProvisioningResourcePromise { + return new AzureProvisioningResourcePromise(this._promise.then(obj => obj.addAzureInfrastructure(name, configureInfrastructure))); + } + + /** Adds Azure provisioning services to the distributed application builder */ + addAzureProvisioning(): DistributedApplicationBuilderPromise { + return new DistributedApplicationBuilderPromise(this._promise.then(obj => obj.addAzureProvisioning())); + } + + /** Adds the shared Azure environment resource to the application model */ + addAzureEnvironment(): AzureEnvironmentResourcePromise { + return new AzureEnvironmentResourcePromise(this._promise.then(obj => obj.addAzureEnvironment())); + } + + /** Adds an Azure user-assigned identity resource */ + addAzureUserAssignedIdentity(name: string): AzureUserAssignedIdentityResourcePromise { + return new AzureUserAssignedIdentityResourcePromise(this._promise.then(obj => obj.addAzureUserAssignedIdentity(name))); + } + +} + +// ============================================================================ +// DistributedApplicationEventing +// ============================================================================ + +/** + * Type class for DistributedApplicationEventing. + */ +export class DistributedApplicationEventing { + constructor(private _handle: IDistributedApplicationEventingHandle, private _client: AspireClientRpc) {} + + /** Serialize for JSON-RPC transport */ + toJSON(): MarshalledHandle { return this._handle.toJSON(); } + + /** Invokes the Unsubscribe method */ + /** @internal */ + async _unsubscribeInternal(subscription: DistributedApplicationEventSubscriptionHandle): Promise { + const rpcArgs: Record = { context: this._handle, subscription }; + await this._client.invokeCapability( + 'Aspire.Hosting.Eventing/IDistributedApplicationEventing.unsubscribe', + rpcArgs + ); + return this; + } + + unsubscribe(subscription: DistributedApplicationEventSubscriptionHandle): DistributedApplicationEventingPromise { + return new DistributedApplicationEventingPromise(this._unsubscribeInternal(subscription)); + } + +} + +/** + * Thenable wrapper for DistributedApplicationEventing that enables fluent chaining. + */ +export class DistributedApplicationEventingPromise implements PromiseLike { + constructor(private _promise: Promise) {} + + then( + onfulfilled?: ((value: DistributedApplicationEventing) => TResult1 | PromiseLike) | null, + onrejected?: ((reason: unknown) => TResult2 | PromiseLike) | null + ): PromiseLike { + return this._promise.then(onfulfilled, onrejected); + } + + /** Invokes the Unsubscribe method */ + unsubscribe(subscription: DistributedApplicationEventSubscriptionHandle): DistributedApplicationEventingPromise { + return new DistributedApplicationEventingPromise(this._promise.then(obj => obj.unsubscribe(subscription))); + } + +} + +// ============================================================================ +// AzureBicepResource +// ============================================================================ + +export class AzureBicepResource extends ResourceBuilderBase { + constructor(handle: AzureBicepResourceHandle, client: AspireClientRpc) { + super(handle, client); + } + + /** @internal */ + private async _withContainerRegistryInternal(registry: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, registry }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withContainerRegistry', + rpcArgs + ); + return new AzureBicepResource(result, this._client); + } + + /** Configures a resource to use a container registry */ + withContainerRegistry(registry: ResourceBuilderBase): AzureBicepResourcePromise { + return new AzureBicepResourcePromise(this._withContainerRegistryInternal(registry)); + } + + /** @internal */ + private async _withDockerfileBaseImageInternal(buildImage?: string, runtimeImage?: string): Promise { + const rpcArgs: Record = { builder: this._handle }; + if (buildImage !== undefined) rpcArgs.buildImage = buildImage; + if (runtimeImage !== undefined) rpcArgs.runtimeImage = runtimeImage; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withDockerfileBaseImage', + rpcArgs + ); + return new AzureBicepResource(result, this._client); + } + + /** Sets the base image for a Dockerfile build */ + withDockerfileBaseImage(options?: WithDockerfileBaseImageOptions): AzureBicepResourcePromise { + const buildImage = options?.buildImage; + const runtimeImage = options?.runtimeImage; + return new AzureBicepResourcePromise(this._withDockerfileBaseImageInternal(buildImage, runtimeImage)); + } + + /** @internal */ + private async _withRequiredCommandInternal(command: string, helpLink?: string): Promise { + const rpcArgs: Record = { builder: this._handle, command }; + if (helpLink !== undefined) rpcArgs.helpLink = helpLink; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withRequiredCommand', + rpcArgs + ); + return new AzureBicepResource(result, this._client); + } + + /** Adds a required command dependency */ + withRequiredCommand(command: string, options?: WithRequiredCommandOptions): AzureBicepResourcePromise { + const helpLink = options?.helpLink; + return new AzureBicepResourcePromise(this._withRequiredCommandInternal(command, helpLink)); + } + + /** @internal */ + private async _withUrlsCallbackInternal(callback: (obj: ResourceUrlsCallbackContext) => Promise): Promise { + const callbackId = registerCallback(async (objData: unknown) => { + const objHandle = wrapIfHandle(objData) as ResourceUrlsCallbackContextHandle; + const obj = new ResourceUrlsCallbackContext(objHandle, this._client); + await callback(obj); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrlsCallback', + rpcArgs + ); + return new AzureBicepResource(result, this._client); + } + + /** Customizes displayed URLs via callback */ + withUrlsCallback(callback: (obj: ResourceUrlsCallbackContext) => Promise): AzureBicepResourcePromise { + return new AzureBicepResourcePromise(this._withUrlsCallbackInternal(callback)); + } + + /** @internal */ + private async _withUrlsCallbackAsyncInternal(callback: (arg: ResourceUrlsCallbackContext) => Promise): Promise { + const callbackId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as ResourceUrlsCallbackContextHandle; + const arg = new ResourceUrlsCallbackContext(argHandle, this._client); + await callback(arg); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrlsCallbackAsync', + rpcArgs + ); + return new AzureBicepResource(result, this._client); + } + + /** Customizes displayed URLs via async callback */ + withUrlsCallbackAsync(callback: (arg: ResourceUrlsCallbackContext) => Promise): AzureBicepResourcePromise { + return new AzureBicepResourcePromise(this._withUrlsCallbackAsyncInternal(callback)); + } + + /** @internal */ + private async _withUrlInternal(url: string, displayText?: string): Promise { + const rpcArgs: Record = { builder: this._handle, url }; + if (displayText !== undefined) rpcArgs.displayText = displayText; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrl', + rpcArgs + ); + return new AzureBicepResource(result, this._client); + } + + /** Adds or modifies displayed URLs */ + withUrl(url: string, options?: WithUrlOptions): AzureBicepResourcePromise { + const displayText = options?.displayText; + return new AzureBicepResourcePromise(this._withUrlInternal(url, displayText)); + } + + /** @internal */ + private async _withUrlExpressionInternal(url: ReferenceExpression, displayText?: string): Promise { + const rpcArgs: Record = { builder: this._handle, url }; + if (displayText !== undefined) rpcArgs.displayText = displayText; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrlExpression', + rpcArgs + ); + return new AzureBicepResource(result, this._client); + } + + /** Adds a URL using a reference expression */ + withUrlExpression(url: ReferenceExpression, options?: WithUrlExpressionOptions): AzureBicepResourcePromise { + const displayText = options?.displayText; + return new AzureBicepResourcePromise(this._withUrlExpressionInternal(url, displayText)); + } + + /** @internal */ + private async _withUrlForEndpointInternal(endpointName: string, callback: (obj: ResourceUrlAnnotation) => Promise): Promise { + const callbackId = registerCallback(async (objData: unknown) => { + const obj = wrapIfHandle(objData) as ResourceUrlAnnotation; + await callback(obj); + }); + const rpcArgs: Record = { builder: this._handle, endpointName, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrlForEndpoint', + rpcArgs + ); + return new AzureBicepResource(result, this._client); + } + + /** Customizes the URL for a specific endpoint via callback */ + withUrlForEndpoint(endpointName: string, callback: (obj: ResourceUrlAnnotation) => Promise): AzureBicepResourcePromise { + return new AzureBicepResourcePromise(this._withUrlForEndpointInternal(endpointName, callback)); + } + + /** @internal */ + private async _excludeFromManifestInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/excludeFromManifest', + rpcArgs + ); + return new AzureBicepResource(result, this._client); + } + + /** Excludes the resource from the deployment manifest */ + excludeFromManifest(): AzureBicepResourcePromise { + return new AzureBicepResourcePromise(this._excludeFromManifestInternal()); + } + + /** @internal */ + private async _withExplicitStartInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withExplicitStart', + rpcArgs + ); + return new AzureBicepResource(result, this._client); + } + + /** Prevents resource from starting automatically */ + withExplicitStart(): AzureBicepResourcePromise { + return new AzureBicepResourcePromise(this._withExplicitStartInternal()); + } + + /** @internal */ + private async _withHealthCheckInternal(key: string): Promise { + const rpcArgs: Record = { builder: this._handle, key }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withHealthCheck', + rpcArgs + ); + return new AzureBicepResource(result, this._client); + } + + /** Adds a health check by key */ + withHealthCheck(key: string): AzureBicepResourcePromise { + return new AzureBicepResourcePromise(this._withHealthCheckInternal(key)); + } + + /** @internal */ + private async _withCommandInternal(name: string, displayName: string, executeCommand: (arg: ExecuteCommandContext) => Promise, commandOptions?: CommandOptions): Promise { + const executeCommandId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as ExecuteCommandContextHandle; + const arg = new ExecuteCommandContext(argHandle, this._client); + return await executeCommand(arg); + }); + const rpcArgs: Record = { builder: this._handle, name, displayName, executeCommand: executeCommandId }; + if (commandOptions !== undefined) rpcArgs.commandOptions = commandOptions; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withCommand', + rpcArgs + ); + return new AzureBicepResource(result, this._client); + } + + /** Adds a resource command */ + withCommand(name: string, displayName: string, executeCommand: (arg: ExecuteCommandContext) => Promise, options?: WithCommandOptions): AzureBicepResourcePromise { + const commandOptions = options?.commandOptions; + return new AzureBicepResourcePromise(this._withCommandInternal(name, displayName, executeCommand, commandOptions)); + } + + /** @internal */ + private async _withParentRelationshipInternal(parent: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, parent }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withParentRelationship', + rpcArgs + ); + return new AzureBicepResource(result, this._client); + } + + /** Sets the parent relationship */ + withParentRelationship(parent: ResourceBuilderBase): AzureBicepResourcePromise { + return new AzureBicepResourcePromise(this._withParentRelationshipInternal(parent)); + } + + /** @internal */ + private async _withChildRelationshipInternal(child: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, child }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withChildRelationship', + rpcArgs + ); + return new AzureBicepResource(result, this._client); + } + + /** Sets a child relationship */ + withChildRelationship(child: ResourceBuilderBase): AzureBicepResourcePromise { + return new AzureBicepResourcePromise(this._withChildRelationshipInternal(child)); + } + + /** @internal */ + private async _withIconNameInternal(iconName: string, iconVariant?: IconVariant): Promise { + const rpcArgs: Record = { builder: this._handle, iconName }; + if (iconVariant !== undefined) rpcArgs.iconVariant = iconVariant; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withIconName', + rpcArgs + ); + return new AzureBicepResource(result, this._client); + } + + /** Sets the icon for the resource */ + withIconName(iconName: string, options?: WithIconNameOptions): AzureBicepResourcePromise { + const iconVariant = options?.iconVariant; + return new AzureBicepResourcePromise(this._withIconNameInternal(iconName, iconVariant)); + } + + /** @internal */ + private async _excludeFromMcpInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/excludeFromMcp', + rpcArgs + ); + return new AzureBicepResource(result, this._client); + } + + /** Excludes the resource from MCP server exposure */ + excludeFromMcp(): AzureBicepResourcePromise { + return new AzureBicepResourcePromise(this._excludeFromMcpInternal()); + } + + /** @internal */ + private async _withPipelineStepFactoryInternal(stepName: string, callback: (arg: PipelineStepContext) => Promise, dependsOn?: string[], requiredBy?: string[], tags?: string[], description?: string): Promise { + const callbackId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as PipelineStepContextHandle; + const arg = new PipelineStepContext(argHandle, this._client); + await callback(arg); + }); + const rpcArgs: Record = { builder: this._handle, stepName, callback: callbackId }; + if (dependsOn !== undefined) rpcArgs.dependsOn = dependsOn; + if (requiredBy !== undefined) rpcArgs.requiredBy = requiredBy; + if (tags !== undefined) rpcArgs.tags = tags; + if (description !== undefined) rpcArgs.description = description; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withPipelineStepFactory', + rpcArgs + ); + return new AzureBicepResource(result, this._client); + } + + /** Adds a pipeline step to the resource */ + withPipelineStepFactory(stepName: string, callback: (arg: PipelineStepContext) => Promise, options?: WithPipelineStepFactoryOptions): AzureBicepResourcePromise { + const dependsOn = options?.dependsOn; + const requiredBy = options?.requiredBy; + const tags = options?.tags; + const description = options?.description; + return new AzureBicepResourcePromise(this._withPipelineStepFactoryInternal(stepName, callback, dependsOn, requiredBy, tags, description)); + } + + /** @internal */ + private async _withPipelineConfigurationAsyncInternal(callback: (arg: PipelineConfigurationContext) => Promise): Promise { + const callbackId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as PipelineConfigurationContextHandle; + const arg = new PipelineConfigurationContext(argHandle, this._client); + await callback(arg); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withPipelineConfigurationAsync', + rpcArgs + ); + return new AzureBicepResource(result, this._client); + } + + /** Configures pipeline step dependencies via an async callback */ + withPipelineConfigurationAsync(callback: (arg: PipelineConfigurationContext) => Promise): AzureBicepResourcePromise { + return new AzureBicepResourcePromise(this._withPipelineConfigurationAsyncInternal(callback)); + } + + /** @internal */ + private async _withPipelineConfigurationInternal(callback: (obj: PipelineConfigurationContext) => Promise): Promise { + const callbackId = registerCallback(async (objData: unknown) => { + const objHandle = wrapIfHandle(objData) as PipelineConfigurationContextHandle; + const obj = new PipelineConfigurationContext(objHandle, this._client); + await callback(obj); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withPipelineConfiguration', + rpcArgs + ); + return new AzureBicepResource(result, this._client); + } + + /** Configures pipeline step dependencies via a callback */ + withPipelineConfiguration(callback: (obj: PipelineConfigurationContext) => Promise): AzureBicepResourcePromise { + return new AzureBicepResourcePromise(this._withPipelineConfigurationInternal(callback)); + } + + /** Gets the resource name */ + async getResourceName(): Promise { + const rpcArgs: Record = { resource: this._handle }; + return await this._client.invokeCapability( + 'Aspire.Hosting/getResourceName', + rpcArgs + ); + } + + /** @internal */ + private async _withStorageRoleAssignmentsInternal(target: AzureStorageResource, roles: AzureStorageRole[]): Promise { + const rpcArgs: Record = { builder: this._handle, target, roles }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure.Storage/withStorageRoleAssignments', + rpcArgs + ); + return new AzureBicepResource(result, this._client); + } + + /** Assigns Azure Storage roles to a resource */ + withStorageRoleAssignments(target: AzureStorageResource, roles: AzureStorageRole[]): AzureBicepResourcePromise { + return new AzureBicepResourcePromise(this._withStorageRoleAssignmentsInternal(target, roles)); + } + + /** @internal */ + private async _withEventHubsRoleAssignmentsInternal(target: AzureEventHubsResource, roles: AzureEventHubsRole[]): Promise { + const rpcArgs: Record = { builder: this._handle, target, roles }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure.EventHubs/withEventHubsRoleAssignments', + rpcArgs + ); + return new AzureBicepResource(result, this._client); + } + + /** Assigns Event Hubs roles to a resource */ + withEventHubsRoleAssignments(target: AzureEventHubsResource, roles: AzureEventHubsRole[]): AzureBicepResourcePromise { + return new AzureBicepResourcePromise(this._withEventHubsRoleAssignmentsInternal(target, roles)); + } + + /** @internal */ + private async _publishAsConnectionStringInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure/publishAsConnectionString', + rpcArgs + ); + return new AzureBicepResource(result, this._client); + } + + /** Publishes an Azure resource to the manifest as a connection string */ + publishAsConnectionString(): AzureBicepResourcePromise { + return new AzureBicepResourcePromise(this._publishAsConnectionStringInternal()); + } + + /** Gets the normalized Bicep identifier for an Azure resource */ + async getBicepIdentifier(): Promise { + const rpcArgs: Record = { resource: this._handle }; + return await this._client.invokeCapability( + 'Aspire.Hosting.Azure/getBicepIdentifier', + rpcArgs + ); + } + + /** @internal */ + private async _clearDefaultRoleAssignmentsInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure/clearDefaultRoleAssignments', + rpcArgs + ); + return new AzureBicepResource(result, this._client); + } + + /** Clears the default Azure role assignments from a resource */ + clearDefaultRoleAssignments(): AzureBicepResourcePromise { + return new AzureBicepResourcePromise(this._clearDefaultRoleAssignmentsInternal()); + } + + /** Determines whether a resource is marked as existing */ + async isExisting(): Promise { + const rpcArgs: Record = { resource: this._handle }; + return await this._client.invokeCapability( + 'Aspire.Hosting.Azure/isExisting', + rpcArgs + ); + } + + /** @internal */ + private async _runAsExistingFromParametersInternal(nameParameter: ParameterResource, resourceGroupParameter: ParameterResource): Promise { + const rpcArgs: Record = { builder: this._handle, nameParameter, resourceGroupParameter }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure/runAsExistingFromParameters', + rpcArgs + ); + return new AzureBicepResource(result, this._client); + } + + /** Marks an Azure resource as existing in run mode by using parameter resources */ + runAsExistingFromParameters(nameParameter: ParameterResource, resourceGroupParameter: ParameterResource): AzureBicepResourcePromise { + return new AzureBicepResourcePromise(this._runAsExistingFromParametersInternal(nameParameter, resourceGroupParameter)); + } + + /** @internal */ + private async _runAsExistingInternal(name: string, resourceGroup: string): Promise { + const rpcArgs: Record = { builder: this._handle, name, resourceGroup }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure/runAsExisting', + rpcArgs + ); + return new AzureBicepResource(result, this._client); + } + + /** Marks an Azure resource as existing in run mode */ + runAsExisting(name: string, resourceGroup: string): AzureBicepResourcePromise { + return new AzureBicepResourcePromise(this._runAsExistingInternal(name, resourceGroup)); + } + + /** @internal */ + private async _publishAsExistingFromParametersInternal(nameParameter: ParameterResource, resourceGroupParameter: ParameterResource): Promise { + const rpcArgs: Record = { builder: this._handle, nameParameter, resourceGroupParameter }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure/publishAsExistingFromParameters', + rpcArgs + ); + return new AzureBicepResource(result, this._client); + } + + /** Marks an Azure resource as existing in publish mode by using parameter resources */ + publishAsExistingFromParameters(nameParameter: ParameterResource, resourceGroupParameter: ParameterResource): AzureBicepResourcePromise { + return new AzureBicepResourcePromise(this._publishAsExistingFromParametersInternal(nameParameter, resourceGroupParameter)); + } + + /** @internal */ + private async _publishAsExistingInternal(name: string, resourceGroup: string): Promise { + const rpcArgs: Record = { builder: this._handle, name, resourceGroup }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure/publishAsExisting', + rpcArgs + ); + return new AzureBicepResource(result, this._client); + } + + /** Marks an Azure resource as existing in publish mode */ + publishAsExisting(name: string, resourceGroup: string): AzureBicepResourcePromise { + return new AzureBicepResourcePromise(this._publishAsExistingInternal(name, resourceGroup)); + } + + /** @internal */ + private async _asExistingInternal(nameParameter: ParameterResource, resourceGroupParameter: ParameterResource): Promise { + const rpcArgs: Record = { builder: this._handle, nameParameter, resourceGroupParameter }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure/asExistingFromParameters', + rpcArgs + ); + return new AzureBicepResource(result, this._client); + } + + /** Marks an Azure resource as existing in both run and publish modes by using parameter resources */ + asExisting(nameParameter: ParameterResource, resourceGroupParameter: ParameterResource): AzureBicepResourcePromise { + return new AzureBicepResourcePromise(this._asExistingInternal(nameParameter, resourceGroupParameter)); + } + +} + +/** + * Thenable wrapper for AzureBicepResource that enables fluent chaining. + * @example + * await builder.addSomething().withX().withY(); + */ +export class AzureBicepResourcePromise implements PromiseLike { + constructor(private _promise: Promise) {} + + then( + onfulfilled?: ((value: AzureBicepResource) => TResult1 | PromiseLike) | null, + onrejected?: ((reason: unknown) => TResult2 | PromiseLike) | null + ): PromiseLike { + return this._promise.then(onfulfilled, onrejected); + } + + /** Configures a resource to use a container registry */ + withContainerRegistry(registry: ResourceBuilderBase): AzureBicepResourcePromise { + return new AzureBicepResourcePromise(this._promise.then(obj => obj.withContainerRegistry(registry))); + } + + /** Sets the base image for a Dockerfile build */ + withDockerfileBaseImage(options?: WithDockerfileBaseImageOptions): AzureBicepResourcePromise { + return new AzureBicepResourcePromise(this._promise.then(obj => obj.withDockerfileBaseImage(options))); + } + + /** Adds a required command dependency */ + withRequiredCommand(command: string, options?: WithRequiredCommandOptions): AzureBicepResourcePromise { + return new AzureBicepResourcePromise(this._promise.then(obj => obj.withRequiredCommand(command, options))); + } + + /** Customizes displayed URLs via callback */ + withUrlsCallback(callback: (obj: ResourceUrlsCallbackContext) => Promise): AzureBicepResourcePromise { + return new AzureBicepResourcePromise(this._promise.then(obj => obj.withUrlsCallback(callback))); + } + + /** Customizes displayed URLs via async callback */ + withUrlsCallbackAsync(callback: (arg: ResourceUrlsCallbackContext) => Promise): AzureBicepResourcePromise { + return new AzureBicepResourcePromise(this._promise.then(obj => obj.withUrlsCallbackAsync(callback))); + } + + /** Adds or modifies displayed URLs */ + withUrl(url: string, options?: WithUrlOptions): AzureBicepResourcePromise { + return new AzureBicepResourcePromise(this._promise.then(obj => obj.withUrl(url, options))); + } + + /** Adds a URL using a reference expression */ + withUrlExpression(url: ReferenceExpression, options?: WithUrlExpressionOptions): AzureBicepResourcePromise { + return new AzureBicepResourcePromise(this._promise.then(obj => obj.withUrlExpression(url, options))); + } + + /** Customizes the URL for a specific endpoint via callback */ + withUrlForEndpoint(endpointName: string, callback: (obj: ResourceUrlAnnotation) => Promise): AzureBicepResourcePromise { + return new AzureBicepResourcePromise(this._promise.then(obj => obj.withUrlForEndpoint(endpointName, callback))); + } + + /** Excludes the resource from the deployment manifest */ + excludeFromManifest(): AzureBicepResourcePromise { + return new AzureBicepResourcePromise(this._promise.then(obj => obj.excludeFromManifest())); + } + + /** Prevents resource from starting automatically */ + withExplicitStart(): AzureBicepResourcePromise { + return new AzureBicepResourcePromise(this._promise.then(obj => obj.withExplicitStart())); + } + + /** Adds a health check by key */ + withHealthCheck(key: string): AzureBicepResourcePromise { + return new AzureBicepResourcePromise(this._promise.then(obj => obj.withHealthCheck(key))); + } + + /** Adds a resource command */ + withCommand(name: string, displayName: string, executeCommand: (arg: ExecuteCommandContext) => Promise, options?: WithCommandOptions): AzureBicepResourcePromise { + return new AzureBicepResourcePromise(this._promise.then(obj => obj.withCommand(name, displayName, executeCommand, options))); + } + + /** Sets the parent relationship */ + withParentRelationship(parent: ResourceBuilderBase): AzureBicepResourcePromise { + return new AzureBicepResourcePromise(this._promise.then(obj => obj.withParentRelationship(parent))); + } + + /** Sets a child relationship */ + withChildRelationship(child: ResourceBuilderBase): AzureBicepResourcePromise { + return new AzureBicepResourcePromise(this._promise.then(obj => obj.withChildRelationship(child))); + } + + /** Sets the icon for the resource */ + withIconName(iconName: string, options?: WithIconNameOptions): AzureBicepResourcePromise { + return new AzureBicepResourcePromise(this._promise.then(obj => obj.withIconName(iconName, options))); + } + + /** Excludes the resource from MCP server exposure */ + excludeFromMcp(): AzureBicepResourcePromise { + return new AzureBicepResourcePromise(this._promise.then(obj => obj.excludeFromMcp())); + } + + /** Adds a pipeline step to the resource */ + withPipelineStepFactory(stepName: string, callback: (arg: PipelineStepContext) => Promise, options?: WithPipelineStepFactoryOptions): AzureBicepResourcePromise { + return new AzureBicepResourcePromise(this._promise.then(obj => obj.withPipelineStepFactory(stepName, callback, options))); + } + + /** Configures pipeline step dependencies via an async callback */ + withPipelineConfigurationAsync(callback: (arg: PipelineConfigurationContext) => Promise): AzureBicepResourcePromise { + return new AzureBicepResourcePromise(this._promise.then(obj => obj.withPipelineConfigurationAsync(callback))); + } + + /** Configures pipeline step dependencies via a callback */ + withPipelineConfiguration(callback: (obj: PipelineConfigurationContext) => Promise): AzureBicepResourcePromise { + return new AzureBicepResourcePromise(this._promise.then(obj => obj.withPipelineConfiguration(callback))); + } + + /** Gets the resource name */ + getResourceName(): Promise { + return this._promise.then(obj => obj.getResourceName()); + } + + /** Assigns Azure Storage roles to a resource */ + withStorageRoleAssignments(target: AzureStorageResource, roles: AzureStorageRole[]): AzureBicepResourcePromise { + return new AzureBicepResourcePromise(this._promise.then(obj => obj.withStorageRoleAssignments(target, roles))); + } + + /** Assigns Event Hubs roles to a resource */ + withEventHubsRoleAssignments(target: AzureEventHubsResource, roles: AzureEventHubsRole[]): AzureBicepResourcePromise { + return new AzureBicepResourcePromise(this._promise.then(obj => obj.withEventHubsRoleAssignments(target, roles))); + } + + /** Publishes an Azure resource to the manifest as a connection string */ + publishAsConnectionString(): AzureBicepResourcePromise { + return new AzureBicepResourcePromise(this._promise.then(obj => obj.publishAsConnectionString())); + } + + /** Gets the normalized Bicep identifier for an Azure resource */ + getBicepIdentifier(): Promise { + return this._promise.then(obj => obj.getBicepIdentifier()); + } + + /** Clears the default Azure role assignments from a resource */ + clearDefaultRoleAssignments(): AzureBicepResourcePromise { + return new AzureBicepResourcePromise(this._promise.then(obj => obj.clearDefaultRoleAssignments())); + } + + /** Determines whether a resource is marked as existing */ + isExisting(): Promise { + return this._promise.then(obj => obj.isExisting()); + } + + /** Marks an Azure resource as existing in run mode by using parameter resources */ + runAsExistingFromParameters(nameParameter: ParameterResource, resourceGroupParameter: ParameterResource): AzureBicepResourcePromise { + return new AzureBicepResourcePromise(this._promise.then(obj => obj.runAsExistingFromParameters(nameParameter, resourceGroupParameter))); + } + + /** Marks an Azure resource as existing in run mode */ + runAsExisting(name: string, resourceGroup: string): AzureBicepResourcePromise { + return new AzureBicepResourcePromise(this._promise.then(obj => obj.runAsExisting(name, resourceGroup))); + } + + /** Marks an Azure resource as existing in publish mode by using parameter resources */ + publishAsExistingFromParameters(nameParameter: ParameterResource, resourceGroupParameter: ParameterResource): AzureBicepResourcePromise { + return new AzureBicepResourcePromise(this._promise.then(obj => obj.publishAsExistingFromParameters(nameParameter, resourceGroupParameter))); + } + + /** Marks an Azure resource as existing in publish mode */ + publishAsExisting(name: string, resourceGroup: string): AzureBicepResourcePromise { + return new AzureBicepResourcePromise(this._promise.then(obj => obj.publishAsExisting(name, resourceGroup))); + } + + /** Marks an Azure resource as existing in both run and publish modes by using parameter resources */ + asExisting(nameParameter: ParameterResource, resourceGroupParameter: ParameterResource): AzureBicepResourcePromise { + return new AzureBicepResourcePromise(this._promise.then(obj => obj.asExisting(nameParameter, resourceGroupParameter))); + } + +} + +// ============================================================================ +// AzureBlobStorageContainerResource +// ============================================================================ + +export class AzureBlobStorageContainerResource extends ResourceBuilderBase { + constructor(handle: AzureBlobStorageContainerResourceHandle, client: AspireClientRpc) { + super(handle, client); + } + + /** @internal */ + private async _withContainerRegistryInternal(registry: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, registry }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withContainerRegistry', + rpcArgs + ); + return new AzureBlobStorageContainerResource(result, this._client); + } + + /** Configures a resource to use a container registry */ + withContainerRegistry(registry: ResourceBuilderBase): AzureBlobStorageContainerResourcePromise { + return new AzureBlobStorageContainerResourcePromise(this._withContainerRegistryInternal(registry)); + } + + /** @internal */ + private async _withDockerfileBaseImageInternal(buildImage?: string, runtimeImage?: string): Promise { + const rpcArgs: Record = { builder: this._handle }; + if (buildImage !== undefined) rpcArgs.buildImage = buildImage; + if (runtimeImage !== undefined) rpcArgs.runtimeImage = runtimeImage; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withDockerfileBaseImage', + rpcArgs + ); + return new AzureBlobStorageContainerResource(result, this._client); + } + + /** Sets the base image for a Dockerfile build */ + withDockerfileBaseImage(options?: WithDockerfileBaseImageOptions): AzureBlobStorageContainerResourcePromise { + const buildImage = options?.buildImage; + const runtimeImage = options?.runtimeImage; + return new AzureBlobStorageContainerResourcePromise(this._withDockerfileBaseImageInternal(buildImage, runtimeImage)); + } + + /** @internal */ + private async _withRequiredCommandInternal(command: string, helpLink?: string): Promise { + const rpcArgs: Record = { builder: this._handle, command }; + if (helpLink !== undefined) rpcArgs.helpLink = helpLink; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withRequiredCommand', + rpcArgs + ); + return new AzureBlobStorageContainerResource(result, this._client); + } + + /** Adds a required command dependency */ + withRequiredCommand(command: string, options?: WithRequiredCommandOptions): AzureBlobStorageContainerResourcePromise { + const helpLink = options?.helpLink; + return new AzureBlobStorageContainerResourcePromise(this._withRequiredCommandInternal(command, helpLink)); + } + + /** @internal */ + private async _withConnectionPropertyInternal(name: string, value: ReferenceExpression): Promise { + const rpcArgs: Record = { builder: this._handle, name, value }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withConnectionProperty', + rpcArgs + ); + return new AzureBlobStorageContainerResource(result, this._client); + } + + /** Adds a connection property with a reference expression */ + withConnectionProperty(name: string, value: ReferenceExpression): AzureBlobStorageContainerResourcePromise { + return new AzureBlobStorageContainerResourcePromise(this._withConnectionPropertyInternal(name, value)); + } + + /** @internal */ + private async _withConnectionPropertyValueInternal(name: string, value: string): Promise { + const rpcArgs: Record = { builder: this._handle, name, value }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withConnectionPropertyValue', + rpcArgs + ); + return new AzureBlobStorageContainerResource(result, this._client); + } + + /** Adds a connection property with a string value */ + withConnectionPropertyValue(name: string, value: string): AzureBlobStorageContainerResourcePromise { + return new AzureBlobStorageContainerResourcePromise(this._withConnectionPropertyValueInternal(name, value)); + } + + /** @internal */ + private async _withUrlsCallbackInternal(callback: (obj: ResourceUrlsCallbackContext) => Promise): Promise { + const callbackId = registerCallback(async (objData: unknown) => { + const objHandle = wrapIfHandle(objData) as ResourceUrlsCallbackContextHandle; + const obj = new ResourceUrlsCallbackContext(objHandle, this._client); + await callback(obj); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrlsCallback', + rpcArgs + ); + return new AzureBlobStorageContainerResource(result, this._client); + } + + /** Customizes displayed URLs via callback */ + withUrlsCallback(callback: (obj: ResourceUrlsCallbackContext) => Promise): AzureBlobStorageContainerResourcePromise { + return new AzureBlobStorageContainerResourcePromise(this._withUrlsCallbackInternal(callback)); + } + + /** @internal */ + private async _withUrlsCallbackAsyncInternal(callback: (arg: ResourceUrlsCallbackContext) => Promise): Promise { + const callbackId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as ResourceUrlsCallbackContextHandle; + const arg = new ResourceUrlsCallbackContext(argHandle, this._client); + await callback(arg); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrlsCallbackAsync', + rpcArgs + ); + return new AzureBlobStorageContainerResource(result, this._client); + } + + /** Customizes displayed URLs via async callback */ + withUrlsCallbackAsync(callback: (arg: ResourceUrlsCallbackContext) => Promise): AzureBlobStorageContainerResourcePromise { + return new AzureBlobStorageContainerResourcePromise(this._withUrlsCallbackAsyncInternal(callback)); + } + + /** @internal */ + private async _withUrlInternal(url: string, displayText?: string): Promise { + const rpcArgs: Record = { builder: this._handle, url }; + if (displayText !== undefined) rpcArgs.displayText = displayText; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrl', + rpcArgs + ); + return new AzureBlobStorageContainerResource(result, this._client); + } + + /** Adds or modifies displayed URLs */ + withUrl(url: string, options?: WithUrlOptions): AzureBlobStorageContainerResourcePromise { + const displayText = options?.displayText; + return new AzureBlobStorageContainerResourcePromise(this._withUrlInternal(url, displayText)); + } + + /** @internal */ + private async _withUrlExpressionInternal(url: ReferenceExpression, displayText?: string): Promise { + const rpcArgs: Record = { builder: this._handle, url }; + if (displayText !== undefined) rpcArgs.displayText = displayText; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrlExpression', + rpcArgs + ); + return new AzureBlobStorageContainerResource(result, this._client); + } + + /** Adds a URL using a reference expression */ + withUrlExpression(url: ReferenceExpression, options?: WithUrlExpressionOptions): AzureBlobStorageContainerResourcePromise { + const displayText = options?.displayText; + return new AzureBlobStorageContainerResourcePromise(this._withUrlExpressionInternal(url, displayText)); + } + + /** @internal */ + private async _withUrlForEndpointInternal(endpointName: string, callback: (obj: ResourceUrlAnnotation) => Promise): Promise { + const callbackId = registerCallback(async (objData: unknown) => { + const obj = wrapIfHandle(objData) as ResourceUrlAnnotation; + await callback(obj); + }); + const rpcArgs: Record = { builder: this._handle, endpointName, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrlForEndpoint', + rpcArgs + ); + return new AzureBlobStorageContainerResource(result, this._client); + } + + /** Customizes the URL for a specific endpoint via callback */ + withUrlForEndpoint(endpointName: string, callback: (obj: ResourceUrlAnnotation) => Promise): AzureBlobStorageContainerResourcePromise { + return new AzureBlobStorageContainerResourcePromise(this._withUrlForEndpointInternal(endpointName, callback)); + } + + /** @internal */ + private async _excludeFromManifestInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/excludeFromManifest', + rpcArgs + ); + return new AzureBlobStorageContainerResource(result, this._client); + } + + /** Excludes the resource from the deployment manifest */ + excludeFromManifest(): AzureBlobStorageContainerResourcePromise { + return new AzureBlobStorageContainerResourcePromise(this._excludeFromManifestInternal()); + } + + /** @internal */ + private async _withExplicitStartInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withExplicitStart', + rpcArgs + ); + return new AzureBlobStorageContainerResource(result, this._client); + } + + /** Prevents resource from starting automatically */ + withExplicitStart(): AzureBlobStorageContainerResourcePromise { + return new AzureBlobStorageContainerResourcePromise(this._withExplicitStartInternal()); + } + + /** @internal */ + private async _withHealthCheckInternal(key: string): Promise { + const rpcArgs: Record = { builder: this._handle, key }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withHealthCheck', + rpcArgs + ); + return new AzureBlobStorageContainerResource(result, this._client); + } + + /** Adds a health check by key */ + withHealthCheck(key: string): AzureBlobStorageContainerResourcePromise { + return new AzureBlobStorageContainerResourcePromise(this._withHealthCheckInternal(key)); + } + + /** @internal */ + private async _withCommandInternal(name: string, displayName: string, executeCommand: (arg: ExecuteCommandContext) => Promise, commandOptions?: CommandOptions): Promise { + const executeCommandId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as ExecuteCommandContextHandle; + const arg = new ExecuteCommandContext(argHandle, this._client); + return await executeCommand(arg); + }); + const rpcArgs: Record = { builder: this._handle, name, displayName, executeCommand: executeCommandId }; + if (commandOptions !== undefined) rpcArgs.commandOptions = commandOptions; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withCommand', + rpcArgs + ); + return new AzureBlobStorageContainerResource(result, this._client); + } + + /** Adds a resource command */ + withCommand(name: string, displayName: string, executeCommand: (arg: ExecuteCommandContext) => Promise, options?: WithCommandOptions): AzureBlobStorageContainerResourcePromise { + const commandOptions = options?.commandOptions; + return new AzureBlobStorageContainerResourcePromise(this._withCommandInternal(name, displayName, executeCommand, commandOptions)); + } + + /** @internal */ + private async _withParentRelationshipInternal(parent: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, parent }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withParentRelationship', + rpcArgs + ); + return new AzureBlobStorageContainerResource(result, this._client); + } + + /** Sets the parent relationship */ + withParentRelationship(parent: ResourceBuilderBase): AzureBlobStorageContainerResourcePromise { + return new AzureBlobStorageContainerResourcePromise(this._withParentRelationshipInternal(parent)); + } + + /** @internal */ + private async _withChildRelationshipInternal(child: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, child }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withChildRelationship', + rpcArgs + ); + return new AzureBlobStorageContainerResource(result, this._client); + } + + /** Sets a child relationship */ + withChildRelationship(child: ResourceBuilderBase): AzureBlobStorageContainerResourcePromise { + return new AzureBlobStorageContainerResourcePromise(this._withChildRelationshipInternal(child)); + } + + /** @internal */ + private async _withIconNameInternal(iconName: string, iconVariant?: IconVariant): Promise { + const rpcArgs: Record = { builder: this._handle, iconName }; + if (iconVariant !== undefined) rpcArgs.iconVariant = iconVariant; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withIconName', + rpcArgs + ); + return new AzureBlobStorageContainerResource(result, this._client); + } + + /** Sets the icon for the resource */ + withIconName(iconName: string, options?: WithIconNameOptions): AzureBlobStorageContainerResourcePromise { + const iconVariant = options?.iconVariant; + return new AzureBlobStorageContainerResourcePromise(this._withIconNameInternal(iconName, iconVariant)); + } + + /** @internal */ + private async _excludeFromMcpInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/excludeFromMcp', + rpcArgs + ); + return new AzureBlobStorageContainerResource(result, this._client); + } + + /** Excludes the resource from MCP server exposure */ + excludeFromMcp(): AzureBlobStorageContainerResourcePromise { + return new AzureBlobStorageContainerResourcePromise(this._excludeFromMcpInternal()); + } + + /** @internal */ + private async _withPipelineStepFactoryInternal(stepName: string, callback: (arg: PipelineStepContext) => Promise, dependsOn?: string[], requiredBy?: string[], tags?: string[], description?: string): Promise { + const callbackId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as PipelineStepContextHandle; + const arg = new PipelineStepContext(argHandle, this._client); + await callback(arg); + }); + const rpcArgs: Record = { builder: this._handle, stepName, callback: callbackId }; + if (dependsOn !== undefined) rpcArgs.dependsOn = dependsOn; + if (requiredBy !== undefined) rpcArgs.requiredBy = requiredBy; + if (tags !== undefined) rpcArgs.tags = tags; + if (description !== undefined) rpcArgs.description = description; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withPipelineStepFactory', + rpcArgs + ); + return new AzureBlobStorageContainerResource(result, this._client); + } + + /** Adds a pipeline step to the resource */ + withPipelineStepFactory(stepName: string, callback: (arg: PipelineStepContext) => Promise, options?: WithPipelineStepFactoryOptions): AzureBlobStorageContainerResourcePromise { + const dependsOn = options?.dependsOn; + const requiredBy = options?.requiredBy; + const tags = options?.tags; + const description = options?.description; + return new AzureBlobStorageContainerResourcePromise(this._withPipelineStepFactoryInternal(stepName, callback, dependsOn, requiredBy, tags, description)); + } + + /** @internal */ + private async _withPipelineConfigurationAsyncInternal(callback: (arg: PipelineConfigurationContext) => Promise): Promise { + const callbackId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as PipelineConfigurationContextHandle; + const arg = new PipelineConfigurationContext(argHandle, this._client); + await callback(arg); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withPipelineConfigurationAsync', + rpcArgs + ); + return new AzureBlobStorageContainerResource(result, this._client); + } + + /** Configures pipeline step dependencies via an async callback */ + withPipelineConfigurationAsync(callback: (arg: PipelineConfigurationContext) => Promise): AzureBlobStorageContainerResourcePromise { + return new AzureBlobStorageContainerResourcePromise(this._withPipelineConfigurationAsyncInternal(callback)); + } + + /** @internal */ + private async _withPipelineConfigurationInternal(callback: (obj: PipelineConfigurationContext) => Promise): Promise { + const callbackId = registerCallback(async (objData: unknown) => { + const objHandle = wrapIfHandle(objData) as PipelineConfigurationContextHandle; + const obj = new PipelineConfigurationContext(objHandle, this._client); + await callback(obj); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withPipelineConfiguration', + rpcArgs + ); + return new AzureBlobStorageContainerResource(result, this._client); + } + + /** Configures pipeline step dependencies via a callback */ + withPipelineConfiguration(callback: (obj: PipelineConfigurationContext) => Promise): AzureBlobStorageContainerResourcePromise { + return new AzureBlobStorageContainerResourcePromise(this._withPipelineConfigurationInternal(callback)); + } + + /** Gets the resource name */ + async getResourceName(): Promise { + const rpcArgs: Record = { resource: this._handle }; + return await this._client.invokeCapability( + 'Aspire.Hosting/getResourceName', + rpcArgs + ); + } + + /** @internal */ + private async _withStorageRoleAssignmentsInternal(target: AzureStorageResource, roles: AzureStorageRole[]): Promise { + const rpcArgs: Record = { builder: this._handle, target, roles }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure.Storage/withStorageRoleAssignments', + rpcArgs + ); + return new AzureBlobStorageContainerResource(result, this._client); + } + + /** Assigns Azure Storage roles to a resource */ + withStorageRoleAssignments(target: AzureStorageResource, roles: AzureStorageRole[]): AzureBlobStorageContainerResourcePromise { + return new AzureBlobStorageContainerResourcePromise(this._withStorageRoleAssignmentsInternal(target, roles)); + } + + /** @internal */ + private async _withEventHubsRoleAssignmentsInternal(target: AzureEventHubsResource, roles: AzureEventHubsRole[]): Promise { + const rpcArgs: Record = { builder: this._handle, target, roles }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure.EventHubs/withEventHubsRoleAssignments', + rpcArgs + ); + return new AzureBlobStorageContainerResource(result, this._client); + } + + /** Assigns Event Hubs roles to a resource */ + withEventHubsRoleAssignments(target: AzureEventHubsResource, roles: AzureEventHubsRole[]): AzureBlobStorageContainerResourcePromise { + return new AzureBlobStorageContainerResourcePromise(this._withEventHubsRoleAssignmentsInternal(target, roles)); + } + +} + +/** + * Thenable wrapper for AzureBlobStorageContainerResource that enables fluent chaining. + * @example + * await builder.addSomething().withX().withY(); + */ +export class AzureBlobStorageContainerResourcePromise implements PromiseLike { + constructor(private _promise: Promise) {} + + then( + onfulfilled?: ((value: AzureBlobStorageContainerResource) => TResult1 | PromiseLike) | null, + onrejected?: ((reason: unknown) => TResult2 | PromiseLike) | null + ): PromiseLike { + return this._promise.then(onfulfilled, onrejected); + } + + /** Configures a resource to use a container registry */ + withContainerRegistry(registry: ResourceBuilderBase): AzureBlobStorageContainerResourcePromise { + return new AzureBlobStorageContainerResourcePromise(this._promise.then(obj => obj.withContainerRegistry(registry))); + } + + /** Sets the base image for a Dockerfile build */ + withDockerfileBaseImage(options?: WithDockerfileBaseImageOptions): AzureBlobStorageContainerResourcePromise { + return new AzureBlobStorageContainerResourcePromise(this._promise.then(obj => obj.withDockerfileBaseImage(options))); + } + + /** Adds a required command dependency */ + withRequiredCommand(command: string, options?: WithRequiredCommandOptions): AzureBlobStorageContainerResourcePromise { + return new AzureBlobStorageContainerResourcePromise(this._promise.then(obj => obj.withRequiredCommand(command, options))); + } + + /** Adds a connection property with a reference expression */ + withConnectionProperty(name: string, value: ReferenceExpression): AzureBlobStorageContainerResourcePromise { + return new AzureBlobStorageContainerResourcePromise(this._promise.then(obj => obj.withConnectionProperty(name, value))); + } + + /** Adds a connection property with a string value */ + withConnectionPropertyValue(name: string, value: string): AzureBlobStorageContainerResourcePromise { + return new AzureBlobStorageContainerResourcePromise(this._promise.then(obj => obj.withConnectionPropertyValue(name, value))); + } + + /** Customizes displayed URLs via callback */ + withUrlsCallback(callback: (obj: ResourceUrlsCallbackContext) => Promise): AzureBlobStorageContainerResourcePromise { + return new AzureBlobStorageContainerResourcePromise(this._promise.then(obj => obj.withUrlsCallback(callback))); + } + + /** Customizes displayed URLs via async callback */ + withUrlsCallbackAsync(callback: (arg: ResourceUrlsCallbackContext) => Promise): AzureBlobStorageContainerResourcePromise { + return new AzureBlobStorageContainerResourcePromise(this._promise.then(obj => obj.withUrlsCallbackAsync(callback))); + } + + /** Adds or modifies displayed URLs */ + withUrl(url: string, options?: WithUrlOptions): AzureBlobStorageContainerResourcePromise { + return new AzureBlobStorageContainerResourcePromise(this._promise.then(obj => obj.withUrl(url, options))); + } + + /** Adds a URL using a reference expression */ + withUrlExpression(url: ReferenceExpression, options?: WithUrlExpressionOptions): AzureBlobStorageContainerResourcePromise { + return new AzureBlobStorageContainerResourcePromise(this._promise.then(obj => obj.withUrlExpression(url, options))); + } + + /** Customizes the URL for a specific endpoint via callback */ + withUrlForEndpoint(endpointName: string, callback: (obj: ResourceUrlAnnotation) => Promise): AzureBlobStorageContainerResourcePromise { + return new AzureBlobStorageContainerResourcePromise(this._promise.then(obj => obj.withUrlForEndpoint(endpointName, callback))); + } + + /** Excludes the resource from the deployment manifest */ + excludeFromManifest(): AzureBlobStorageContainerResourcePromise { + return new AzureBlobStorageContainerResourcePromise(this._promise.then(obj => obj.excludeFromManifest())); + } + + /** Prevents resource from starting automatically */ + withExplicitStart(): AzureBlobStorageContainerResourcePromise { + return new AzureBlobStorageContainerResourcePromise(this._promise.then(obj => obj.withExplicitStart())); + } + + /** Adds a health check by key */ + withHealthCheck(key: string): AzureBlobStorageContainerResourcePromise { + return new AzureBlobStorageContainerResourcePromise(this._promise.then(obj => obj.withHealthCheck(key))); + } + + /** Adds a resource command */ + withCommand(name: string, displayName: string, executeCommand: (arg: ExecuteCommandContext) => Promise, options?: WithCommandOptions): AzureBlobStorageContainerResourcePromise { + return new AzureBlobStorageContainerResourcePromise(this._promise.then(obj => obj.withCommand(name, displayName, executeCommand, options))); + } + + /** Sets the parent relationship */ + withParentRelationship(parent: ResourceBuilderBase): AzureBlobStorageContainerResourcePromise { + return new AzureBlobStorageContainerResourcePromise(this._promise.then(obj => obj.withParentRelationship(parent))); + } + + /** Sets a child relationship */ + withChildRelationship(child: ResourceBuilderBase): AzureBlobStorageContainerResourcePromise { + return new AzureBlobStorageContainerResourcePromise(this._promise.then(obj => obj.withChildRelationship(child))); + } + + /** Sets the icon for the resource */ + withIconName(iconName: string, options?: WithIconNameOptions): AzureBlobStorageContainerResourcePromise { + return new AzureBlobStorageContainerResourcePromise(this._promise.then(obj => obj.withIconName(iconName, options))); + } + + /** Excludes the resource from MCP server exposure */ + excludeFromMcp(): AzureBlobStorageContainerResourcePromise { + return new AzureBlobStorageContainerResourcePromise(this._promise.then(obj => obj.excludeFromMcp())); + } + + /** Adds a pipeline step to the resource */ + withPipelineStepFactory(stepName: string, callback: (arg: PipelineStepContext) => Promise, options?: WithPipelineStepFactoryOptions): AzureBlobStorageContainerResourcePromise { + return new AzureBlobStorageContainerResourcePromise(this._promise.then(obj => obj.withPipelineStepFactory(stepName, callback, options))); + } + + /** Configures pipeline step dependencies via an async callback */ + withPipelineConfigurationAsync(callback: (arg: PipelineConfigurationContext) => Promise): AzureBlobStorageContainerResourcePromise { + return new AzureBlobStorageContainerResourcePromise(this._promise.then(obj => obj.withPipelineConfigurationAsync(callback))); + } + + /** Configures pipeline step dependencies via a callback */ + withPipelineConfiguration(callback: (obj: PipelineConfigurationContext) => Promise): AzureBlobStorageContainerResourcePromise { + return new AzureBlobStorageContainerResourcePromise(this._promise.then(obj => obj.withPipelineConfiguration(callback))); + } + + /** Gets the resource name */ + getResourceName(): Promise { + return this._promise.then(obj => obj.getResourceName()); + } + + /** Assigns Azure Storage roles to a resource */ + withStorageRoleAssignments(target: AzureStorageResource, roles: AzureStorageRole[]): AzureBlobStorageContainerResourcePromise { + return new AzureBlobStorageContainerResourcePromise(this._promise.then(obj => obj.withStorageRoleAssignments(target, roles))); + } + + /** Assigns Event Hubs roles to a resource */ + withEventHubsRoleAssignments(target: AzureEventHubsResource, roles: AzureEventHubsRole[]): AzureBlobStorageContainerResourcePromise { + return new AzureBlobStorageContainerResourcePromise(this._promise.then(obj => obj.withEventHubsRoleAssignments(target, roles))); + } + +} + +// ============================================================================ +// AzureBlobStorageResource +// ============================================================================ + +export class AzureBlobStorageResource extends ResourceBuilderBase { + constructor(handle: AzureBlobStorageResourceHandle, client: AspireClientRpc) { + super(handle, client); + } + + /** @internal */ + private async _withContainerRegistryInternal(registry: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, registry }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withContainerRegistry', + rpcArgs + ); + return new AzureBlobStorageResource(result, this._client); + } + + /** Configures a resource to use a container registry */ + withContainerRegistry(registry: ResourceBuilderBase): AzureBlobStorageResourcePromise { + return new AzureBlobStorageResourcePromise(this._withContainerRegistryInternal(registry)); + } + + /** @internal */ + private async _withDockerfileBaseImageInternal(buildImage?: string, runtimeImage?: string): Promise { + const rpcArgs: Record = { builder: this._handle }; + if (buildImage !== undefined) rpcArgs.buildImage = buildImage; + if (runtimeImage !== undefined) rpcArgs.runtimeImage = runtimeImage; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withDockerfileBaseImage', + rpcArgs + ); + return new AzureBlobStorageResource(result, this._client); + } + + /** Sets the base image for a Dockerfile build */ + withDockerfileBaseImage(options?: WithDockerfileBaseImageOptions): AzureBlobStorageResourcePromise { + const buildImage = options?.buildImage; + const runtimeImage = options?.runtimeImage; + return new AzureBlobStorageResourcePromise(this._withDockerfileBaseImageInternal(buildImage, runtimeImage)); + } + + /** @internal */ + private async _withRequiredCommandInternal(command: string, helpLink?: string): Promise { + const rpcArgs: Record = { builder: this._handle, command }; + if (helpLink !== undefined) rpcArgs.helpLink = helpLink; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withRequiredCommand', + rpcArgs + ); + return new AzureBlobStorageResource(result, this._client); + } + + /** Adds a required command dependency */ + withRequiredCommand(command: string, options?: WithRequiredCommandOptions): AzureBlobStorageResourcePromise { + const helpLink = options?.helpLink; + return new AzureBlobStorageResourcePromise(this._withRequiredCommandInternal(command, helpLink)); + } + + /** @internal */ + private async _withConnectionPropertyInternal(name: string, value: ReferenceExpression): Promise { + const rpcArgs: Record = { builder: this._handle, name, value }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withConnectionProperty', + rpcArgs + ); + return new AzureBlobStorageResource(result, this._client); + } + + /** Adds a connection property with a reference expression */ + withConnectionProperty(name: string, value: ReferenceExpression): AzureBlobStorageResourcePromise { + return new AzureBlobStorageResourcePromise(this._withConnectionPropertyInternal(name, value)); + } + + /** @internal */ + private async _withConnectionPropertyValueInternal(name: string, value: string): Promise { + const rpcArgs: Record = { builder: this._handle, name, value }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withConnectionPropertyValue', + rpcArgs + ); + return new AzureBlobStorageResource(result, this._client); + } + + /** Adds a connection property with a string value */ + withConnectionPropertyValue(name: string, value: string): AzureBlobStorageResourcePromise { + return new AzureBlobStorageResourcePromise(this._withConnectionPropertyValueInternal(name, value)); + } + + /** @internal */ + private async _withUrlsCallbackInternal(callback: (obj: ResourceUrlsCallbackContext) => Promise): Promise { + const callbackId = registerCallback(async (objData: unknown) => { + const objHandle = wrapIfHandle(objData) as ResourceUrlsCallbackContextHandle; + const obj = new ResourceUrlsCallbackContext(objHandle, this._client); + await callback(obj); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrlsCallback', + rpcArgs + ); + return new AzureBlobStorageResource(result, this._client); + } + + /** Customizes displayed URLs via callback */ + withUrlsCallback(callback: (obj: ResourceUrlsCallbackContext) => Promise): AzureBlobStorageResourcePromise { + return new AzureBlobStorageResourcePromise(this._withUrlsCallbackInternal(callback)); + } + + /** @internal */ + private async _withUrlsCallbackAsyncInternal(callback: (arg: ResourceUrlsCallbackContext) => Promise): Promise { + const callbackId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as ResourceUrlsCallbackContextHandle; + const arg = new ResourceUrlsCallbackContext(argHandle, this._client); + await callback(arg); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrlsCallbackAsync', + rpcArgs + ); + return new AzureBlobStorageResource(result, this._client); + } + + /** Customizes displayed URLs via async callback */ + withUrlsCallbackAsync(callback: (arg: ResourceUrlsCallbackContext) => Promise): AzureBlobStorageResourcePromise { + return new AzureBlobStorageResourcePromise(this._withUrlsCallbackAsyncInternal(callback)); + } + + /** @internal */ + private async _withUrlInternal(url: string, displayText?: string): Promise { + const rpcArgs: Record = { builder: this._handle, url }; + if (displayText !== undefined) rpcArgs.displayText = displayText; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrl', + rpcArgs + ); + return new AzureBlobStorageResource(result, this._client); + } + + /** Adds or modifies displayed URLs */ + withUrl(url: string, options?: WithUrlOptions): AzureBlobStorageResourcePromise { + const displayText = options?.displayText; + return new AzureBlobStorageResourcePromise(this._withUrlInternal(url, displayText)); + } + + /** @internal */ + private async _withUrlExpressionInternal(url: ReferenceExpression, displayText?: string): Promise { + const rpcArgs: Record = { builder: this._handle, url }; + if (displayText !== undefined) rpcArgs.displayText = displayText; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrlExpression', + rpcArgs + ); + return new AzureBlobStorageResource(result, this._client); + } + + /** Adds a URL using a reference expression */ + withUrlExpression(url: ReferenceExpression, options?: WithUrlExpressionOptions): AzureBlobStorageResourcePromise { + const displayText = options?.displayText; + return new AzureBlobStorageResourcePromise(this._withUrlExpressionInternal(url, displayText)); + } + + /** @internal */ + private async _withUrlForEndpointInternal(endpointName: string, callback: (obj: ResourceUrlAnnotation) => Promise): Promise { + const callbackId = registerCallback(async (objData: unknown) => { + const obj = wrapIfHandle(objData) as ResourceUrlAnnotation; + await callback(obj); + }); + const rpcArgs: Record = { builder: this._handle, endpointName, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrlForEndpoint', + rpcArgs + ); + return new AzureBlobStorageResource(result, this._client); + } + + /** Customizes the URL for a specific endpoint via callback */ + withUrlForEndpoint(endpointName: string, callback: (obj: ResourceUrlAnnotation) => Promise): AzureBlobStorageResourcePromise { + return new AzureBlobStorageResourcePromise(this._withUrlForEndpointInternal(endpointName, callback)); + } + + /** @internal */ + private async _excludeFromManifestInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/excludeFromManifest', + rpcArgs + ); + return new AzureBlobStorageResource(result, this._client); + } + + /** Excludes the resource from the deployment manifest */ + excludeFromManifest(): AzureBlobStorageResourcePromise { + return new AzureBlobStorageResourcePromise(this._excludeFromManifestInternal()); + } + + /** @internal */ + private async _withExplicitStartInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withExplicitStart', + rpcArgs + ); + return new AzureBlobStorageResource(result, this._client); + } + + /** Prevents resource from starting automatically */ + withExplicitStart(): AzureBlobStorageResourcePromise { + return new AzureBlobStorageResourcePromise(this._withExplicitStartInternal()); + } + + /** @internal */ + private async _withHealthCheckInternal(key: string): Promise { + const rpcArgs: Record = { builder: this._handle, key }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withHealthCheck', + rpcArgs + ); + return new AzureBlobStorageResource(result, this._client); + } + + /** Adds a health check by key */ + withHealthCheck(key: string): AzureBlobStorageResourcePromise { + return new AzureBlobStorageResourcePromise(this._withHealthCheckInternal(key)); + } + + /** @internal */ + private async _withCommandInternal(name: string, displayName: string, executeCommand: (arg: ExecuteCommandContext) => Promise, commandOptions?: CommandOptions): Promise { + const executeCommandId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as ExecuteCommandContextHandle; + const arg = new ExecuteCommandContext(argHandle, this._client); + return await executeCommand(arg); + }); + const rpcArgs: Record = { builder: this._handle, name, displayName, executeCommand: executeCommandId }; + if (commandOptions !== undefined) rpcArgs.commandOptions = commandOptions; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withCommand', + rpcArgs + ); + return new AzureBlobStorageResource(result, this._client); + } + + /** Adds a resource command */ + withCommand(name: string, displayName: string, executeCommand: (arg: ExecuteCommandContext) => Promise, options?: WithCommandOptions): AzureBlobStorageResourcePromise { + const commandOptions = options?.commandOptions; + return new AzureBlobStorageResourcePromise(this._withCommandInternal(name, displayName, executeCommand, commandOptions)); + } + + /** @internal */ + private async _withParentRelationshipInternal(parent: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, parent }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withParentRelationship', + rpcArgs + ); + return new AzureBlobStorageResource(result, this._client); + } + + /** Sets the parent relationship */ + withParentRelationship(parent: ResourceBuilderBase): AzureBlobStorageResourcePromise { + return new AzureBlobStorageResourcePromise(this._withParentRelationshipInternal(parent)); + } + + /** @internal */ + private async _withChildRelationshipInternal(child: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, child }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withChildRelationship', + rpcArgs + ); + return new AzureBlobStorageResource(result, this._client); + } + + /** Sets a child relationship */ + withChildRelationship(child: ResourceBuilderBase): AzureBlobStorageResourcePromise { + return new AzureBlobStorageResourcePromise(this._withChildRelationshipInternal(child)); + } + + /** @internal */ + private async _withIconNameInternal(iconName: string, iconVariant?: IconVariant): Promise { + const rpcArgs: Record = { builder: this._handle, iconName }; + if (iconVariant !== undefined) rpcArgs.iconVariant = iconVariant; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withIconName', + rpcArgs + ); + return new AzureBlobStorageResource(result, this._client); + } + + /** Sets the icon for the resource */ + withIconName(iconName: string, options?: WithIconNameOptions): AzureBlobStorageResourcePromise { + const iconVariant = options?.iconVariant; + return new AzureBlobStorageResourcePromise(this._withIconNameInternal(iconName, iconVariant)); + } + + /** @internal */ + private async _excludeFromMcpInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/excludeFromMcp', + rpcArgs + ); + return new AzureBlobStorageResource(result, this._client); + } + + /** Excludes the resource from MCP server exposure */ + excludeFromMcp(): AzureBlobStorageResourcePromise { + return new AzureBlobStorageResourcePromise(this._excludeFromMcpInternal()); + } + + /** @internal */ + private async _withPipelineStepFactoryInternal(stepName: string, callback: (arg: PipelineStepContext) => Promise, dependsOn?: string[], requiredBy?: string[], tags?: string[], description?: string): Promise { + const callbackId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as PipelineStepContextHandle; + const arg = new PipelineStepContext(argHandle, this._client); + await callback(arg); + }); + const rpcArgs: Record = { builder: this._handle, stepName, callback: callbackId }; + if (dependsOn !== undefined) rpcArgs.dependsOn = dependsOn; + if (requiredBy !== undefined) rpcArgs.requiredBy = requiredBy; + if (tags !== undefined) rpcArgs.tags = tags; + if (description !== undefined) rpcArgs.description = description; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withPipelineStepFactory', + rpcArgs + ); + return new AzureBlobStorageResource(result, this._client); + } + + /** Adds a pipeline step to the resource */ + withPipelineStepFactory(stepName: string, callback: (arg: PipelineStepContext) => Promise, options?: WithPipelineStepFactoryOptions): AzureBlobStorageResourcePromise { + const dependsOn = options?.dependsOn; + const requiredBy = options?.requiredBy; + const tags = options?.tags; + const description = options?.description; + return new AzureBlobStorageResourcePromise(this._withPipelineStepFactoryInternal(stepName, callback, dependsOn, requiredBy, tags, description)); + } + + /** @internal */ + private async _withPipelineConfigurationAsyncInternal(callback: (arg: PipelineConfigurationContext) => Promise): Promise { + const callbackId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as PipelineConfigurationContextHandle; + const arg = new PipelineConfigurationContext(argHandle, this._client); + await callback(arg); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withPipelineConfigurationAsync', + rpcArgs + ); + return new AzureBlobStorageResource(result, this._client); + } + + /** Configures pipeline step dependencies via an async callback */ + withPipelineConfigurationAsync(callback: (arg: PipelineConfigurationContext) => Promise): AzureBlobStorageResourcePromise { + return new AzureBlobStorageResourcePromise(this._withPipelineConfigurationAsyncInternal(callback)); + } + + /** @internal */ + private async _withPipelineConfigurationInternal(callback: (obj: PipelineConfigurationContext) => Promise): Promise { + const callbackId = registerCallback(async (objData: unknown) => { + const objHandle = wrapIfHandle(objData) as PipelineConfigurationContextHandle; + const obj = new PipelineConfigurationContext(objHandle, this._client); + await callback(obj); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withPipelineConfiguration', + rpcArgs + ); + return new AzureBlobStorageResource(result, this._client); + } + + /** Configures pipeline step dependencies via a callback */ + withPipelineConfiguration(callback: (obj: PipelineConfigurationContext) => Promise): AzureBlobStorageResourcePromise { + return new AzureBlobStorageResourcePromise(this._withPipelineConfigurationInternal(callback)); + } + + /** Gets the resource name */ + async getResourceName(): Promise { + const rpcArgs: Record = { resource: this._handle }; + return await this._client.invokeCapability( + 'Aspire.Hosting/getResourceName', + rpcArgs + ); + } + + /** @internal */ + private async _withStorageRoleAssignmentsInternal(target: AzureStorageResource, roles: AzureStorageRole[]): Promise { + const rpcArgs: Record = { builder: this._handle, target, roles }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure.Storage/withStorageRoleAssignments', + rpcArgs + ); + return new AzureBlobStorageResource(result, this._client); + } + + /** Assigns Azure Storage roles to a resource */ + withStorageRoleAssignments(target: AzureStorageResource, roles: AzureStorageRole[]): AzureBlobStorageResourcePromise { + return new AzureBlobStorageResourcePromise(this._withStorageRoleAssignmentsInternal(target, roles)); + } + + /** @internal */ + private async _withEventHubsRoleAssignmentsInternal(target: AzureEventHubsResource, roles: AzureEventHubsRole[]): Promise { + const rpcArgs: Record = { builder: this._handle, target, roles }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure.EventHubs/withEventHubsRoleAssignments', + rpcArgs + ); + return new AzureBlobStorageResource(result, this._client); + } + + /** Assigns Event Hubs roles to a resource */ + withEventHubsRoleAssignments(target: AzureEventHubsResource, roles: AzureEventHubsRole[]): AzureBlobStorageResourcePromise { + return new AzureBlobStorageResourcePromise(this._withEventHubsRoleAssignmentsInternal(target, roles)); + } + +} + +/** + * Thenable wrapper for AzureBlobStorageResource that enables fluent chaining. + * @example + * await builder.addSomething().withX().withY(); + */ +export class AzureBlobStorageResourcePromise implements PromiseLike { + constructor(private _promise: Promise) {} + + then( + onfulfilled?: ((value: AzureBlobStorageResource) => TResult1 | PromiseLike) | null, + onrejected?: ((reason: unknown) => TResult2 | PromiseLike) | null + ): PromiseLike { + return this._promise.then(onfulfilled, onrejected); + } + + /** Configures a resource to use a container registry */ + withContainerRegistry(registry: ResourceBuilderBase): AzureBlobStorageResourcePromise { + return new AzureBlobStorageResourcePromise(this._promise.then(obj => obj.withContainerRegistry(registry))); + } + + /** Sets the base image for a Dockerfile build */ + withDockerfileBaseImage(options?: WithDockerfileBaseImageOptions): AzureBlobStorageResourcePromise { + return new AzureBlobStorageResourcePromise(this._promise.then(obj => obj.withDockerfileBaseImage(options))); + } + + /** Adds a required command dependency */ + withRequiredCommand(command: string, options?: WithRequiredCommandOptions): AzureBlobStorageResourcePromise { + return new AzureBlobStorageResourcePromise(this._promise.then(obj => obj.withRequiredCommand(command, options))); + } + + /** Adds a connection property with a reference expression */ + withConnectionProperty(name: string, value: ReferenceExpression): AzureBlobStorageResourcePromise { + return new AzureBlobStorageResourcePromise(this._promise.then(obj => obj.withConnectionProperty(name, value))); + } + + /** Adds a connection property with a string value */ + withConnectionPropertyValue(name: string, value: string): AzureBlobStorageResourcePromise { + return new AzureBlobStorageResourcePromise(this._promise.then(obj => obj.withConnectionPropertyValue(name, value))); + } + + /** Customizes displayed URLs via callback */ + withUrlsCallback(callback: (obj: ResourceUrlsCallbackContext) => Promise): AzureBlobStorageResourcePromise { + return new AzureBlobStorageResourcePromise(this._promise.then(obj => obj.withUrlsCallback(callback))); + } + + /** Customizes displayed URLs via async callback */ + withUrlsCallbackAsync(callback: (arg: ResourceUrlsCallbackContext) => Promise): AzureBlobStorageResourcePromise { + return new AzureBlobStorageResourcePromise(this._promise.then(obj => obj.withUrlsCallbackAsync(callback))); + } + + /** Adds or modifies displayed URLs */ + withUrl(url: string, options?: WithUrlOptions): AzureBlobStorageResourcePromise { + return new AzureBlobStorageResourcePromise(this._promise.then(obj => obj.withUrl(url, options))); + } + + /** Adds a URL using a reference expression */ + withUrlExpression(url: ReferenceExpression, options?: WithUrlExpressionOptions): AzureBlobStorageResourcePromise { + return new AzureBlobStorageResourcePromise(this._promise.then(obj => obj.withUrlExpression(url, options))); + } + + /** Customizes the URL for a specific endpoint via callback */ + withUrlForEndpoint(endpointName: string, callback: (obj: ResourceUrlAnnotation) => Promise): AzureBlobStorageResourcePromise { + return new AzureBlobStorageResourcePromise(this._promise.then(obj => obj.withUrlForEndpoint(endpointName, callback))); + } + + /** Excludes the resource from the deployment manifest */ + excludeFromManifest(): AzureBlobStorageResourcePromise { + return new AzureBlobStorageResourcePromise(this._promise.then(obj => obj.excludeFromManifest())); + } + + /** Prevents resource from starting automatically */ + withExplicitStart(): AzureBlobStorageResourcePromise { + return new AzureBlobStorageResourcePromise(this._promise.then(obj => obj.withExplicitStart())); + } + + /** Adds a health check by key */ + withHealthCheck(key: string): AzureBlobStorageResourcePromise { + return new AzureBlobStorageResourcePromise(this._promise.then(obj => obj.withHealthCheck(key))); + } + + /** Adds a resource command */ + withCommand(name: string, displayName: string, executeCommand: (arg: ExecuteCommandContext) => Promise, options?: WithCommandOptions): AzureBlobStorageResourcePromise { + return new AzureBlobStorageResourcePromise(this._promise.then(obj => obj.withCommand(name, displayName, executeCommand, options))); + } + + /** Sets the parent relationship */ + withParentRelationship(parent: ResourceBuilderBase): AzureBlobStorageResourcePromise { + return new AzureBlobStorageResourcePromise(this._promise.then(obj => obj.withParentRelationship(parent))); + } + + /** Sets a child relationship */ + withChildRelationship(child: ResourceBuilderBase): AzureBlobStorageResourcePromise { + return new AzureBlobStorageResourcePromise(this._promise.then(obj => obj.withChildRelationship(child))); + } + + /** Sets the icon for the resource */ + withIconName(iconName: string, options?: WithIconNameOptions): AzureBlobStorageResourcePromise { + return new AzureBlobStorageResourcePromise(this._promise.then(obj => obj.withIconName(iconName, options))); + } + + /** Excludes the resource from MCP server exposure */ + excludeFromMcp(): AzureBlobStorageResourcePromise { + return new AzureBlobStorageResourcePromise(this._promise.then(obj => obj.excludeFromMcp())); + } + + /** Adds a pipeline step to the resource */ + withPipelineStepFactory(stepName: string, callback: (arg: PipelineStepContext) => Promise, options?: WithPipelineStepFactoryOptions): AzureBlobStorageResourcePromise { + return new AzureBlobStorageResourcePromise(this._promise.then(obj => obj.withPipelineStepFactory(stepName, callback, options))); + } + + /** Configures pipeline step dependencies via an async callback */ + withPipelineConfigurationAsync(callback: (arg: PipelineConfigurationContext) => Promise): AzureBlobStorageResourcePromise { + return new AzureBlobStorageResourcePromise(this._promise.then(obj => obj.withPipelineConfigurationAsync(callback))); + } + + /** Configures pipeline step dependencies via a callback */ + withPipelineConfiguration(callback: (obj: PipelineConfigurationContext) => Promise): AzureBlobStorageResourcePromise { + return new AzureBlobStorageResourcePromise(this._promise.then(obj => obj.withPipelineConfiguration(callback))); + } + + /** Gets the resource name */ + getResourceName(): Promise { + return this._promise.then(obj => obj.getResourceName()); + } + + /** Assigns Azure Storage roles to a resource */ + withStorageRoleAssignments(target: AzureStorageResource, roles: AzureStorageRole[]): AzureBlobStorageResourcePromise { + return new AzureBlobStorageResourcePromise(this._promise.then(obj => obj.withStorageRoleAssignments(target, roles))); + } + + /** Assigns Event Hubs roles to a resource */ + withEventHubsRoleAssignments(target: AzureEventHubsResource, roles: AzureEventHubsRole[]): AzureBlobStorageResourcePromise { + return new AzureBlobStorageResourcePromise(this._promise.then(obj => obj.withEventHubsRoleAssignments(target, roles))); + } + +} + +// ============================================================================ +// AzureDataLakeStorageFileSystemResource +// ============================================================================ + +export class AzureDataLakeStorageFileSystemResource extends ResourceBuilderBase { + constructor(handle: AzureDataLakeStorageFileSystemResourceHandle, client: AspireClientRpc) { + super(handle, client); + } + + /** @internal */ + private async _withContainerRegistryInternal(registry: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, registry }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withContainerRegistry', + rpcArgs + ); + return new AzureDataLakeStorageFileSystemResource(result, this._client); + } + + /** Configures a resource to use a container registry */ + withContainerRegistry(registry: ResourceBuilderBase): AzureDataLakeStorageFileSystemResourcePromise { + return new AzureDataLakeStorageFileSystemResourcePromise(this._withContainerRegistryInternal(registry)); + } + + /** @internal */ + private async _withDockerfileBaseImageInternal(buildImage?: string, runtimeImage?: string): Promise { + const rpcArgs: Record = { builder: this._handle }; + if (buildImage !== undefined) rpcArgs.buildImage = buildImage; + if (runtimeImage !== undefined) rpcArgs.runtimeImage = runtimeImage; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withDockerfileBaseImage', + rpcArgs + ); + return new AzureDataLakeStorageFileSystemResource(result, this._client); + } + + /** Sets the base image for a Dockerfile build */ + withDockerfileBaseImage(options?: WithDockerfileBaseImageOptions): AzureDataLakeStorageFileSystemResourcePromise { + const buildImage = options?.buildImage; + const runtimeImage = options?.runtimeImage; + return new AzureDataLakeStorageFileSystemResourcePromise(this._withDockerfileBaseImageInternal(buildImage, runtimeImage)); + } + + /** @internal */ + private async _withRequiredCommandInternal(command: string, helpLink?: string): Promise { + const rpcArgs: Record = { builder: this._handle, command }; + if (helpLink !== undefined) rpcArgs.helpLink = helpLink; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withRequiredCommand', + rpcArgs + ); + return new AzureDataLakeStorageFileSystemResource(result, this._client); + } + + /** Adds a required command dependency */ + withRequiredCommand(command: string, options?: WithRequiredCommandOptions): AzureDataLakeStorageFileSystemResourcePromise { + const helpLink = options?.helpLink; + return new AzureDataLakeStorageFileSystemResourcePromise(this._withRequiredCommandInternal(command, helpLink)); + } + + /** @internal */ + private async _withConnectionPropertyInternal(name: string, value: ReferenceExpression): Promise { + const rpcArgs: Record = { builder: this._handle, name, value }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withConnectionProperty', + rpcArgs + ); + return new AzureDataLakeStorageFileSystemResource(result, this._client); + } + + /** Adds a connection property with a reference expression */ + withConnectionProperty(name: string, value: ReferenceExpression): AzureDataLakeStorageFileSystemResourcePromise { + return new AzureDataLakeStorageFileSystemResourcePromise(this._withConnectionPropertyInternal(name, value)); + } + + /** @internal */ + private async _withConnectionPropertyValueInternal(name: string, value: string): Promise { + const rpcArgs: Record = { builder: this._handle, name, value }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withConnectionPropertyValue', + rpcArgs + ); + return new AzureDataLakeStorageFileSystemResource(result, this._client); + } + + /** Adds a connection property with a string value */ + withConnectionPropertyValue(name: string, value: string): AzureDataLakeStorageFileSystemResourcePromise { + return new AzureDataLakeStorageFileSystemResourcePromise(this._withConnectionPropertyValueInternal(name, value)); + } + + /** @internal */ + private async _withUrlsCallbackInternal(callback: (obj: ResourceUrlsCallbackContext) => Promise): Promise { + const callbackId = registerCallback(async (objData: unknown) => { + const objHandle = wrapIfHandle(objData) as ResourceUrlsCallbackContextHandle; + const obj = new ResourceUrlsCallbackContext(objHandle, this._client); + await callback(obj); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrlsCallback', + rpcArgs + ); + return new AzureDataLakeStorageFileSystemResource(result, this._client); + } + + /** Customizes displayed URLs via callback */ + withUrlsCallback(callback: (obj: ResourceUrlsCallbackContext) => Promise): AzureDataLakeStorageFileSystemResourcePromise { + return new AzureDataLakeStorageFileSystemResourcePromise(this._withUrlsCallbackInternal(callback)); + } + + /** @internal */ + private async _withUrlsCallbackAsyncInternal(callback: (arg: ResourceUrlsCallbackContext) => Promise): Promise { + const callbackId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as ResourceUrlsCallbackContextHandle; + const arg = new ResourceUrlsCallbackContext(argHandle, this._client); + await callback(arg); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrlsCallbackAsync', + rpcArgs + ); + return new AzureDataLakeStorageFileSystemResource(result, this._client); + } + + /** Customizes displayed URLs via async callback */ + withUrlsCallbackAsync(callback: (arg: ResourceUrlsCallbackContext) => Promise): AzureDataLakeStorageFileSystemResourcePromise { + return new AzureDataLakeStorageFileSystemResourcePromise(this._withUrlsCallbackAsyncInternal(callback)); + } + + /** @internal */ + private async _withUrlInternal(url: string, displayText?: string): Promise { + const rpcArgs: Record = { builder: this._handle, url }; + if (displayText !== undefined) rpcArgs.displayText = displayText; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrl', + rpcArgs + ); + return new AzureDataLakeStorageFileSystemResource(result, this._client); + } + + /** Adds or modifies displayed URLs */ + withUrl(url: string, options?: WithUrlOptions): AzureDataLakeStorageFileSystemResourcePromise { + const displayText = options?.displayText; + return new AzureDataLakeStorageFileSystemResourcePromise(this._withUrlInternal(url, displayText)); + } + + /** @internal */ + private async _withUrlExpressionInternal(url: ReferenceExpression, displayText?: string): Promise { + const rpcArgs: Record = { builder: this._handle, url }; + if (displayText !== undefined) rpcArgs.displayText = displayText; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrlExpression', + rpcArgs + ); + return new AzureDataLakeStorageFileSystemResource(result, this._client); + } + + /** Adds a URL using a reference expression */ + withUrlExpression(url: ReferenceExpression, options?: WithUrlExpressionOptions): AzureDataLakeStorageFileSystemResourcePromise { + const displayText = options?.displayText; + return new AzureDataLakeStorageFileSystemResourcePromise(this._withUrlExpressionInternal(url, displayText)); + } + + /** @internal */ + private async _withUrlForEndpointInternal(endpointName: string, callback: (obj: ResourceUrlAnnotation) => Promise): Promise { + const callbackId = registerCallback(async (objData: unknown) => { + const obj = wrapIfHandle(objData) as ResourceUrlAnnotation; + await callback(obj); + }); + const rpcArgs: Record = { builder: this._handle, endpointName, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrlForEndpoint', + rpcArgs + ); + return new AzureDataLakeStorageFileSystemResource(result, this._client); + } + + /** Customizes the URL for a specific endpoint via callback */ + withUrlForEndpoint(endpointName: string, callback: (obj: ResourceUrlAnnotation) => Promise): AzureDataLakeStorageFileSystemResourcePromise { + return new AzureDataLakeStorageFileSystemResourcePromise(this._withUrlForEndpointInternal(endpointName, callback)); + } + + /** @internal */ + private async _excludeFromManifestInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/excludeFromManifest', + rpcArgs + ); + return new AzureDataLakeStorageFileSystemResource(result, this._client); + } + + /** Excludes the resource from the deployment manifest */ + excludeFromManifest(): AzureDataLakeStorageFileSystemResourcePromise { + return new AzureDataLakeStorageFileSystemResourcePromise(this._excludeFromManifestInternal()); + } + + /** @internal */ + private async _withExplicitStartInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withExplicitStart', + rpcArgs + ); + return new AzureDataLakeStorageFileSystemResource(result, this._client); + } + + /** Prevents resource from starting automatically */ + withExplicitStart(): AzureDataLakeStorageFileSystemResourcePromise { + return new AzureDataLakeStorageFileSystemResourcePromise(this._withExplicitStartInternal()); + } + + /** @internal */ + private async _withHealthCheckInternal(key: string): Promise { + const rpcArgs: Record = { builder: this._handle, key }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withHealthCheck', + rpcArgs + ); + return new AzureDataLakeStorageFileSystemResource(result, this._client); + } + + /** Adds a health check by key */ + withHealthCheck(key: string): AzureDataLakeStorageFileSystemResourcePromise { + return new AzureDataLakeStorageFileSystemResourcePromise(this._withHealthCheckInternal(key)); + } + + /** @internal */ + private async _withCommandInternal(name: string, displayName: string, executeCommand: (arg: ExecuteCommandContext) => Promise, commandOptions?: CommandOptions): Promise { + const executeCommandId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as ExecuteCommandContextHandle; + const arg = new ExecuteCommandContext(argHandle, this._client); + return await executeCommand(arg); + }); + const rpcArgs: Record = { builder: this._handle, name, displayName, executeCommand: executeCommandId }; + if (commandOptions !== undefined) rpcArgs.commandOptions = commandOptions; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withCommand', + rpcArgs + ); + return new AzureDataLakeStorageFileSystemResource(result, this._client); + } + + /** Adds a resource command */ + withCommand(name: string, displayName: string, executeCommand: (arg: ExecuteCommandContext) => Promise, options?: WithCommandOptions): AzureDataLakeStorageFileSystemResourcePromise { + const commandOptions = options?.commandOptions; + return new AzureDataLakeStorageFileSystemResourcePromise(this._withCommandInternal(name, displayName, executeCommand, commandOptions)); + } + + /** @internal */ + private async _withParentRelationshipInternal(parent: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, parent }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withParentRelationship', + rpcArgs + ); + return new AzureDataLakeStorageFileSystemResource(result, this._client); + } + + /** Sets the parent relationship */ + withParentRelationship(parent: ResourceBuilderBase): AzureDataLakeStorageFileSystemResourcePromise { + return new AzureDataLakeStorageFileSystemResourcePromise(this._withParentRelationshipInternal(parent)); + } + + /** @internal */ + private async _withChildRelationshipInternal(child: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, child }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withChildRelationship', + rpcArgs + ); + return new AzureDataLakeStorageFileSystemResource(result, this._client); + } + + /** Sets a child relationship */ + withChildRelationship(child: ResourceBuilderBase): AzureDataLakeStorageFileSystemResourcePromise { + return new AzureDataLakeStorageFileSystemResourcePromise(this._withChildRelationshipInternal(child)); + } + + /** @internal */ + private async _withIconNameInternal(iconName: string, iconVariant?: IconVariant): Promise { + const rpcArgs: Record = { builder: this._handle, iconName }; + if (iconVariant !== undefined) rpcArgs.iconVariant = iconVariant; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withIconName', + rpcArgs + ); + return new AzureDataLakeStorageFileSystemResource(result, this._client); + } + + /** Sets the icon for the resource */ + withIconName(iconName: string, options?: WithIconNameOptions): AzureDataLakeStorageFileSystemResourcePromise { + const iconVariant = options?.iconVariant; + return new AzureDataLakeStorageFileSystemResourcePromise(this._withIconNameInternal(iconName, iconVariant)); + } + + /** @internal */ + private async _excludeFromMcpInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/excludeFromMcp', + rpcArgs + ); + return new AzureDataLakeStorageFileSystemResource(result, this._client); + } + + /** Excludes the resource from MCP server exposure */ + excludeFromMcp(): AzureDataLakeStorageFileSystemResourcePromise { + return new AzureDataLakeStorageFileSystemResourcePromise(this._excludeFromMcpInternal()); + } + + /** @internal */ + private async _withPipelineStepFactoryInternal(stepName: string, callback: (arg: PipelineStepContext) => Promise, dependsOn?: string[], requiredBy?: string[], tags?: string[], description?: string): Promise { + const callbackId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as PipelineStepContextHandle; + const arg = new PipelineStepContext(argHandle, this._client); + await callback(arg); + }); + const rpcArgs: Record = { builder: this._handle, stepName, callback: callbackId }; + if (dependsOn !== undefined) rpcArgs.dependsOn = dependsOn; + if (requiredBy !== undefined) rpcArgs.requiredBy = requiredBy; + if (tags !== undefined) rpcArgs.tags = tags; + if (description !== undefined) rpcArgs.description = description; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withPipelineStepFactory', + rpcArgs + ); + return new AzureDataLakeStorageFileSystemResource(result, this._client); + } + + /** Adds a pipeline step to the resource */ + withPipelineStepFactory(stepName: string, callback: (arg: PipelineStepContext) => Promise, options?: WithPipelineStepFactoryOptions): AzureDataLakeStorageFileSystemResourcePromise { + const dependsOn = options?.dependsOn; + const requiredBy = options?.requiredBy; + const tags = options?.tags; + const description = options?.description; + return new AzureDataLakeStorageFileSystemResourcePromise(this._withPipelineStepFactoryInternal(stepName, callback, dependsOn, requiredBy, tags, description)); + } + + /** @internal */ + private async _withPipelineConfigurationAsyncInternal(callback: (arg: PipelineConfigurationContext) => Promise): Promise { + const callbackId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as PipelineConfigurationContextHandle; + const arg = new PipelineConfigurationContext(argHandle, this._client); + await callback(arg); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withPipelineConfigurationAsync', + rpcArgs + ); + return new AzureDataLakeStorageFileSystemResource(result, this._client); + } + + /** Configures pipeline step dependencies via an async callback */ + withPipelineConfigurationAsync(callback: (arg: PipelineConfigurationContext) => Promise): AzureDataLakeStorageFileSystemResourcePromise { + return new AzureDataLakeStorageFileSystemResourcePromise(this._withPipelineConfigurationAsyncInternal(callback)); + } + + /** @internal */ + private async _withPipelineConfigurationInternal(callback: (obj: PipelineConfigurationContext) => Promise): Promise { + const callbackId = registerCallback(async (objData: unknown) => { + const objHandle = wrapIfHandle(objData) as PipelineConfigurationContextHandle; + const obj = new PipelineConfigurationContext(objHandle, this._client); + await callback(obj); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withPipelineConfiguration', + rpcArgs + ); + return new AzureDataLakeStorageFileSystemResource(result, this._client); + } + + /** Configures pipeline step dependencies via a callback */ + withPipelineConfiguration(callback: (obj: PipelineConfigurationContext) => Promise): AzureDataLakeStorageFileSystemResourcePromise { + return new AzureDataLakeStorageFileSystemResourcePromise(this._withPipelineConfigurationInternal(callback)); + } + + /** Gets the resource name */ + async getResourceName(): Promise { + const rpcArgs: Record = { resource: this._handle }; + return await this._client.invokeCapability( + 'Aspire.Hosting/getResourceName', + rpcArgs + ); + } + + /** @internal */ + private async _withStorageRoleAssignmentsInternal(target: AzureStorageResource, roles: AzureStorageRole[]): Promise { + const rpcArgs: Record = { builder: this._handle, target, roles }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure.Storage/withStorageRoleAssignments', + rpcArgs + ); + return new AzureDataLakeStorageFileSystemResource(result, this._client); + } + + /** Assigns Azure Storage roles to a resource */ + withStorageRoleAssignments(target: AzureStorageResource, roles: AzureStorageRole[]): AzureDataLakeStorageFileSystemResourcePromise { + return new AzureDataLakeStorageFileSystemResourcePromise(this._withStorageRoleAssignmentsInternal(target, roles)); + } + + /** @internal */ + private async _withEventHubsRoleAssignmentsInternal(target: AzureEventHubsResource, roles: AzureEventHubsRole[]): Promise { + const rpcArgs: Record = { builder: this._handle, target, roles }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure.EventHubs/withEventHubsRoleAssignments', + rpcArgs + ); + return new AzureDataLakeStorageFileSystemResource(result, this._client); + } + + /** Assigns Event Hubs roles to a resource */ + withEventHubsRoleAssignments(target: AzureEventHubsResource, roles: AzureEventHubsRole[]): AzureDataLakeStorageFileSystemResourcePromise { + return new AzureDataLakeStorageFileSystemResourcePromise(this._withEventHubsRoleAssignmentsInternal(target, roles)); + } + +} + +/** + * Thenable wrapper for AzureDataLakeStorageFileSystemResource that enables fluent chaining. + * @example + * await builder.addSomething().withX().withY(); + */ +export class AzureDataLakeStorageFileSystemResourcePromise implements PromiseLike { + constructor(private _promise: Promise) {} + + then( + onfulfilled?: ((value: AzureDataLakeStorageFileSystemResource) => TResult1 | PromiseLike) | null, + onrejected?: ((reason: unknown) => TResult2 | PromiseLike) | null + ): PromiseLike { + return this._promise.then(onfulfilled, onrejected); + } + + /** Configures a resource to use a container registry */ + withContainerRegistry(registry: ResourceBuilderBase): AzureDataLakeStorageFileSystemResourcePromise { + return new AzureDataLakeStorageFileSystemResourcePromise(this._promise.then(obj => obj.withContainerRegistry(registry))); + } + + /** Sets the base image for a Dockerfile build */ + withDockerfileBaseImage(options?: WithDockerfileBaseImageOptions): AzureDataLakeStorageFileSystemResourcePromise { + return new AzureDataLakeStorageFileSystemResourcePromise(this._promise.then(obj => obj.withDockerfileBaseImage(options))); + } + + /** Adds a required command dependency */ + withRequiredCommand(command: string, options?: WithRequiredCommandOptions): AzureDataLakeStorageFileSystemResourcePromise { + return new AzureDataLakeStorageFileSystemResourcePromise(this._promise.then(obj => obj.withRequiredCommand(command, options))); + } + + /** Adds a connection property with a reference expression */ + withConnectionProperty(name: string, value: ReferenceExpression): AzureDataLakeStorageFileSystemResourcePromise { + return new AzureDataLakeStorageFileSystemResourcePromise(this._promise.then(obj => obj.withConnectionProperty(name, value))); + } + + /** Adds a connection property with a string value */ + withConnectionPropertyValue(name: string, value: string): AzureDataLakeStorageFileSystemResourcePromise { + return new AzureDataLakeStorageFileSystemResourcePromise(this._promise.then(obj => obj.withConnectionPropertyValue(name, value))); + } + + /** Customizes displayed URLs via callback */ + withUrlsCallback(callback: (obj: ResourceUrlsCallbackContext) => Promise): AzureDataLakeStorageFileSystemResourcePromise { + return new AzureDataLakeStorageFileSystemResourcePromise(this._promise.then(obj => obj.withUrlsCallback(callback))); + } + + /** Customizes displayed URLs via async callback */ + withUrlsCallbackAsync(callback: (arg: ResourceUrlsCallbackContext) => Promise): AzureDataLakeStorageFileSystemResourcePromise { + return new AzureDataLakeStorageFileSystemResourcePromise(this._promise.then(obj => obj.withUrlsCallbackAsync(callback))); + } + + /** Adds or modifies displayed URLs */ + withUrl(url: string, options?: WithUrlOptions): AzureDataLakeStorageFileSystemResourcePromise { + return new AzureDataLakeStorageFileSystemResourcePromise(this._promise.then(obj => obj.withUrl(url, options))); + } + + /** Adds a URL using a reference expression */ + withUrlExpression(url: ReferenceExpression, options?: WithUrlExpressionOptions): AzureDataLakeStorageFileSystemResourcePromise { + return new AzureDataLakeStorageFileSystemResourcePromise(this._promise.then(obj => obj.withUrlExpression(url, options))); + } + + /** Customizes the URL for a specific endpoint via callback */ + withUrlForEndpoint(endpointName: string, callback: (obj: ResourceUrlAnnotation) => Promise): AzureDataLakeStorageFileSystemResourcePromise { + return new AzureDataLakeStorageFileSystemResourcePromise(this._promise.then(obj => obj.withUrlForEndpoint(endpointName, callback))); + } + + /** Excludes the resource from the deployment manifest */ + excludeFromManifest(): AzureDataLakeStorageFileSystemResourcePromise { + return new AzureDataLakeStorageFileSystemResourcePromise(this._promise.then(obj => obj.excludeFromManifest())); + } + + /** Prevents resource from starting automatically */ + withExplicitStart(): AzureDataLakeStorageFileSystemResourcePromise { + return new AzureDataLakeStorageFileSystemResourcePromise(this._promise.then(obj => obj.withExplicitStart())); + } + + /** Adds a health check by key */ + withHealthCheck(key: string): AzureDataLakeStorageFileSystemResourcePromise { + return new AzureDataLakeStorageFileSystemResourcePromise(this._promise.then(obj => obj.withHealthCheck(key))); + } + + /** Adds a resource command */ + withCommand(name: string, displayName: string, executeCommand: (arg: ExecuteCommandContext) => Promise, options?: WithCommandOptions): AzureDataLakeStorageFileSystemResourcePromise { + return new AzureDataLakeStorageFileSystemResourcePromise(this._promise.then(obj => obj.withCommand(name, displayName, executeCommand, options))); + } + + /** Sets the parent relationship */ + withParentRelationship(parent: ResourceBuilderBase): AzureDataLakeStorageFileSystemResourcePromise { + return new AzureDataLakeStorageFileSystemResourcePromise(this._promise.then(obj => obj.withParentRelationship(parent))); + } + + /** Sets a child relationship */ + withChildRelationship(child: ResourceBuilderBase): AzureDataLakeStorageFileSystemResourcePromise { + return new AzureDataLakeStorageFileSystemResourcePromise(this._promise.then(obj => obj.withChildRelationship(child))); + } + + /** Sets the icon for the resource */ + withIconName(iconName: string, options?: WithIconNameOptions): AzureDataLakeStorageFileSystemResourcePromise { + return new AzureDataLakeStorageFileSystemResourcePromise(this._promise.then(obj => obj.withIconName(iconName, options))); + } + + /** Excludes the resource from MCP server exposure */ + excludeFromMcp(): AzureDataLakeStorageFileSystemResourcePromise { + return new AzureDataLakeStorageFileSystemResourcePromise(this._promise.then(obj => obj.excludeFromMcp())); + } + + /** Adds a pipeline step to the resource */ + withPipelineStepFactory(stepName: string, callback: (arg: PipelineStepContext) => Promise, options?: WithPipelineStepFactoryOptions): AzureDataLakeStorageFileSystemResourcePromise { + return new AzureDataLakeStorageFileSystemResourcePromise(this._promise.then(obj => obj.withPipelineStepFactory(stepName, callback, options))); + } + + /** Configures pipeline step dependencies via an async callback */ + withPipelineConfigurationAsync(callback: (arg: PipelineConfigurationContext) => Promise): AzureDataLakeStorageFileSystemResourcePromise { + return new AzureDataLakeStorageFileSystemResourcePromise(this._promise.then(obj => obj.withPipelineConfigurationAsync(callback))); + } + + /** Configures pipeline step dependencies via a callback */ + withPipelineConfiguration(callback: (obj: PipelineConfigurationContext) => Promise): AzureDataLakeStorageFileSystemResourcePromise { + return new AzureDataLakeStorageFileSystemResourcePromise(this._promise.then(obj => obj.withPipelineConfiguration(callback))); + } + + /** Gets the resource name */ + getResourceName(): Promise { + return this._promise.then(obj => obj.getResourceName()); + } + + /** Assigns Azure Storage roles to a resource */ + withStorageRoleAssignments(target: AzureStorageResource, roles: AzureStorageRole[]): AzureDataLakeStorageFileSystemResourcePromise { + return new AzureDataLakeStorageFileSystemResourcePromise(this._promise.then(obj => obj.withStorageRoleAssignments(target, roles))); + } + + /** Assigns Event Hubs roles to a resource */ + withEventHubsRoleAssignments(target: AzureEventHubsResource, roles: AzureEventHubsRole[]): AzureDataLakeStorageFileSystemResourcePromise { + return new AzureDataLakeStorageFileSystemResourcePromise(this._promise.then(obj => obj.withEventHubsRoleAssignments(target, roles))); + } + +} + +// ============================================================================ +// AzureDataLakeStorageResource +// ============================================================================ + +export class AzureDataLakeStorageResource extends ResourceBuilderBase { + constructor(handle: AzureDataLakeStorageResourceHandle, client: AspireClientRpc) { + super(handle, client); + } + + /** @internal */ + private async _withContainerRegistryInternal(registry: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, registry }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withContainerRegistry', + rpcArgs + ); + return new AzureDataLakeStorageResource(result, this._client); + } + + /** Configures a resource to use a container registry */ + withContainerRegistry(registry: ResourceBuilderBase): AzureDataLakeStorageResourcePromise { + return new AzureDataLakeStorageResourcePromise(this._withContainerRegistryInternal(registry)); + } + + /** @internal */ + private async _withDockerfileBaseImageInternal(buildImage?: string, runtimeImage?: string): Promise { + const rpcArgs: Record = { builder: this._handle }; + if (buildImage !== undefined) rpcArgs.buildImage = buildImage; + if (runtimeImage !== undefined) rpcArgs.runtimeImage = runtimeImage; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withDockerfileBaseImage', + rpcArgs + ); + return new AzureDataLakeStorageResource(result, this._client); + } + + /** Sets the base image for a Dockerfile build */ + withDockerfileBaseImage(options?: WithDockerfileBaseImageOptions): AzureDataLakeStorageResourcePromise { + const buildImage = options?.buildImage; + const runtimeImage = options?.runtimeImage; + return new AzureDataLakeStorageResourcePromise(this._withDockerfileBaseImageInternal(buildImage, runtimeImage)); + } + + /** @internal */ + private async _withRequiredCommandInternal(command: string, helpLink?: string): Promise { + const rpcArgs: Record = { builder: this._handle, command }; + if (helpLink !== undefined) rpcArgs.helpLink = helpLink; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withRequiredCommand', + rpcArgs + ); + return new AzureDataLakeStorageResource(result, this._client); + } + + /** Adds a required command dependency */ + withRequiredCommand(command: string, options?: WithRequiredCommandOptions): AzureDataLakeStorageResourcePromise { + const helpLink = options?.helpLink; + return new AzureDataLakeStorageResourcePromise(this._withRequiredCommandInternal(command, helpLink)); + } + + /** @internal */ + private async _withConnectionPropertyInternal(name: string, value: ReferenceExpression): Promise { + const rpcArgs: Record = { builder: this._handle, name, value }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withConnectionProperty', + rpcArgs + ); + return new AzureDataLakeStorageResource(result, this._client); + } + + /** Adds a connection property with a reference expression */ + withConnectionProperty(name: string, value: ReferenceExpression): AzureDataLakeStorageResourcePromise { + return new AzureDataLakeStorageResourcePromise(this._withConnectionPropertyInternal(name, value)); + } + + /** @internal */ + private async _withConnectionPropertyValueInternal(name: string, value: string): Promise { + const rpcArgs: Record = { builder: this._handle, name, value }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withConnectionPropertyValue', + rpcArgs + ); + return new AzureDataLakeStorageResource(result, this._client); + } + + /** Adds a connection property with a string value */ + withConnectionPropertyValue(name: string, value: string): AzureDataLakeStorageResourcePromise { + return new AzureDataLakeStorageResourcePromise(this._withConnectionPropertyValueInternal(name, value)); + } + + /** @internal */ + private async _withUrlsCallbackInternal(callback: (obj: ResourceUrlsCallbackContext) => Promise): Promise { + const callbackId = registerCallback(async (objData: unknown) => { + const objHandle = wrapIfHandle(objData) as ResourceUrlsCallbackContextHandle; + const obj = new ResourceUrlsCallbackContext(objHandle, this._client); + await callback(obj); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrlsCallback', + rpcArgs + ); + return new AzureDataLakeStorageResource(result, this._client); + } + + /** Customizes displayed URLs via callback */ + withUrlsCallback(callback: (obj: ResourceUrlsCallbackContext) => Promise): AzureDataLakeStorageResourcePromise { + return new AzureDataLakeStorageResourcePromise(this._withUrlsCallbackInternal(callback)); + } + + /** @internal */ + private async _withUrlsCallbackAsyncInternal(callback: (arg: ResourceUrlsCallbackContext) => Promise): Promise { + const callbackId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as ResourceUrlsCallbackContextHandle; + const arg = new ResourceUrlsCallbackContext(argHandle, this._client); + await callback(arg); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrlsCallbackAsync', + rpcArgs + ); + return new AzureDataLakeStorageResource(result, this._client); + } + + /** Customizes displayed URLs via async callback */ + withUrlsCallbackAsync(callback: (arg: ResourceUrlsCallbackContext) => Promise): AzureDataLakeStorageResourcePromise { + return new AzureDataLakeStorageResourcePromise(this._withUrlsCallbackAsyncInternal(callback)); + } + + /** @internal */ + private async _withUrlInternal(url: string, displayText?: string): Promise { + const rpcArgs: Record = { builder: this._handle, url }; + if (displayText !== undefined) rpcArgs.displayText = displayText; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrl', + rpcArgs + ); + return new AzureDataLakeStorageResource(result, this._client); + } + + /** Adds or modifies displayed URLs */ + withUrl(url: string, options?: WithUrlOptions): AzureDataLakeStorageResourcePromise { + const displayText = options?.displayText; + return new AzureDataLakeStorageResourcePromise(this._withUrlInternal(url, displayText)); + } + + /** @internal */ + private async _withUrlExpressionInternal(url: ReferenceExpression, displayText?: string): Promise { + const rpcArgs: Record = { builder: this._handle, url }; + if (displayText !== undefined) rpcArgs.displayText = displayText; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrlExpression', + rpcArgs + ); + return new AzureDataLakeStorageResource(result, this._client); + } + + /** Adds a URL using a reference expression */ + withUrlExpression(url: ReferenceExpression, options?: WithUrlExpressionOptions): AzureDataLakeStorageResourcePromise { + const displayText = options?.displayText; + return new AzureDataLakeStorageResourcePromise(this._withUrlExpressionInternal(url, displayText)); + } + + /** @internal */ + private async _withUrlForEndpointInternal(endpointName: string, callback: (obj: ResourceUrlAnnotation) => Promise): Promise { + const callbackId = registerCallback(async (objData: unknown) => { + const obj = wrapIfHandle(objData) as ResourceUrlAnnotation; + await callback(obj); + }); + const rpcArgs: Record = { builder: this._handle, endpointName, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrlForEndpoint', + rpcArgs + ); + return new AzureDataLakeStorageResource(result, this._client); + } + + /** Customizes the URL for a specific endpoint via callback */ + withUrlForEndpoint(endpointName: string, callback: (obj: ResourceUrlAnnotation) => Promise): AzureDataLakeStorageResourcePromise { + return new AzureDataLakeStorageResourcePromise(this._withUrlForEndpointInternal(endpointName, callback)); + } + + /** @internal */ + private async _excludeFromManifestInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/excludeFromManifest', + rpcArgs + ); + return new AzureDataLakeStorageResource(result, this._client); + } + + /** Excludes the resource from the deployment manifest */ + excludeFromManifest(): AzureDataLakeStorageResourcePromise { + return new AzureDataLakeStorageResourcePromise(this._excludeFromManifestInternal()); + } + + /** @internal */ + private async _withExplicitStartInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withExplicitStart', + rpcArgs + ); + return new AzureDataLakeStorageResource(result, this._client); + } + + /** Prevents resource from starting automatically */ + withExplicitStart(): AzureDataLakeStorageResourcePromise { + return new AzureDataLakeStorageResourcePromise(this._withExplicitStartInternal()); + } + + /** @internal */ + private async _withHealthCheckInternal(key: string): Promise { + const rpcArgs: Record = { builder: this._handle, key }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withHealthCheck', + rpcArgs + ); + return new AzureDataLakeStorageResource(result, this._client); + } + + /** Adds a health check by key */ + withHealthCheck(key: string): AzureDataLakeStorageResourcePromise { + return new AzureDataLakeStorageResourcePromise(this._withHealthCheckInternal(key)); + } + + /** @internal */ + private async _withCommandInternal(name: string, displayName: string, executeCommand: (arg: ExecuteCommandContext) => Promise, commandOptions?: CommandOptions): Promise { + const executeCommandId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as ExecuteCommandContextHandle; + const arg = new ExecuteCommandContext(argHandle, this._client); + return await executeCommand(arg); + }); + const rpcArgs: Record = { builder: this._handle, name, displayName, executeCommand: executeCommandId }; + if (commandOptions !== undefined) rpcArgs.commandOptions = commandOptions; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withCommand', + rpcArgs + ); + return new AzureDataLakeStorageResource(result, this._client); + } + + /** Adds a resource command */ + withCommand(name: string, displayName: string, executeCommand: (arg: ExecuteCommandContext) => Promise, options?: WithCommandOptions): AzureDataLakeStorageResourcePromise { + const commandOptions = options?.commandOptions; + return new AzureDataLakeStorageResourcePromise(this._withCommandInternal(name, displayName, executeCommand, commandOptions)); + } + + /** @internal */ + private async _withParentRelationshipInternal(parent: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, parent }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withParentRelationship', + rpcArgs + ); + return new AzureDataLakeStorageResource(result, this._client); + } + + /** Sets the parent relationship */ + withParentRelationship(parent: ResourceBuilderBase): AzureDataLakeStorageResourcePromise { + return new AzureDataLakeStorageResourcePromise(this._withParentRelationshipInternal(parent)); + } + + /** @internal */ + private async _withChildRelationshipInternal(child: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, child }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withChildRelationship', + rpcArgs + ); + return new AzureDataLakeStorageResource(result, this._client); + } + + /** Sets a child relationship */ + withChildRelationship(child: ResourceBuilderBase): AzureDataLakeStorageResourcePromise { + return new AzureDataLakeStorageResourcePromise(this._withChildRelationshipInternal(child)); + } + + /** @internal */ + private async _withIconNameInternal(iconName: string, iconVariant?: IconVariant): Promise { + const rpcArgs: Record = { builder: this._handle, iconName }; + if (iconVariant !== undefined) rpcArgs.iconVariant = iconVariant; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withIconName', + rpcArgs + ); + return new AzureDataLakeStorageResource(result, this._client); + } + + /** Sets the icon for the resource */ + withIconName(iconName: string, options?: WithIconNameOptions): AzureDataLakeStorageResourcePromise { + const iconVariant = options?.iconVariant; + return new AzureDataLakeStorageResourcePromise(this._withIconNameInternal(iconName, iconVariant)); + } + + /** @internal */ + private async _excludeFromMcpInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/excludeFromMcp', + rpcArgs + ); + return new AzureDataLakeStorageResource(result, this._client); + } + + /** Excludes the resource from MCP server exposure */ + excludeFromMcp(): AzureDataLakeStorageResourcePromise { + return new AzureDataLakeStorageResourcePromise(this._excludeFromMcpInternal()); + } + + /** @internal */ + private async _withPipelineStepFactoryInternal(stepName: string, callback: (arg: PipelineStepContext) => Promise, dependsOn?: string[], requiredBy?: string[], tags?: string[], description?: string): Promise { + const callbackId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as PipelineStepContextHandle; + const arg = new PipelineStepContext(argHandle, this._client); + await callback(arg); + }); + const rpcArgs: Record = { builder: this._handle, stepName, callback: callbackId }; + if (dependsOn !== undefined) rpcArgs.dependsOn = dependsOn; + if (requiredBy !== undefined) rpcArgs.requiredBy = requiredBy; + if (tags !== undefined) rpcArgs.tags = tags; + if (description !== undefined) rpcArgs.description = description; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withPipelineStepFactory', + rpcArgs + ); + return new AzureDataLakeStorageResource(result, this._client); + } + + /** Adds a pipeline step to the resource */ + withPipelineStepFactory(stepName: string, callback: (arg: PipelineStepContext) => Promise, options?: WithPipelineStepFactoryOptions): AzureDataLakeStorageResourcePromise { + const dependsOn = options?.dependsOn; + const requiredBy = options?.requiredBy; + const tags = options?.tags; + const description = options?.description; + return new AzureDataLakeStorageResourcePromise(this._withPipelineStepFactoryInternal(stepName, callback, dependsOn, requiredBy, tags, description)); + } + + /** @internal */ + private async _withPipelineConfigurationAsyncInternal(callback: (arg: PipelineConfigurationContext) => Promise): Promise { + const callbackId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as PipelineConfigurationContextHandle; + const arg = new PipelineConfigurationContext(argHandle, this._client); + await callback(arg); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withPipelineConfigurationAsync', + rpcArgs + ); + return new AzureDataLakeStorageResource(result, this._client); + } + + /** Configures pipeline step dependencies via an async callback */ + withPipelineConfigurationAsync(callback: (arg: PipelineConfigurationContext) => Promise): AzureDataLakeStorageResourcePromise { + return new AzureDataLakeStorageResourcePromise(this._withPipelineConfigurationAsyncInternal(callback)); + } + + /** @internal */ + private async _withPipelineConfigurationInternal(callback: (obj: PipelineConfigurationContext) => Promise): Promise { + const callbackId = registerCallback(async (objData: unknown) => { + const objHandle = wrapIfHandle(objData) as PipelineConfigurationContextHandle; + const obj = new PipelineConfigurationContext(objHandle, this._client); + await callback(obj); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withPipelineConfiguration', + rpcArgs + ); + return new AzureDataLakeStorageResource(result, this._client); + } + + /** Configures pipeline step dependencies via a callback */ + withPipelineConfiguration(callback: (obj: PipelineConfigurationContext) => Promise): AzureDataLakeStorageResourcePromise { + return new AzureDataLakeStorageResourcePromise(this._withPipelineConfigurationInternal(callback)); + } + + /** Gets the resource name */ + async getResourceName(): Promise { + const rpcArgs: Record = { resource: this._handle }; + return await this._client.invokeCapability( + 'Aspire.Hosting/getResourceName', + rpcArgs + ); + } + + /** @internal */ + private async _withStorageRoleAssignmentsInternal(target: AzureStorageResource, roles: AzureStorageRole[]): Promise { + const rpcArgs: Record = { builder: this._handle, target, roles }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure.Storage/withStorageRoleAssignments', + rpcArgs + ); + return new AzureDataLakeStorageResource(result, this._client); + } + + /** Assigns Azure Storage roles to a resource */ + withStorageRoleAssignments(target: AzureStorageResource, roles: AzureStorageRole[]): AzureDataLakeStorageResourcePromise { + return new AzureDataLakeStorageResourcePromise(this._withStorageRoleAssignmentsInternal(target, roles)); + } + + /** @internal */ + private async _withEventHubsRoleAssignmentsInternal(target: AzureEventHubsResource, roles: AzureEventHubsRole[]): Promise { + const rpcArgs: Record = { builder: this._handle, target, roles }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure.EventHubs/withEventHubsRoleAssignments', + rpcArgs + ); + return new AzureDataLakeStorageResource(result, this._client); + } + + /** Assigns Event Hubs roles to a resource */ + withEventHubsRoleAssignments(target: AzureEventHubsResource, roles: AzureEventHubsRole[]): AzureDataLakeStorageResourcePromise { + return new AzureDataLakeStorageResourcePromise(this._withEventHubsRoleAssignmentsInternal(target, roles)); + } + +} + +/** + * Thenable wrapper for AzureDataLakeStorageResource that enables fluent chaining. + * @example + * await builder.addSomething().withX().withY(); + */ +export class AzureDataLakeStorageResourcePromise implements PromiseLike { + constructor(private _promise: Promise) {} + + then( + onfulfilled?: ((value: AzureDataLakeStorageResource) => TResult1 | PromiseLike) | null, + onrejected?: ((reason: unknown) => TResult2 | PromiseLike) | null + ): PromiseLike { + return this._promise.then(onfulfilled, onrejected); + } + + /** Configures a resource to use a container registry */ + withContainerRegistry(registry: ResourceBuilderBase): AzureDataLakeStorageResourcePromise { + return new AzureDataLakeStorageResourcePromise(this._promise.then(obj => obj.withContainerRegistry(registry))); + } + + /** Sets the base image for a Dockerfile build */ + withDockerfileBaseImage(options?: WithDockerfileBaseImageOptions): AzureDataLakeStorageResourcePromise { + return new AzureDataLakeStorageResourcePromise(this._promise.then(obj => obj.withDockerfileBaseImage(options))); + } + + /** Adds a required command dependency */ + withRequiredCommand(command: string, options?: WithRequiredCommandOptions): AzureDataLakeStorageResourcePromise { + return new AzureDataLakeStorageResourcePromise(this._promise.then(obj => obj.withRequiredCommand(command, options))); + } + + /** Adds a connection property with a reference expression */ + withConnectionProperty(name: string, value: ReferenceExpression): AzureDataLakeStorageResourcePromise { + return new AzureDataLakeStorageResourcePromise(this._promise.then(obj => obj.withConnectionProperty(name, value))); + } + + /** Adds a connection property with a string value */ + withConnectionPropertyValue(name: string, value: string): AzureDataLakeStorageResourcePromise { + return new AzureDataLakeStorageResourcePromise(this._promise.then(obj => obj.withConnectionPropertyValue(name, value))); + } + + /** Customizes displayed URLs via callback */ + withUrlsCallback(callback: (obj: ResourceUrlsCallbackContext) => Promise): AzureDataLakeStorageResourcePromise { + return new AzureDataLakeStorageResourcePromise(this._promise.then(obj => obj.withUrlsCallback(callback))); + } + + /** Customizes displayed URLs via async callback */ + withUrlsCallbackAsync(callback: (arg: ResourceUrlsCallbackContext) => Promise): AzureDataLakeStorageResourcePromise { + return new AzureDataLakeStorageResourcePromise(this._promise.then(obj => obj.withUrlsCallbackAsync(callback))); + } + + /** Adds or modifies displayed URLs */ + withUrl(url: string, options?: WithUrlOptions): AzureDataLakeStorageResourcePromise { + return new AzureDataLakeStorageResourcePromise(this._promise.then(obj => obj.withUrl(url, options))); + } + + /** Adds a URL using a reference expression */ + withUrlExpression(url: ReferenceExpression, options?: WithUrlExpressionOptions): AzureDataLakeStorageResourcePromise { + return new AzureDataLakeStorageResourcePromise(this._promise.then(obj => obj.withUrlExpression(url, options))); + } + + /** Customizes the URL for a specific endpoint via callback */ + withUrlForEndpoint(endpointName: string, callback: (obj: ResourceUrlAnnotation) => Promise): AzureDataLakeStorageResourcePromise { + return new AzureDataLakeStorageResourcePromise(this._promise.then(obj => obj.withUrlForEndpoint(endpointName, callback))); + } + + /** Excludes the resource from the deployment manifest */ + excludeFromManifest(): AzureDataLakeStorageResourcePromise { + return new AzureDataLakeStorageResourcePromise(this._promise.then(obj => obj.excludeFromManifest())); + } + + /** Prevents resource from starting automatically */ + withExplicitStart(): AzureDataLakeStorageResourcePromise { + return new AzureDataLakeStorageResourcePromise(this._promise.then(obj => obj.withExplicitStart())); + } + + /** Adds a health check by key */ + withHealthCheck(key: string): AzureDataLakeStorageResourcePromise { + return new AzureDataLakeStorageResourcePromise(this._promise.then(obj => obj.withHealthCheck(key))); + } + + /** Adds a resource command */ + withCommand(name: string, displayName: string, executeCommand: (arg: ExecuteCommandContext) => Promise, options?: WithCommandOptions): AzureDataLakeStorageResourcePromise { + return new AzureDataLakeStorageResourcePromise(this._promise.then(obj => obj.withCommand(name, displayName, executeCommand, options))); + } + + /** Sets the parent relationship */ + withParentRelationship(parent: ResourceBuilderBase): AzureDataLakeStorageResourcePromise { + return new AzureDataLakeStorageResourcePromise(this._promise.then(obj => obj.withParentRelationship(parent))); + } + + /** Sets a child relationship */ + withChildRelationship(child: ResourceBuilderBase): AzureDataLakeStorageResourcePromise { + return new AzureDataLakeStorageResourcePromise(this._promise.then(obj => obj.withChildRelationship(child))); + } + + /** Sets the icon for the resource */ + withIconName(iconName: string, options?: WithIconNameOptions): AzureDataLakeStorageResourcePromise { + return new AzureDataLakeStorageResourcePromise(this._promise.then(obj => obj.withIconName(iconName, options))); + } + + /** Excludes the resource from MCP server exposure */ + excludeFromMcp(): AzureDataLakeStorageResourcePromise { + return new AzureDataLakeStorageResourcePromise(this._promise.then(obj => obj.excludeFromMcp())); + } + + /** Adds a pipeline step to the resource */ + withPipelineStepFactory(stepName: string, callback: (arg: PipelineStepContext) => Promise, options?: WithPipelineStepFactoryOptions): AzureDataLakeStorageResourcePromise { + return new AzureDataLakeStorageResourcePromise(this._promise.then(obj => obj.withPipelineStepFactory(stepName, callback, options))); + } + + /** Configures pipeline step dependencies via an async callback */ + withPipelineConfigurationAsync(callback: (arg: PipelineConfigurationContext) => Promise): AzureDataLakeStorageResourcePromise { + return new AzureDataLakeStorageResourcePromise(this._promise.then(obj => obj.withPipelineConfigurationAsync(callback))); + } + + /** Configures pipeline step dependencies via a callback */ + withPipelineConfiguration(callback: (obj: PipelineConfigurationContext) => Promise): AzureDataLakeStorageResourcePromise { + return new AzureDataLakeStorageResourcePromise(this._promise.then(obj => obj.withPipelineConfiguration(callback))); + } + + /** Gets the resource name */ + getResourceName(): Promise { + return this._promise.then(obj => obj.getResourceName()); + } + + /** Assigns Azure Storage roles to a resource */ + withStorageRoleAssignments(target: AzureStorageResource, roles: AzureStorageRole[]): AzureDataLakeStorageResourcePromise { + return new AzureDataLakeStorageResourcePromise(this._promise.then(obj => obj.withStorageRoleAssignments(target, roles))); + } + + /** Assigns Event Hubs roles to a resource */ + withEventHubsRoleAssignments(target: AzureEventHubsResource, roles: AzureEventHubsRole[]): AzureDataLakeStorageResourcePromise { + return new AzureDataLakeStorageResourcePromise(this._promise.then(obj => obj.withEventHubsRoleAssignments(target, roles))); + } + +} + +// ============================================================================ +// AzureEnvironmentResource +// ============================================================================ + +export class AzureEnvironmentResource extends ResourceBuilderBase { + constructor(handle: AzureEnvironmentResourceHandle, client: AspireClientRpc) { + super(handle, client); + } + + /** @internal */ + private async _withContainerRegistryInternal(registry: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, registry }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withContainerRegistry', + rpcArgs + ); + return new AzureEnvironmentResource(result, this._client); + } + + /** Configures a resource to use a container registry */ + withContainerRegistry(registry: ResourceBuilderBase): AzureEnvironmentResourcePromise { + return new AzureEnvironmentResourcePromise(this._withContainerRegistryInternal(registry)); + } + + /** @internal */ + private async _withDockerfileBaseImageInternal(buildImage?: string, runtimeImage?: string): Promise { + const rpcArgs: Record = { builder: this._handle }; + if (buildImage !== undefined) rpcArgs.buildImage = buildImage; + if (runtimeImage !== undefined) rpcArgs.runtimeImage = runtimeImage; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withDockerfileBaseImage', + rpcArgs + ); + return new AzureEnvironmentResource(result, this._client); + } + + /** Sets the base image for a Dockerfile build */ + withDockerfileBaseImage(options?: WithDockerfileBaseImageOptions): AzureEnvironmentResourcePromise { + const buildImage = options?.buildImage; + const runtimeImage = options?.runtimeImage; + return new AzureEnvironmentResourcePromise(this._withDockerfileBaseImageInternal(buildImage, runtimeImage)); + } + + /** @internal */ + private async _withRequiredCommandInternal(command: string, helpLink?: string): Promise { + const rpcArgs: Record = { builder: this._handle, command }; + if (helpLink !== undefined) rpcArgs.helpLink = helpLink; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withRequiredCommand', + rpcArgs + ); + return new AzureEnvironmentResource(result, this._client); + } + + /** Adds a required command dependency */ + withRequiredCommand(command: string, options?: WithRequiredCommandOptions): AzureEnvironmentResourcePromise { + const helpLink = options?.helpLink; + return new AzureEnvironmentResourcePromise(this._withRequiredCommandInternal(command, helpLink)); + } + + /** @internal */ + private async _withUrlsCallbackInternal(callback: (obj: ResourceUrlsCallbackContext) => Promise): Promise { + const callbackId = registerCallback(async (objData: unknown) => { + const objHandle = wrapIfHandle(objData) as ResourceUrlsCallbackContextHandle; + const obj = new ResourceUrlsCallbackContext(objHandle, this._client); + await callback(obj); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrlsCallback', + rpcArgs + ); + return new AzureEnvironmentResource(result, this._client); + } + + /** Customizes displayed URLs via callback */ + withUrlsCallback(callback: (obj: ResourceUrlsCallbackContext) => Promise): AzureEnvironmentResourcePromise { + return new AzureEnvironmentResourcePromise(this._withUrlsCallbackInternal(callback)); + } + + /** @internal */ + private async _withUrlsCallbackAsyncInternal(callback: (arg: ResourceUrlsCallbackContext) => Promise): Promise { + const callbackId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as ResourceUrlsCallbackContextHandle; + const arg = new ResourceUrlsCallbackContext(argHandle, this._client); + await callback(arg); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrlsCallbackAsync', + rpcArgs + ); + return new AzureEnvironmentResource(result, this._client); + } + + /** Customizes displayed URLs via async callback */ + withUrlsCallbackAsync(callback: (arg: ResourceUrlsCallbackContext) => Promise): AzureEnvironmentResourcePromise { + return new AzureEnvironmentResourcePromise(this._withUrlsCallbackAsyncInternal(callback)); + } + + /** @internal */ + private async _withUrlInternal(url: string, displayText?: string): Promise { + const rpcArgs: Record = { builder: this._handle, url }; + if (displayText !== undefined) rpcArgs.displayText = displayText; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrl', + rpcArgs + ); + return new AzureEnvironmentResource(result, this._client); + } + + /** Adds or modifies displayed URLs */ + withUrl(url: string, options?: WithUrlOptions): AzureEnvironmentResourcePromise { + const displayText = options?.displayText; + return new AzureEnvironmentResourcePromise(this._withUrlInternal(url, displayText)); + } + + /** @internal */ + private async _withUrlExpressionInternal(url: ReferenceExpression, displayText?: string): Promise { + const rpcArgs: Record = { builder: this._handle, url }; + if (displayText !== undefined) rpcArgs.displayText = displayText; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrlExpression', + rpcArgs + ); + return new AzureEnvironmentResource(result, this._client); + } + + /** Adds a URL using a reference expression */ + withUrlExpression(url: ReferenceExpression, options?: WithUrlExpressionOptions): AzureEnvironmentResourcePromise { + const displayText = options?.displayText; + return new AzureEnvironmentResourcePromise(this._withUrlExpressionInternal(url, displayText)); + } + + /** @internal */ + private async _withUrlForEndpointInternal(endpointName: string, callback: (obj: ResourceUrlAnnotation) => Promise): Promise { + const callbackId = registerCallback(async (objData: unknown) => { + const obj = wrapIfHandle(objData) as ResourceUrlAnnotation; + await callback(obj); + }); + const rpcArgs: Record = { builder: this._handle, endpointName, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrlForEndpoint', + rpcArgs + ); + return new AzureEnvironmentResource(result, this._client); + } + + /** Customizes the URL for a specific endpoint via callback */ + withUrlForEndpoint(endpointName: string, callback: (obj: ResourceUrlAnnotation) => Promise): AzureEnvironmentResourcePromise { + return new AzureEnvironmentResourcePromise(this._withUrlForEndpointInternal(endpointName, callback)); + } + + /** @internal */ + private async _excludeFromManifestInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/excludeFromManifest', + rpcArgs + ); + return new AzureEnvironmentResource(result, this._client); + } + + /** Excludes the resource from the deployment manifest */ + excludeFromManifest(): AzureEnvironmentResourcePromise { + return new AzureEnvironmentResourcePromise(this._excludeFromManifestInternal()); + } + + /** @internal */ + private async _withExplicitStartInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withExplicitStart', + rpcArgs + ); + return new AzureEnvironmentResource(result, this._client); + } + + /** Prevents resource from starting automatically */ + withExplicitStart(): AzureEnvironmentResourcePromise { + return new AzureEnvironmentResourcePromise(this._withExplicitStartInternal()); + } + + /** @internal */ + private async _withHealthCheckInternal(key: string): Promise { + const rpcArgs: Record = { builder: this._handle, key }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withHealthCheck', + rpcArgs + ); + return new AzureEnvironmentResource(result, this._client); + } + + /** Adds a health check by key */ + withHealthCheck(key: string): AzureEnvironmentResourcePromise { + return new AzureEnvironmentResourcePromise(this._withHealthCheckInternal(key)); + } + + /** @internal */ + private async _withCommandInternal(name: string, displayName: string, executeCommand: (arg: ExecuteCommandContext) => Promise, commandOptions?: CommandOptions): Promise { + const executeCommandId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as ExecuteCommandContextHandle; + const arg = new ExecuteCommandContext(argHandle, this._client); + return await executeCommand(arg); + }); + const rpcArgs: Record = { builder: this._handle, name, displayName, executeCommand: executeCommandId }; + if (commandOptions !== undefined) rpcArgs.commandOptions = commandOptions; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withCommand', + rpcArgs + ); + return new AzureEnvironmentResource(result, this._client); + } + + /** Adds a resource command */ + withCommand(name: string, displayName: string, executeCommand: (arg: ExecuteCommandContext) => Promise, options?: WithCommandOptions): AzureEnvironmentResourcePromise { + const commandOptions = options?.commandOptions; + return new AzureEnvironmentResourcePromise(this._withCommandInternal(name, displayName, executeCommand, commandOptions)); + } + + /** @internal */ + private async _withParentRelationshipInternal(parent: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, parent }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withParentRelationship', + rpcArgs + ); + return new AzureEnvironmentResource(result, this._client); + } + + /** Sets the parent relationship */ + withParentRelationship(parent: ResourceBuilderBase): AzureEnvironmentResourcePromise { + return new AzureEnvironmentResourcePromise(this._withParentRelationshipInternal(parent)); + } + + /** @internal */ + private async _withChildRelationshipInternal(child: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, child }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withChildRelationship', + rpcArgs + ); + return new AzureEnvironmentResource(result, this._client); + } + + /** Sets a child relationship */ + withChildRelationship(child: ResourceBuilderBase): AzureEnvironmentResourcePromise { + return new AzureEnvironmentResourcePromise(this._withChildRelationshipInternal(child)); + } + + /** @internal */ + private async _withIconNameInternal(iconName: string, iconVariant?: IconVariant): Promise { + const rpcArgs: Record = { builder: this._handle, iconName }; + if (iconVariant !== undefined) rpcArgs.iconVariant = iconVariant; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withIconName', + rpcArgs + ); + return new AzureEnvironmentResource(result, this._client); + } + + /** Sets the icon for the resource */ + withIconName(iconName: string, options?: WithIconNameOptions): AzureEnvironmentResourcePromise { + const iconVariant = options?.iconVariant; + return new AzureEnvironmentResourcePromise(this._withIconNameInternal(iconName, iconVariant)); + } + + /** @internal */ + private async _excludeFromMcpInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/excludeFromMcp', + rpcArgs + ); + return new AzureEnvironmentResource(result, this._client); + } + + /** Excludes the resource from MCP server exposure */ + excludeFromMcp(): AzureEnvironmentResourcePromise { + return new AzureEnvironmentResourcePromise(this._excludeFromMcpInternal()); + } + + /** @internal */ + private async _withPipelineStepFactoryInternal(stepName: string, callback: (arg: PipelineStepContext) => Promise, dependsOn?: string[], requiredBy?: string[], tags?: string[], description?: string): Promise { + const callbackId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as PipelineStepContextHandle; + const arg = new PipelineStepContext(argHandle, this._client); + await callback(arg); + }); + const rpcArgs: Record = { builder: this._handle, stepName, callback: callbackId }; + if (dependsOn !== undefined) rpcArgs.dependsOn = dependsOn; + if (requiredBy !== undefined) rpcArgs.requiredBy = requiredBy; + if (tags !== undefined) rpcArgs.tags = tags; + if (description !== undefined) rpcArgs.description = description; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withPipelineStepFactory', + rpcArgs + ); + return new AzureEnvironmentResource(result, this._client); + } + + /** Adds a pipeline step to the resource */ + withPipelineStepFactory(stepName: string, callback: (arg: PipelineStepContext) => Promise, options?: WithPipelineStepFactoryOptions): AzureEnvironmentResourcePromise { + const dependsOn = options?.dependsOn; + const requiredBy = options?.requiredBy; + const tags = options?.tags; + const description = options?.description; + return new AzureEnvironmentResourcePromise(this._withPipelineStepFactoryInternal(stepName, callback, dependsOn, requiredBy, tags, description)); + } + + /** @internal */ + private async _withPipelineConfigurationAsyncInternal(callback: (arg: PipelineConfigurationContext) => Promise): Promise { + const callbackId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as PipelineConfigurationContextHandle; + const arg = new PipelineConfigurationContext(argHandle, this._client); + await callback(arg); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withPipelineConfigurationAsync', + rpcArgs + ); + return new AzureEnvironmentResource(result, this._client); + } + + /** Configures pipeline step dependencies via an async callback */ + withPipelineConfigurationAsync(callback: (arg: PipelineConfigurationContext) => Promise): AzureEnvironmentResourcePromise { + return new AzureEnvironmentResourcePromise(this._withPipelineConfigurationAsyncInternal(callback)); + } + + /** @internal */ + private async _withPipelineConfigurationInternal(callback: (obj: PipelineConfigurationContext) => Promise): Promise { + const callbackId = registerCallback(async (objData: unknown) => { + const objHandle = wrapIfHandle(objData) as PipelineConfigurationContextHandle; + const obj = new PipelineConfigurationContext(objHandle, this._client); + await callback(obj); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withPipelineConfiguration', + rpcArgs + ); + return new AzureEnvironmentResource(result, this._client); + } + + /** Configures pipeline step dependencies via a callback */ + withPipelineConfiguration(callback: (obj: PipelineConfigurationContext) => Promise): AzureEnvironmentResourcePromise { + return new AzureEnvironmentResourcePromise(this._withPipelineConfigurationInternal(callback)); + } + + /** Gets the resource name */ + async getResourceName(): Promise { + const rpcArgs: Record = { resource: this._handle }; + return await this._client.invokeCapability( + 'Aspire.Hosting/getResourceName', + rpcArgs + ); + } + + /** @internal */ + private async _withStorageRoleAssignmentsInternal(target: AzureStorageResource, roles: AzureStorageRole[]): Promise { + const rpcArgs: Record = { builder: this._handle, target, roles }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure.Storage/withStorageRoleAssignments', + rpcArgs + ); + return new AzureEnvironmentResource(result, this._client); + } + + /** Assigns Azure Storage roles to a resource */ + withStorageRoleAssignments(target: AzureStorageResource, roles: AzureStorageRole[]): AzureEnvironmentResourcePromise { + return new AzureEnvironmentResourcePromise(this._withStorageRoleAssignmentsInternal(target, roles)); + } + + /** @internal */ + private async _withEventHubsRoleAssignmentsInternal(target: AzureEventHubsResource, roles: AzureEventHubsRole[]): Promise { + const rpcArgs: Record = { builder: this._handle, target, roles }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure.EventHubs/withEventHubsRoleAssignments', + rpcArgs + ); + return new AzureEnvironmentResource(result, this._client); + } + + /** Assigns Event Hubs roles to a resource */ + withEventHubsRoleAssignments(target: AzureEventHubsResource, roles: AzureEventHubsRole[]): AzureEnvironmentResourcePromise { + return new AzureEnvironmentResourcePromise(this._withEventHubsRoleAssignmentsInternal(target, roles)); + } + + /** @internal */ + private async _withLocationInternal(location: ParameterResource): Promise { + const rpcArgs: Record = { builder: this._handle, location }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure/withLocation', + rpcArgs + ); + return new AzureEnvironmentResource(result, this._client); + } + + /** Sets the Azure location for the shared Azure environment resource */ + withLocation(location: ParameterResource): AzureEnvironmentResourcePromise { + return new AzureEnvironmentResourcePromise(this._withLocationInternal(location)); + } + + /** @internal */ + private async _withResourceGroupInternal(resourceGroup: ParameterResource): Promise { + const rpcArgs: Record = { builder: this._handle, resourceGroup }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure/withResourceGroup', + rpcArgs + ); + return new AzureEnvironmentResource(result, this._client); + } + + /** Sets the Azure resource group for the shared Azure environment resource */ + withResourceGroup(resourceGroup: ParameterResource): AzureEnvironmentResourcePromise { + return new AzureEnvironmentResourcePromise(this._withResourceGroupInternal(resourceGroup)); + } + +} + +/** + * Thenable wrapper for AzureEnvironmentResource that enables fluent chaining. + * @example + * await builder.addSomething().withX().withY(); + */ +export class AzureEnvironmentResourcePromise implements PromiseLike { + constructor(private _promise: Promise) {} + + then( + onfulfilled?: ((value: AzureEnvironmentResource) => TResult1 | PromiseLike) | null, + onrejected?: ((reason: unknown) => TResult2 | PromiseLike) | null + ): PromiseLike { + return this._promise.then(onfulfilled, onrejected); + } + + /** Configures a resource to use a container registry */ + withContainerRegistry(registry: ResourceBuilderBase): AzureEnvironmentResourcePromise { + return new AzureEnvironmentResourcePromise(this._promise.then(obj => obj.withContainerRegistry(registry))); + } + + /** Sets the base image for a Dockerfile build */ + withDockerfileBaseImage(options?: WithDockerfileBaseImageOptions): AzureEnvironmentResourcePromise { + return new AzureEnvironmentResourcePromise(this._promise.then(obj => obj.withDockerfileBaseImage(options))); + } + + /** Adds a required command dependency */ + withRequiredCommand(command: string, options?: WithRequiredCommandOptions): AzureEnvironmentResourcePromise { + return new AzureEnvironmentResourcePromise(this._promise.then(obj => obj.withRequiredCommand(command, options))); + } + + /** Customizes displayed URLs via callback */ + withUrlsCallback(callback: (obj: ResourceUrlsCallbackContext) => Promise): AzureEnvironmentResourcePromise { + return new AzureEnvironmentResourcePromise(this._promise.then(obj => obj.withUrlsCallback(callback))); + } + + /** Customizes displayed URLs via async callback */ + withUrlsCallbackAsync(callback: (arg: ResourceUrlsCallbackContext) => Promise): AzureEnvironmentResourcePromise { + return new AzureEnvironmentResourcePromise(this._promise.then(obj => obj.withUrlsCallbackAsync(callback))); + } + + /** Adds or modifies displayed URLs */ + withUrl(url: string, options?: WithUrlOptions): AzureEnvironmentResourcePromise { + return new AzureEnvironmentResourcePromise(this._promise.then(obj => obj.withUrl(url, options))); + } + + /** Adds a URL using a reference expression */ + withUrlExpression(url: ReferenceExpression, options?: WithUrlExpressionOptions): AzureEnvironmentResourcePromise { + return new AzureEnvironmentResourcePromise(this._promise.then(obj => obj.withUrlExpression(url, options))); + } + + /** Customizes the URL for a specific endpoint via callback */ + withUrlForEndpoint(endpointName: string, callback: (obj: ResourceUrlAnnotation) => Promise): AzureEnvironmentResourcePromise { + return new AzureEnvironmentResourcePromise(this._promise.then(obj => obj.withUrlForEndpoint(endpointName, callback))); + } + + /** Excludes the resource from the deployment manifest */ + excludeFromManifest(): AzureEnvironmentResourcePromise { + return new AzureEnvironmentResourcePromise(this._promise.then(obj => obj.excludeFromManifest())); + } + + /** Prevents resource from starting automatically */ + withExplicitStart(): AzureEnvironmentResourcePromise { + return new AzureEnvironmentResourcePromise(this._promise.then(obj => obj.withExplicitStart())); + } + + /** Adds a health check by key */ + withHealthCheck(key: string): AzureEnvironmentResourcePromise { + return new AzureEnvironmentResourcePromise(this._promise.then(obj => obj.withHealthCheck(key))); + } + + /** Adds a resource command */ + withCommand(name: string, displayName: string, executeCommand: (arg: ExecuteCommandContext) => Promise, options?: WithCommandOptions): AzureEnvironmentResourcePromise { + return new AzureEnvironmentResourcePromise(this._promise.then(obj => obj.withCommand(name, displayName, executeCommand, options))); + } + + /** Sets the parent relationship */ + withParentRelationship(parent: ResourceBuilderBase): AzureEnvironmentResourcePromise { + return new AzureEnvironmentResourcePromise(this._promise.then(obj => obj.withParentRelationship(parent))); + } + + /** Sets a child relationship */ + withChildRelationship(child: ResourceBuilderBase): AzureEnvironmentResourcePromise { + return new AzureEnvironmentResourcePromise(this._promise.then(obj => obj.withChildRelationship(child))); + } + + /** Sets the icon for the resource */ + withIconName(iconName: string, options?: WithIconNameOptions): AzureEnvironmentResourcePromise { + return new AzureEnvironmentResourcePromise(this._promise.then(obj => obj.withIconName(iconName, options))); + } + + /** Excludes the resource from MCP server exposure */ + excludeFromMcp(): AzureEnvironmentResourcePromise { + return new AzureEnvironmentResourcePromise(this._promise.then(obj => obj.excludeFromMcp())); + } + + /** Adds a pipeline step to the resource */ + withPipelineStepFactory(stepName: string, callback: (arg: PipelineStepContext) => Promise, options?: WithPipelineStepFactoryOptions): AzureEnvironmentResourcePromise { + return new AzureEnvironmentResourcePromise(this._promise.then(obj => obj.withPipelineStepFactory(stepName, callback, options))); + } + + /** Configures pipeline step dependencies via an async callback */ + withPipelineConfigurationAsync(callback: (arg: PipelineConfigurationContext) => Promise): AzureEnvironmentResourcePromise { + return new AzureEnvironmentResourcePromise(this._promise.then(obj => obj.withPipelineConfigurationAsync(callback))); + } + + /** Configures pipeline step dependencies via a callback */ + withPipelineConfiguration(callback: (obj: PipelineConfigurationContext) => Promise): AzureEnvironmentResourcePromise { + return new AzureEnvironmentResourcePromise(this._promise.then(obj => obj.withPipelineConfiguration(callback))); + } + + /** Gets the resource name */ + getResourceName(): Promise { + return this._promise.then(obj => obj.getResourceName()); + } + + /** Assigns Azure Storage roles to a resource */ + withStorageRoleAssignments(target: AzureStorageResource, roles: AzureStorageRole[]): AzureEnvironmentResourcePromise { + return new AzureEnvironmentResourcePromise(this._promise.then(obj => obj.withStorageRoleAssignments(target, roles))); + } + + /** Assigns Event Hubs roles to a resource */ + withEventHubsRoleAssignments(target: AzureEventHubsResource, roles: AzureEventHubsRole[]): AzureEnvironmentResourcePromise { + return new AzureEnvironmentResourcePromise(this._promise.then(obj => obj.withEventHubsRoleAssignments(target, roles))); + } + + /** Sets the Azure location for the shared Azure environment resource */ + withLocation(location: ParameterResource): AzureEnvironmentResourcePromise { + return new AzureEnvironmentResourcePromise(this._promise.then(obj => obj.withLocation(location))); + } + + /** Sets the Azure resource group for the shared Azure environment resource */ + withResourceGroup(resourceGroup: ParameterResource): AzureEnvironmentResourcePromise { + return new AzureEnvironmentResourcePromise(this._promise.then(obj => obj.withResourceGroup(resourceGroup))); + } + +} + +// ============================================================================ +// AzureEventHubConsumerGroupResource +// ============================================================================ + +export class AzureEventHubConsumerGroupResource extends ResourceBuilderBase { + constructor(handle: AzureEventHubConsumerGroupResourceHandle, client: AspireClientRpc) { + super(handle, client); + } + + /** @internal */ + private async _withContainerRegistryInternal(registry: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, registry }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withContainerRegistry', + rpcArgs + ); + return new AzureEventHubConsumerGroupResource(result, this._client); + } + + /** Configures a resource to use a container registry */ + withContainerRegistry(registry: ResourceBuilderBase): AzureEventHubConsumerGroupResourcePromise { + return new AzureEventHubConsumerGroupResourcePromise(this._withContainerRegistryInternal(registry)); + } + + /** @internal */ + private async _withDockerfileBaseImageInternal(buildImage?: string, runtimeImage?: string): Promise { + const rpcArgs: Record = { builder: this._handle }; + if (buildImage !== undefined) rpcArgs.buildImage = buildImage; + if (runtimeImage !== undefined) rpcArgs.runtimeImage = runtimeImage; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withDockerfileBaseImage', + rpcArgs + ); + return new AzureEventHubConsumerGroupResource(result, this._client); + } + + /** Sets the base image for a Dockerfile build */ + withDockerfileBaseImage(options?: WithDockerfileBaseImageOptions): AzureEventHubConsumerGroupResourcePromise { + const buildImage = options?.buildImage; + const runtimeImage = options?.runtimeImage; + return new AzureEventHubConsumerGroupResourcePromise(this._withDockerfileBaseImageInternal(buildImage, runtimeImage)); + } + + /** @internal */ + private async _withRequiredCommandInternal(command: string, helpLink?: string): Promise { + const rpcArgs: Record = { builder: this._handle, command }; + if (helpLink !== undefined) rpcArgs.helpLink = helpLink; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withRequiredCommand', + rpcArgs + ); + return new AzureEventHubConsumerGroupResource(result, this._client); + } + + /** Adds a required command dependency */ + withRequiredCommand(command: string, options?: WithRequiredCommandOptions): AzureEventHubConsumerGroupResourcePromise { + const helpLink = options?.helpLink; + return new AzureEventHubConsumerGroupResourcePromise(this._withRequiredCommandInternal(command, helpLink)); + } + + /** @internal */ + private async _withConnectionPropertyInternal(name: string, value: ReferenceExpression): Promise { + const rpcArgs: Record = { builder: this._handle, name, value }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withConnectionProperty', + rpcArgs + ); + return new AzureEventHubConsumerGroupResource(result, this._client); + } + + /** Adds a connection property with a reference expression */ + withConnectionProperty(name: string, value: ReferenceExpression): AzureEventHubConsumerGroupResourcePromise { + return new AzureEventHubConsumerGroupResourcePromise(this._withConnectionPropertyInternal(name, value)); + } + + /** @internal */ + private async _withConnectionPropertyValueInternal(name: string, value: string): Promise { + const rpcArgs: Record = { builder: this._handle, name, value }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withConnectionPropertyValue', + rpcArgs + ); + return new AzureEventHubConsumerGroupResource(result, this._client); + } + + /** Adds a connection property with a string value */ + withConnectionPropertyValue(name: string, value: string): AzureEventHubConsumerGroupResourcePromise { + return new AzureEventHubConsumerGroupResourcePromise(this._withConnectionPropertyValueInternal(name, value)); + } + + /** @internal */ + private async _withUrlsCallbackInternal(callback: (obj: ResourceUrlsCallbackContext) => Promise): Promise { + const callbackId = registerCallback(async (objData: unknown) => { + const objHandle = wrapIfHandle(objData) as ResourceUrlsCallbackContextHandle; + const obj = new ResourceUrlsCallbackContext(objHandle, this._client); + await callback(obj); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrlsCallback', + rpcArgs + ); + return new AzureEventHubConsumerGroupResource(result, this._client); + } + + /** Customizes displayed URLs via callback */ + withUrlsCallback(callback: (obj: ResourceUrlsCallbackContext) => Promise): AzureEventHubConsumerGroupResourcePromise { + return new AzureEventHubConsumerGroupResourcePromise(this._withUrlsCallbackInternal(callback)); + } + + /** @internal */ + private async _withUrlsCallbackAsyncInternal(callback: (arg: ResourceUrlsCallbackContext) => Promise): Promise { + const callbackId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as ResourceUrlsCallbackContextHandle; + const arg = new ResourceUrlsCallbackContext(argHandle, this._client); + await callback(arg); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrlsCallbackAsync', + rpcArgs + ); + return new AzureEventHubConsumerGroupResource(result, this._client); + } + + /** Customizes displayed URLs via async callback */ + withUrlsCallbackAsync(callback: (arg: ResourceUrlsCallbackContext) => Promise): AzureEventHubConsumerGroupResourcePromise { + return new AzureEventHubConsumerGroupResourcePromise(this._withUrlsCallbackAsyncInternal(callback)); + } + + /** @internal */ + private async _withUrlInternal(url: string, displayText?: string): Promise { + const rpcArgs: Record = { builder: this._handle, url }; + if (displayText !== undefined) rpcArgs.displayText = displayText; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrl', + rpcArgs + ); + return new AzureEventHubConsumerGroupResource(result, this._client); + } + + /** Adds or modifies displayed URLs */ + withUrl(url: string, options?: WithUrlOptions): AzureEventHubConsumerGroupResourcePromise { + const displayText = options?.displayText; + return new AzureEventHubConsumerGroupResourcePromise(this._withUrlInternal(url, displayText)); + } + + /** @internal */ + private async _withUrlExpressionInternal(url: ReferenceExpression, displayText?: string): Promise { + const rpcArgs: Record = { builder: this._handle, url }; + if (displayText !== undefined) rpcArgs.displayText = displayText; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrlExpression', + rpcArgs + ); + return new AzureEventHubConsumerGroupResource(result, this._client); + } + + /** Adds a URL using a reference expression */ + withUrlExpression(url: ReferenceExpression, options?: WithUrlExpressionOptions): AzureEventHubConsumerGroupResourcePromise { + const displayText = options?.displayText; + return new AzureEventHubConsumerGroupResourcePromise(this._withUrlExpressionInternal(url, displayText)); + } + + /** @internal */ + private async _withUrlForEndpointInternal(endpointName: string, callback: (obj: ResourceUrlAnnotation) => Promise): Promise { + const callbackId = registerCallback(async (objData: unknown) => { + const obj = wrapIfHandle(objData) as ResourceUrlAnnotation; + await callback(obj); + }); + const rpcArgs: Record = { builder: this._handle, endpointName, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrlForEndpoint', + rpcArgs + ); + return new AzureEventHubConsumerGroupResource(result, this._client); + } + + /** Customizes the URL for a specific endpoint via callback */ + withUrlForEndpoint(endpointName: string, callback: (obj: ResourceUrlAnnotation) => Promise): AzureEventHubConsumerGroupResourcePromise { + return new AzureEventHubConsumerGroupResourcePromise(this._withUrlForEndpointInternal(endpointName, callback)); + } + + /** @internal */ + private async _excludeFromManifestInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/excludeFromManifest', + rpcArgs + ); + return new AzureEventHubConsumerGroupResource(result, this._client); + } + + /** Excludes the resource from the deployment manifest */ + excludeFromManifest(): AzureEventHubConsumerGroupResourcePromise { + return new AzureEventHubConsumerGroupResourcePromise(this._excludeFromManifestInternal()); + } + + /** @internal */ + private async _withExplicitStartInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withExplicitStart', + rpcArgs + ); + return new AzureEventHubConsumerGroupResource(result, this._client); + } + + /** Prevents resource from starting automatically */ + withExplicitStart(): AzureEventHubConsumerGroupResourcePromise { + return new AzureEventHubConsumerGroupResourcePromise(this._withExplicitStartInternal()); + } + + /** @internal */ + private async _withHealthCheckInternal(key: string): Promise { + const rpcArgs: Record = { builder: this._handle, key }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withHealthCheck', + rpcArgs + ); + return new AzureEventHubConsumerGroupResource(result, this._client); + } + + /** Adds a health check by key */ + withHealthCheck(key: string): AzureEventHubConsumerGroupResourcePromise { + return new AzureEventHubConsumerGroupResourcePromise(this._withHealthCheckInternal(key)); + } + + /** @internal */ + private async _withCommandInternal(name: string, displayName: string, executeCommand: (arg: ExecuteCommandContext) => Promise, commandOptions?: CommandOptions): Promise { + const executeCommandId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as ExecuteCommandContextHandle; + const arg = new ExecuteCommandContext(argHandle, this._client); + return await executeCommand(arg); + }); + const rpcArgs: Record = { builder: this._handle, name, displayName, executeCommand: executeCommandId }; + if (commandOptions !== undefined) rpcArgs.commandOptions = commandOptions; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withCommand', + rpcArgs + ); + return new AzureEventHubConsumerGroupResource(result, this._client); + } + + /** Adds a resource command */ + withCommand(name: string, displayName: string, executeCommand: (arg: ExecuteCommandContext) => Promise, options?: WithCommandOptions): AzureEventHubConsumerGroupResourcePromise { + const commandOptions = options?.commandOptions; + return new AzureEventHubConsumerGroupResourcePromise(this._withCommandInternal(name, displayName, executeCommand, commandOptions)); + } + + /** @internal */ + private async _withParentRelationshipInternal(parent: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, parent }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withParentRelationship', + rpcArgs + ); + return new AzureEventHubConsumerGroupResource(result, this._client); + } + + /** Sets the parent relationship */ + withParentRelationship(parent: ResourceBuilderBase): AzureEventHubConsumerGroupResourcePromise { + return new AzureEventHubConsumerGroupResourcePromise(this._withParentRelationshipInternal(parent)); + } + + /** @internal */ + private async _withChildRelationshipInternal(child: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, child }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withChildRelationship', + rpcArgs + ); + return new AzureEventHubConsumerGroupResource(result, this._client); + } + + /** Sets a child relationship */ + withChildRelationship(child: ResourceBuilderBase): AzureEventHubConsumerGroupResourcePromise { + return new AzureEventHubConsumerGroupResourcePromise(this._withChildRelationshipInternal(child)); + } + + /** @internal */ + private async _withIconNameInternal(iconName: string, iconVariant?: IconVariant): Promise { + const rpcArgs: Record = { builder: this._handle, iconName }; + if (iconVariant !== undefined) rpcArgs.iconVariant = iconVariant; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withIconName', + rpcArgs + ); + return new AzureEventHubConsumerGroupResource(result, this._client); + } + + /** Sets the icon for the resource */ + withIconName(iconName: string, options?: WithIconNameOptions): AzureEventHubConsumerGroupResourcePromise { + const iconVariant = options?.iconVariant; + return new AzureEventHubConsumerGroupResourcePromise(this._withIconNameInternal(iconName, iconVariant)); + } + + /** @internal */ + private async _excludeFromMcpInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/excludeFromMcp', + rpcArgs + ); + return new AzureEventHubConsumerGroupResource(result, this._client); + } + + /** Excludes the resource from MCP server exposure */ + excludeFromMcp(): AzureEventHubConsumerGroupResourcePromise { + return new AzureEventHubConsumerGroupResourcePromise(this._excludeFromMcpInternal()); + } + + /** @internal */ + private async _withPipelineStepFactoryInternal(stepName: string, callback: (arg: PipelineStepContext) => Promise, dependsOn?: string[], requiredBy?: string[], tags?: string[], description?: string): Promise { + const callbackId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as PipelineStepContextHandle; + const arg = new PipelineStepContext(argHandle, this._client); + await callback(arg); + }); + const rpcArgs: Record = { builder: this._handle, stepName, callback: callbackId }; + if (dependsOn !== undefined) rpcArgs.dependsOn = dependsOn; + if (requiredBy !== undefined) rpcArgs.requiredBy = requiredBy; + if (tags !== undefined) rpcArgs.tags = tags; + if (description !== undefined) rpcArgs.description = description; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withPipelineStepFactory', + rpcArgs + ); + return new AzureEventHubConsumerGroupResource(result, this._client); + } + + /** Adds a pipeline step to the resource */ + withPipelineStepFactory(stepName: string, callback: (arg: PipelineStepContext) => Promise, options?: WithPipelineStepFactoryOptions): AzureEventHubConsumerGroupResourcePromise { + const dependsOn = options?.dependsOn; + const requiredBy = options?.requiredBy; + const tags = options?.tags; + const description = options?.description; + return new AzureEventHubConsumerGroupResourcePromise(this._withPipelineStepFactoryInternal(stepName, callback, dependsOn, requiredBy, tags, description)); + } + + /** @internal */ + private async _withPipelineConfigurationAsyncInternal(callback: (arg: PipelineConfigurationContext) => Promise): Promise { + const callbackId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as PipelineConfigurationContextHandle; + const arg = new PipelineConfigurationContext(argHandle, this._client); + await callback(arg); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withPipelineConfigurationAsync', + rpcArgs + ); + return new AzureEventHubConsumerGroupResource(result, this._client); + } + + /** Configures pipeline step dependencies via an async callback */ + withPipelineConfigurationAsync(callback: (arg: PipelineConfigurationContext) => Promise): AzureEventHubConsumerGroupResourcePromise { + return new AzureEventHubConsumerGroupResourcePromise(this._withPipelineConfigurationAsyncInternal(callback)); + } + + /** @internal */ + private async _withPipelineConfigurationInternal(callback: (obj: PipelineConfigurationContext) => Promise): Promise { + const callbackId = registerCallback(async (objData: unknown) => { + const objHandle = wrapIfHandle(objData) as PipelineConfigurationContextHandle; + const obj = new PipelineConfigurationContext(objHandle, this._client); + await callback(obj); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withPipelineConfiguration', + rpcArgs + ); + return new AzureEventHubConsumerGroupResource(result, this._client); + } + + /** Configures pipeline step dependencies via a callback */ + withPipelineConfiguration(callback: (obj: PipelineConfigurationContext) => Promise): AzureEventHubConsumerGroupResourcePromise { + return new AzureEventHubConsumerGroupResourcePromise(this._withPipelineConfigurationInternal(callback)); + } + + /** Gets the resource name */ + async getResourceName(): Promise { + const rpcArgs: Record = { resource: this._handle }; + return await this._client.invokeCapability( + 'Aspire.Hosting/getResourceName', + rpcArgs + ); + } + + /** @internal */ + private async _withStorageRoleAssignmentsInternal(target: AzureStorageResource, roles: AzureStorageRole[]): Promise { + const rpcArgs: Record = { builder: this._handle, target, roles }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure.Storage/withStorageRoleAssignments', + rpcArgs + ); + return new AzureEventHubConsumerGroupResource(result, this._client); + } + + /** Assigns Azure Storage roles to a resource */ + withStorageRoleAssignments(target: AzureStorageResource, roles: AzureStorageRole[]): AzureEventHubConsumerGroupResourcePromise { + return new AzureEventHubConsumerGroupResourcePromise(this._withStorageRoleAssignmentsInternal(target, roles)); + } + + /** @internal */ + private async _withEventHubsRoleAssignmentsInternal(target: AzureEventHubsResource, roles: AzureEventHubsRole[]): Promise { + const rpcArgs: Record = { builder: this._handle, target, roles }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure.EventHubs/withEventHubsRoleAssignments', + rpcArgs + ); + return new AzureEventHubConsumerGroupResource(result, this._client); + } + + /** Assigns Event Hubs roles to a resource */ + withEventHubsRoleAssignments(target: AzureEventHubsResource, roles: AzureEventHubsRole[]): AzureEventHubConsumerGroupResourcePromise { + return new AzureEventHubConsumerGroupResourcePromise(this._withEventHubsRoleAssignmentsInternal(target, roles)); + } + +} + +/** + * Thenable wrapper for AzureEventHubConsumerGroupResource that enables fluent chaining. + * @example + * await builder.addSomething().withX().withY(); + */ +export class AzureEventHubConsumerGroupResourcePromise implements PromiseLike { + constructor(private _promise: Promise) {} + + then( + onfulfilled?: ((value: AzureEventHubConsumerGroupResource) => TResult1 | PromiseLike) | null, + onrejected?: ((reason: unknown) => TResult2 | PromiseLike) | null + ): PromiseLike { + return this._promise.then(onfulfilled, onrejected); + } + + /** Configures a resource to use a container registry */ + withContainerRegistry(registry: ResourceBuilderBase): AzureEventHubConsumerGroupResourcePromise { + return new AzureEventHubConsumerGroupResourcePromise(this._promise.then(obj => obj.withContainerRegistry(registry))); + } + + /** Sets the base image for a Dockerfile build */ + withDockerfileBaseImage(options?: WithDockerfileBaseImageOptions): AzureEventHubConsumerGroupResourcePromise { + return new AzureEventHubConsumerGroupResourcePromise(this._promise.then(obj => obj.withDockerfileBaseImage(options))); + } + + /** Adds a required command dependency */ + withRequiredCommand(command: string, options?: WithRequiredCommandOptions): AzureEventHubConsumerGroupResourcePromise { + return new AzureEventHubConsumerGroupResourcePromise(this._promise.then(obj => obj.withRequiredCommand(command, options))); + } + + /** Adds a connection property with a reference expression */ + withConnectionProperty(name: string, value: ReferenceExpression): AzureEventHubConsumerGroupResourcePromise { + return new AzureEventHubConsumerGroupResourcePromise(this._promise.then(obj => obj.withConnectionProperty(name, value))); + } + + /** Adds a connection property with a string value */ + withConnectionPropertyValue(name: string, value: string): AzureEventHubConsumerGroupResourcePromise { + return new AzureEventHubConsumerGroupResourcePromise(this._promise.then(obj => obj.withConnectionPropertyValue(name, value))); + } + + /** Customizes displayed URLs via callback */ + withUrlsCallback(callback: (obj: ResourceUrlsCallbackContext) => Promise): AzureEventHubConsumerGroupResourcePromise { + return new AzureEventHubConsumerGroupResourcePromise(this._promise.then(obj => obj.withUrlsCallback(callback))); + } + + /** Customizes displayed URLs via async callback */ + withUrlsCallbackAsync(callback: (arg: ResourceUrlsCallbackContext) => Promise): AzureEventHubConsumerGroupResourcePromise { + return new AzureEventHubConsumerGroupResourcePromise(this._promise.then(obj => obj.withUrlsCallbackAsync(callback))); + } + + /** Adds or modifies displayed URLs */ + withUrl(url: string, options?: WithUrlOptions): AzureEventHubConsumerGroupResourcePromise { + return new AzureEventHubConsumerGroupResourcePromise(this._promise.then(obj => obj.withUrl(url, options))); + } + + /** Adds a URL using a reference expression */ + withUrlExpression(url: ReferenceExpression, options?: WithUrlExpressionOptions): AzureEventHubConsumerGroupResourcePromise { + return new AzureEventHubConsumerGroupResourcePromise(this._promise.then(obj => obj.withUrlExpression(url, options))); + } + + /** Customizes the URL for a specific endpoint via callback */ + withUrlForEndpoint(endpointName: string, callback: (obj: ResourceUrlAnnotation) => Promise): AzureEventHubConsumerGroupResourcePromise { + return new AzureEventHubConsumerGroupResourcePromise(this._promise.then(obj => obj.withUrlForEndpoint(endpointName, callback))); + } + + /** Excludes the resource from the deployment manifest */ + excludeFromManifest(): AzureEventHubConsumerGroupResourcePromise { + return new AzureEventHubConsumerGroupResourcePromise(this._promise.then(obj => obj.excludeFromManifest())); + } + + /** Prevents resource from starting automatically */ + withExplicitStart(): AzureEventHubConsumerGroupResourcePromise { + return new AzureEventHubConsumerGroupResourcePromise(this._promise.then(obj => obj.withExplicitStart())); + } + + /** Adds a health check by key */ + withHealthCheck(key: string): AzureEventHubConsumerGroupResourcePromise { + return new AzureEventHubConsumerGroupResourcePromise(this._promise.then(obj => obj.withHealthCheck(key))); + } + + /** Adds a resource command */ + withCommand(name: string, displayName: string, executeCommand: (arg: ExecuteCommandContext) => Promise, options?: WithCommandOptions): AzureEventHubConsumerGroupResourcePromise { + return new AzureEventHubConsumerGroupResourcePromise(this._promise.then(obj => obj.withCommand(name, displayName, executeCommand, options))); + } + + /** Sets the parent relationship */ + withParentRelationship(parent: ResourceBuilderBase): AzureEventHubConsumerGroupResourcePromise { + return new AzureEventHubConsumerGroupResourcePromise(this._promise.then(obj => obj.withParentRelationship(parent))); + } + + /** Sets a child relationship */ + withChildRelationship(child: ResourceBuilderBase): AzureEventHubConsumerGroupResourcePromise { + return new AzureEventHubConsumerGroupResourcePromise(this._promise.then(obj => obj.withChildRelationship(child))); + } + + /** Sets the icon for the resource */ + withIconName(iconName: string, options?: WithIconNameOptions): AzureEventHubConsumerGroupResourcePromise { + return new AzureEventHubConsumerGroupResourcePromise(this._promise.then(obj => obj.withIconName(iconName, options))); + } + + /** Excludes the resource from MCP server exposure */ + excludeFromMcp(): AzureEventHubConsumerGroupResourcePromise { + return new AzureEventHubConsumerGroupResourcePromise(this._promise.then(obj => obj.excludeFromMcp())); + } + + /** Adds a pipeline step to the resource */ + withPipelineStepFactory(stepName: string, callback: (arg: PipelineStepContext) => Promise, options?: WithPipelineStepFactoryOptions): AzureEventHubConsumerGroupResourcePromise { + return new AzureEventHubConsumerGroupResourcePromise(this._promise.then(obj => obj.withPipelineStepFactory(stepName, callback, options))); + } + + /** Configures pipeline step dependencies via an async callback */ + withPipelineConfigurationAsync(callback: (arg: PipelineConfigurationContext) => Promise): AzureEventHubConsumerGroupResourcePromise { + return new AzureEventHubConsumerGroupResourcePromise(this._promise.then(obj => obj.withPipelineConfigurationAsync(callback))); + } + + /** Configures pipeline step dependencies via a callback */ + withPipelineConfiguration(callback: (obj: PipelineConfigurationContext) => Promise): AzureEventHubConsumerGroupResourcePromise { + return new AzureEventHubConsumerGroupResourcePromise(this._promise.then(obj => obj.withPipelineConfiguration(callback))); + } + + /** Gets the resource name */ + getResourceName(): Promise { + return this._promise.then(obj => obj.getResourceName()); + } + + /** Assigns Azure Storage roles to a resource */ + withStorageRoleAssignments(target: AzureStorageResource, roles: AzureStorageRole[]): AzureEventHubConsumerGroupResourcePromise { + return new AzureEventHubConsumerGroupResourcePromise(this._promise.then(obj => obj.withStorageRoleAssignments(target, roles))); + } + + /** Assigns Event Hubs roles to a resource */ + withEventHubsRoleAssignments(target: AzureEventHubsResource, roles: AzureEventHubsRole[]): AzureEventHubConsumerGroupResourcePromise { + return new AzureEventHubConsumerGroupResourcePromise(this._promise.then(obj => obj.withEventHubsRoleAssignments(target, roles))); + } + +} + +// ============================================================================ +// AzureEventHubResource +// ============================================================================ + +export class AzureEventHubResource extends ResourceBuilderBase { + constructor(handle: AzureEventHubResourceHandle, client: AspireClientRpc) { + super(handle, client); + } + + /** Gets the HubName property */ + hubName = { + get: async (): Promise => { + return await this._client.invokeCapability( + 'Aspire.Hosting.Azure/AzureEventHubResource.hubName', + { context: this._handle } + ); + }, + set: async (value: string): Promise => { + await this._client.invokeCapability( + 'Aspire.Hosting.Azure/AzureEventHubResource.setHubName', + { context: this._handle, value } + ); + } + }; + + /** Gets the PartitionCount property */ + partitionCount = { + get: async (): Promise => { + return await this._client.invokeCapability( + 'Aspire.Hosting.Azure/AzureEventHubResource.partitionCount', + { context: this._handle } + ); + }, + set: async (value: number): Promise => { + await this._client.invokeCapability( + 'Aspire.Hosting.Azure/AzureEventHubResource.setPartitionCount', + { context: this._handle, value } + ); + } + }; + + /** Gets the Name property */ + name = { + get: async (): Promise => { + return await this._client.invokeCapability( + 'Aspire.Hosting.Azure/AzureEventHubResource.name', + { context: this._handle } + ); + }, + }; + + /** @internal */ + private async _withContainerRegistryInternal(registry: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, registry }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withContainerRegistry', + rpcArgs + ); + return new AzureEventHubResource(result, this._client); + } + + /** Configures a resource to use a container registry */ + withContainerRegistry(registry: ResourceBuilderBase): AzureEventHubResourcePromise { + return new AzureEventHubResourcePromise(this._withContainerRegistryInternal(registry)); + } + + /** @internal */ + private async _withDockerfileBaseImageInternal(buildImage?: string, runtimeImage?: string): Promise { + const rpcArgs: Record = { builder: this._handle }; + if (buildImage !== undefined) rpcArgs.buildImage = buildImage; + if (runtimeImage !== undefined) rpcArgs.runtimeImage = runtimeImage; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withDockerfileBaseImage', + rpcArgs + ); + return new AzureEventHubResource(result, this._client); + } + + /** Sets the base image for a Dockerfile build */ + withDockerfileBaseImage(options?: WithDockerfileBaseImageOptions): AzureEventHubResourcePromise { + const buildImage = options?.buildImage; + const runtimeImage = options?.runtimeImage; + return new AzureEventHubResourcePromise(this._withDockerfileBaseImageInternal(buildImage, runtimeImage)); + } + + /** @internal */ + private async _withRequiredCommandInternal(command: string, helpLink?: string): Promise { + const rpcArgs: Record = { builder: this._handle, command }; + if (helpLink !== undefined) rpcArgs.helpLink = helpLink; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withRequiredCommand', + rpcArgs + ); + return new AzureEventHubResource(result, this._client); + } + + /** Adds a required command dependency */ + withRequiredCommand(command: string, options?: WithRequiredCommandOptions): AzureEventHubResourcePromise { + const helpLink = options?.helpLink; + return new AzureEventHubResourcePromise(this._withRequiredCommandInternal(command, helpLink)); + } + + /** @internal */ + private async _withConnectionPropertyInternal(name: string, value: ReferenceExpression): Promise { + const rpcArgs: Record = { builder: this._handle, name, value }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withConnectionProperty', + rpcArgs + ); + return new AzureEventHubResource(result, this._client); + } + + /** Adds a connection property with a reference expression */ + withConnectionProperty(name: string, value: ReferenceExpression): AzureEventHubResourcePromise { + return new AzureEventHubResourcePromise(this._withConnectionPropertyInternal(name, value)); + } + + /** @internal */ + private async _withConnectionPropertyValueInternal(name: string, value: string): Promise { + const rpcArgs: Record = { builder: this._handle, name, value }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withConnectionPropertyValue', + rpcArgs + ); + return new AzureEventHubResource(result, this._client); + } + + /** Adds a connection property with a string value */ + withConnectionPropertyValue(name: string, value: string): AzureEventHubResourcePromise { + return new AzureEventHubResourcePromise(this._withConnectionPropertyValueInternal(name, value)); + } + + /** @internal */ + private async _withUrlsCallbackInternal(callback: (obj: ResourceUrlsCallbackContext) => Promise): Promise { + const callbackId = registerCallback(async (objData: unknown) => { + const objHandle = wrapIfHandle(objData) as ResourceUrlsCallbackContextHandle; + const obj = new ResourceUrlsCallbackContext(objHandle, this._client); + await callback(obj); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrlsCallback', + rpcArgs + ); + return new AzureEventHubResource(result, this._client); + } + + /** Customizes displayed URLs via callback */ + withUrlsCallback(callback: (obj: ResourceUrlsCallbackContext) => Promise): AzureEventHubResourcePromise { + return new AzureEventHubResourcePromise(this._withUrlsCallbackInternal(callback)); + } + + /** @internal */ + private async _withUrlsCallbackAsyncInternal(callback: (arg: ResourceUrlsCallbackContext) => Promise): Promise { + const callbackId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as ResourceUrlsCallbackContextHandle; + const arg = new ResourceUrlsCallbackContext(argHandle, this._client); + await callback(arg); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrlsCallbackAsync', + rpcArgs + ); + return new AzureEventHubResource(result, this._client); + } + + /** Customizes displayed URLs via async callback */ + withUrlsCallbackAsync(callback: (arg: ResourceUrlsCallbackContext) => Promise): AzureEventHubResourcePromise { + return new AzureEventHubResourcePromise(this._withUrlsCallbackAsyncInternal(callback)); + } + + /** @internal */ + private async _withUrlInternal(url: string, displayText?: string): Promise { + const rpcArgs: Record = { builder: this._handle, url }; + if (displayText !== undefined) rpcArgs.displayText = displayText; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrl', + rpcArgs + ); + return new AzureEventHubResource(result, this._client); + } + + /** Adds or modifies displayed URLs */ + withUrl(url: string, options?: WithUrlOptions): AzureEventHubResourcePromise { + const displayText = options?.displayText; + return new AzureEventHubResourcePromise(this._withUrlInternal(url, displayText)); + } + + /** @internal */ + private async _withUrlExpressionInternal(url: ReferenceExpression, displayText?: string): Promise { + const rpcArgs: Record = { builder: this._handle, url }; + if (displayText !== undefined) rpcArgs.displayText = displayText; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrlExpression', + rpcArgs + ); + return new AzureEventHubResource(result, this._client); + } + + /** Adds a URL using a reference expression */ + withUrlExpression(url: ReferenceExpression, options?: WithUrlExpressionOptions): AzureEventHubResourcePromise { + const displayText = options?.displayText; + return new AzureEventHubResourcePromise(this._withUrlExpressionInternal(url, displayText)); + } + + /** @internal */ + private async _withUrlForEndpointInternal(endpointName: string, callback: (obj: ResourceUrlAnnotation) => Promise): Promise { + const callbackId = registerCallback(async (objData: unknown) => { + const obj = wrapIfHandle(objData) as ResourceUrlAnnotation; + await callback(obj); + }); + const rpcArgs: Record = { builder: this._handle, endpointName, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrlForEndpoint', + rpcArgs + ); + return new AzureEventHubResource(result, this._client); + } + + /** Customizes the URL for a specific endpoint via callback */ + withUrlForEndpoint(endpointName: string, callback: (obj: ResourceUrlAnnotation) => Promise): AzureEventHubResourcePromise { + return new AzureEventHubResourcePromise(this._withUrlForEndpointInternal(endpointName, callback)); + } + + /** @internal */ + private async _excludeFromManifestInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/excludeFromManifest', + rpcArgs + ); + return new AzureEventHubResource(result, this._client); + } + + /** Excludes the resource from the deployment manifest */ + excludeFromManifest(): AzureEventHubResourcePromise { + return new AzureEventHubResourcePromise(this._excludeFromManifestInternal()); + } + + /** @internal */ + private async _withExplicitStartInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withExplicitStart', + rpcArgs + ); + return new AzureEventHubResource(result, this._client); + } + + /** Prevents resource from starting automatically */ + withExplicitStart(): AzureEventHubResourcePromise { + return new AzureEventHubResourcePromise(this._withExplicitStartInternal()); + } + + /** @internal */ + private async _withHealthCheckInternal(key: string): Promise { + const rpcArgs: Record = { builder: this._handle, key }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withHealthCheck', + rpcArgs + ); + return new AzureEventHubResource(result, this._client); + } + + /** Adds a health check by key */ + withHealthCheck(key: string): AzureEventHubResourcePromise { + return new AzureEventHubResourcePromise(this._withHealthCheckInternal(key)); + } + + /** @internal */ + private async _withCommandInternal(name: string, displayName: string, executeCommand: (arg: ExecuteCommandContext) => Promise, commandOptions?: CommandOptions): Promise { + const executeCommandId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as ExecuteCommandContextHandle; + const arg = new ExecuteCommandContext(argHandle, this._client); + return await executeCommand(arg); + }); + const rpcArgs: Record = { builder: this._handle, name, displayName, executeCommand: executeCommandId }; + if (commandOptions !== undefined) rpcArgs.commandOptions = commandOptions; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withCommand', + rpcArgs + ); + return new AzureEventHubResource(result, this._client); + } + + /** Adds a resource command */ + withCommand(name: string, displayName: string, executeCommand: (arg: ExecuteCommandContext) => Promise, options?: WithCommandOptions): AzureEventHubResourcePromise { + const commandOptions = options?.commandOptions; + return new AzureEventHubResourcePromise(this._withCommandInternal(name, displayName, executeCommand, commandOptions)); + } + + /** @internal */ + private async _withParentRelationshipInternal(parent: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, parent }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withParentRelationship', + rpcArgs + ); + return new AzureEventHubResource(result, this._client); + } + + /** Sets the parent relationship */ + withParentRelationship(parent: ResourceBuilderBase): AzureEventHubResourcePromise { + return new AzureEventHubResourcePromise(this._withParentRelationshipInternal(parent)); + } + + /** @internal */ + private async _withChildRelationshipInternal(child: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, child }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withChildRelationship', + rpcArgs + ); + return new AzureEventHubResource(result, this._client); + } + + /** Sets a child relationship */ + withChildRelationship(child: ResourceBuilderBase): AzureEventHubResourcePromise { + return new AzureEventHubResourcePromise(this._withChildRelationshipInternal(child)); + } + + /** @internal */ + private async _withIconNameInternal(iconName: string, iconVariant?: IconVariant): Promise { + const rpcArgs: Record = { builder: this._handle, iconName }; + if (iconVariant !== undefined) rpcArgs.iconVariant = iconVariant; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withIconName', + rpcArgs + ); + return new AzureEventHubResource(result, this._client); + } + + /** Sets the icon for the resource */ + withIconName(iconName: string, options?: WithIconNameOptions): AzureEventHubResourcePromise { + const iconVariant = options?.iconVariant; + return new AzureEventHubResourcePromise(this._withIconNameInternal(iconName, iconVariant)); + } + + /** @internal */ + private async _excludeFromMcpInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/excludeFromMcp', + rpcArgs + ); + return new AzureEventHubResource(result, this._client); + } + + /** Excludes the resource from MCP server exposure */ + excludeFromMcp(): AzureEventHubResourcePromise { + return new AzureEventHubResourcePromise(this._excludeFromMcpInternal()); + } + + /** @internal */ + private async _withPipelineStepFactoryInternal(stepName: string, callback: (arg: PipelineStepContext) => Promise, dependsOn?: string[], requiredBy?: string[], tags?: string[], description?: string): Promise { + const callbackId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as PipelineStepContextHandle; + const arg = new PipelineStepContext(argHandle, this._client); + await callback(arg); + }); + const rpcArgs: Record = { builder: this._handle, stepName, callback: callbackId }; + if (dependsOn !== undefined) rpcArgs.dependsOn = dependsOn; + if (requiredBy !== undefined) rpcArgs.requiredBy = requiredBy; + if (tags !== undefined) rpcArgs.tags = tags; + if (description !== undefined) rpcArgs.description = description; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withPipelineStepFactory', + rpcArgs + ); + return new AzureEventHubResource(result, this._client); + } + + /** Adds a pipeline step to the resource */ + withPipelineStepFactory(stepName: string, callback: (arg: PipelineStepContext) => Promise, options?: WithPipelineStepFactoryOptions): AzureEventHubResourcePromise { + const dependsOn = options?.dependsOn; + const requiredBy = options?.requiredBy; + const tags = options?.tags; + const description = options?.description; + return new AzureEventHubResourcePromise(this._withPipelineStepFactoryInternal(stepName, callback, dependsOn, requiredBy, tags, description)); + } + + /** @internal */ + private async _withPipelineConfigurationAsyncInternal(callback: (arg: PipelineConfigurationContext) => Promise): Promise { + const callbackId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as PipelineConfigurationContextHandle; + const arg = new PipelineConfigurationContext(argHandle, this._client); + await callback(arg); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withPipelineConfigurationAsync', + rpcArgs + ); + return new AzureEventHubResource(result, this._client); + } + + /** Configures pipeline step dependencies via an async callback */ + withPipelineConfigurationAsync(callback: (arg: PipelineConfigurationContext) => Promise): AzureEventHubResourcePromise { + return new AzureEventHubResourcePromise(this._withPipelineConfigurationAsyncInternal(callback)); + } + + /** @internal */ + private async _withPipelineConfigurationInternal(callback: (obj: PipelineConfigurationContext) => Promise): Promise { + const callbackId = registerCallback(async (objData: unknown) => { + const objHandle = wrapIfHandle(objData) as PipelineConfigurationContextHandle; + const obj = new PipelineConfigurationContext(objHandle, this._client); + await callback(obj); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withPipelineConfiguration', + rpcArgs + ); + return new AzureEventHubResource(result, this._client); + } + + /** Configures pipeline step dependencies via a callback */ + withPipelineConfiguration(callback: (obj: PipelineConfigurationContext) => Promise): AzureEventHubResourcePromise { + return new AzureEventHubResourcePromise(this._withPipelineConfigurationInternal(callback)); + } + + /** Gets the resource name */ + async getResourceName(): Promise { + const rpcArgs: Record = { resource: this._handle }; + return await this._client.invokeCapability( + 'Aspire.Hosting/getResourceName', + rpcArgs + ); + } + + /** @internal */ + private async _withStorageRoleAssignmentsInternal(target: AzureStorageResource, roles: AzureStorageRole[]): Promise { + const rpcArgs: Record = { builder: this._handle, target, roles }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure.Storage/withStorageRoleAssignments', + rpcArgs + ); + return new AzureEventHubResource(result, this._client); + } + + /** Assigns Azure Storage roles to a resource */ + withStorageRoleAssignments(target: AzureStorageResource, roles: AzureStorageRole[]): AzureEventHubResourcePromise { + return new AzureEventHubResourcePromise(this._withStorageRoleAssignmentsInternal(target, roles)); + } + + /** @internal */ + private async _withPropertiesInternal(configure: (obj: AzureEventHubResource) => Promise): Promise { + const configureId = registerCallback(async (objData: unknown) => { + const objHandle = wrapIfHandle(objData) as AzureEventHubResourceHandle; + const obj = new AzureEventHubResource(objHandle, this._client); + await configure(obj); + }); + const rpcArgs: Record = { builder: this._handle, configure: configureId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure.EventHubs/withProperties', + rpcArgs + ); + return new AzureEventHubResource(result, this._client); + } + + /** Configures properties of an Azure Event Hub */ + withProperties(configure: (obj: AzureEventHubResource) => Promise): AzureEventHubResourcePromise { + return new AzureEventHubResourcePromise(this._withPropertiesInternal(configure)); + } + + /** @internal */ + private async _addConsumerGroupInternal(name: string, groupName?: string): Promise { + const rpcArgs: Record = { builder: this._handle, name }; + if (groupName !== undefined) rpcArgs.groupName = groupName; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure.EventHubs/addConsumerGroup', + rpcArgs + ); + return new AzureEventHubConsumerGroupResource(result, this._client); + } + + /** Adds an Azure Event Hub consumer group resource */ + addConsumerGroup(name: string, options?: AddConsumerGroupOptions): AzureEventHubConsumerGroupResourcePromise { + const groupName = options?.groupName; + return new AzureEventHubConsumerGroupResourcePromise(this._addConsumerGroupInternal(name, groupName)); + } + + /** @internal */ + private async _withEventHubsRoleAssignmentsInternal(target: AzureEventHubsResource, roles: AzureEventHubsRole[]): Promise { + const rpcArgs: Record = { builder: this._handle, target, roles }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure.EventHubs/withEventHubsRoleAssignments', + rpcArgs + ); + return new AzureEventHubResource(result, this._client); + } + + /** Assigns Event Hubs roles to a resource */ + withEventHubsRoleAssignments(target: AzureEventHubsResource, roles: AzureEventHubsRole[]): AzureEventHubResourcePromise { + return new AzureEventHubResourcePromise(this._withEventHubsRoleAssignmentsInternal(target, roles)); + } + +} + +/** + * Thenable wrapper for AzureEventHubResource that enables fluent chaining. + * @example + * await builder.addSomething().withX().withY(); + */ +export class AzureEventHubResourcePromise implements PromiseLike { + constructor(private _promise: Promise) {} + + then( + onfulfilled?: ((value: AzureEventHubResource) => TResult1 | PromiseLike) | null, + onrejected?: ((reason: unknown) => TResult2 | PromiseLike) | null + ): PromiseLike { + return this._promise.then(onfulfilled, onrejected); + } + + /** Configures a resource to use a container registry */ + withContainerRegistry(registry: ResourceBuilderBase): AzureEventHubResourcePromise { + return new AzureEventHubResourcePromise(this._promise.then(obj => obj.withContainerRegistry(registry))); + } + + /** Sets the base image for a Dockerfile build */ + withDockerfileBaseImage(options?: WithDockerfileBaseImageOptions): AzureEventHubResourcePromise { + return new AzureEventHubResourcePromise(this._promise.then(obj => obj.withDockerfileBaseImage(options))); + } + + /** Adds a required command dependency */ + withRequiredCommand(command: string, options?: WithRequiredCommandOptions): AzureEventHubResourcePromise { + return new AzureEventHubResourcePromise(this._promise.then(obj => obj.withRequiredCommand(command, options))); + } + + /** Adds a connection property with a reference expression */ + withConnectionProperty(name: string, value: ReferenceExpression): AzureEventHubResourcePromise { + return new AzureEventHubResourcePromise(this._promise.then(obj => obj.withConnectionProperty(name, value))); + } + + /** Adds a connection property with a string value */ + withConnectionPropertyValue(name: string, value: string): AzureEventHubResourcePromise { + return new AzureEventHubResourcePromise(this._promise.then(obj => obj.withConnectionPropertyValue(name, value))); + } + + /** Customizes displayed URLs via callback */ + withUrlsCallback(callback: (obj: ResourceUrlsCallbackContext) => Promise): AzureEventHubResourcePromise { + return new AzureEventHubResourcePromise(this._promise.then(obj => obj.withUrlsCallback(callback))); + } + + /** Customizes displayed URLs via async callback */ + withUrlsCallbackAsync(callback: (arg: ResourceUrlsCallbackContext) => Promise): AzureEventHubResourcePromise { + return new AzureEventHubResourcePromise(this._promise.then(obj => obj.withUrlsCallbackAsync(callback))); + } + + /** Adds or modifies displayed URLs */ + withUrl(url: string, options?: WithUrlOptions): AzureEventHubResourcePromise { + return new AzureEventHubResourcePromise(this._promise.then(obj => obj.withUrl(url, options))); + } + + /** Adds a URL using a reference expression */ + withUrlExpression(url: ReferenceExpression, options?: WithUrlExpressionOptions): AzureEventHubResourcePromise { + return new AzureEventHubResourcePromise(this._promise.then(obj => obj.withUrlExpression(url, options))); + } + + /** Customizes the URL for a specific endpoint via callback */ + withUrlForEndpoint(endpointName: string, callback: (obj: ResourceUrlAnnotation) => Promise): AzureEventHubResourcePromise { + return new AzureEventHubResourcePromise(this._promise.then(obj => obj.withUrlForEndpoint(endpointName, callback))); + } + + /** Excludes the resource from the deployment manifest */ + excludeFromManifest(): AzureEventHubResourcePromise { + return new AzureEventHubResourcePromise(this._promise.then(obj => obj.excludeFromManifest())); + } + + /** Prevents resource from starting automatically */ + withExplicitStart(): AzureEventHubResourcePromise { + return new AzureEventHubResourcePromise(this._promise.then(obj => obj.withExplicitStart())); + } + + /** Adds a health check by key */ + withHealthCheck(key: string): AzureEventHubResourcePromise { + return new AzureEventHubResourcePromise(this._promise.then(obj => obj.withHealthCheck(key))); + } + + /** Adds a resource command */ + withCommand(name: string, displayName: string, executeCommand: (arg: ExecuteCommandContext) => Promise, options?: WithCommandOptions): AzureEventHubResourcePromise { + return new AzureEventHubResourcePromise(this._promise.then(obj => obj.withCommand(name, displayName, executeCommand, options))); + } + + /** Sets the parent relationship */ + withParentRelationship(parent: ResourceBuilderBase): AzureEventHubResourcePromise { + return new AzureEventHubResourcePromise(this._promise.then(obj => obj.withParentRelationship(parent))); + } + + /** Sets a child relationship */ + withChildRelationship(child: ResourceBuilderBase): AzureEventHubResourcePromise { + return new AzureEventHubResourcePromise(this._promise.then(obj => obj.withChildRelationship(child))); + } + + /** Sets the icon for the resource */ + withIconName(iconName: string, options?: WithIconNameOptions): AzureEventHubResourcePromise { + return new AzureEventHubResourcePromise(this._promise.then(obj => obj.withIconName(iconName, options))); + } + + /** Excludes the resource from MCP server exposure */ + excludeFromMcp(): AzureEventHubResourcePromise { + return new AzureEventHubResourcePromise(this._promise.then(obj => obj.excludeFromMcp())); + } + + /** Adds a pipeline step to the resource */ + withPipelineStepFactory(stepName: string, callback: (arg: PipelineStepContext) => Promise, options?: WithPipelineStepFactoryOptions): AzureEventHubResourcePromise { + return new AzureEventHubResourcePromise(this._promise.then(obj => obj.withPipelineStepFactory(stepName, callback, options))); + } + + /** Configures pipeline step dependencies via an async callback */ + withPipelineConfigurationAsync(callback: (arg: PipelineConfigurationContext) => Promise): AzureEventHubResourcePromise { + return new AzureEventHubResourcePromise(this._promise.then(obj => obj.withPipelineConfigurationAsync(callback))); + } + + /** Configures pipeline step dependencies via a callback */ + withPipelineConfiguration(callback: (obj: PipelineConfigurationContext) => Promise): AzureEventHubResourcePromise { + return new AzureEventHubResourcePromise(this._promise.then(obj => obj.withPipelineConfiguration(callback))); + } + + /** Gets the resource name */ + getResourceName(): Promise { + return this._promise.then(obj => obj.getResourceName()); + } + + /** Assigns Azure Storage roles to a resource */ + withStorageRoleAssignments(target: AzureStorageResource, roles: AzureStorageRole[]): AzureEventHubResourcePromise { + return new AzureEventHubResourcePromise(this._promise.then(obj => obj.withStorageRoleAssignments(target, roles))); + } + + /** Configures properties of an Azure Event Hub */ + withProperties(configure: (obj: AzureEventHubResource) => Promise): AzureEventHubResourcePromise { + return new AzureEventHubResourcePromise(this._promise.then(obj => obj.withProperties(configure))); + } + + /** Adds an Azure Event Hub consumer group resource */ + addConsumerGroup(name: string, options?: AddConsumerGroupOptions): AzureEventHubConsumerGroupResourcePromise { + return new AzureEventHubConsumerGroupResourcePromise(this._promise.then(obj => obj.addConsumerGroup(name, options))); + } + + /** Assigns Event Hubs roles to a resource */ + withEventHubsRoleAssignments(target: AzureEventHubsResource, roles: AzureEventHubsRole[]): AzureEventHubResourcePromise { + return new AzureEventHubResourcePromise(this._promise.then(obj => obj.withEventHubsRoleAssignments(target, roles))); + } + +} + +// ============================================================================ +// AzureEventHubsEmulatorResource +// ============================================================================ + +export class AzureEventHubsEmulatorResource extends ResourceBuilderBase { + constructor(handle: AzureEventHubsEmulatorResourceHandle, client: AspireClientRpc) { + super(handle, client); + } + + /** @internal */ + private async _withContainerRegistryInternal(registry: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, registry }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withContainerRegistry', + rpcArgs + ); + return new AzureEventHubsEmulatorResource(result, this._client); + } + + /** Configures a resource to use a container registry */ + withContainerRegistry(registry: ResourceBuilderBase): AzureEventHubsEmulatorResourcePromise { + return new AzureEventHubsEmulatorResourcePromise(this._withContainerRegistryInternal(registry)); + } + + /** @internal */ + private async _withBindMountInternal(source: string, target: string, isReadOnly?: boolean): Promise { + const rpcArgs: Record = { builder: this._handle, source, target }; + if (isReadOnly !== undefined) rpcArgs.isReadOnly = isReadOnly; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withBindMount', + rpcArgs + ); + return new AzureEventHubsEmulatorResource(result, this._client); + } + + /** Adds a bind mount */ + withBindMount(source: string, target: string, options?: WithBindMountOptions): AzureEventHubsEmulatorResourcePromise { + const isReadOnly = options?.isReadOnly; + return new AzureEventHubsEmulatorResourcePromise(this._withBindMountInternal(source, target, isReadOnly)); + } + + /** @internal */ + private async _withEntrypointInternal(entrypoint: string): Promise { + const rpcArgs: Record = { builder: this._handle, entrypoint }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withEntrypoint', + rpcArgs + ); + return new AzureEventHubsEmulatorResource(result, this._client); + } + + /** Sets the container entrypoint */ + withEntrypoint(entrypoint: string): AzureEventHubsEmulatorResourcePromise { + return new AzureEventHubsEmulatorResourcePromise(this._withEntrypointInternal(entrypoint)); + } + + /** @internal */ + private async _withImageTagInternal(tag: string): Promise { + const rpcArgs: Record = { builder: this._handle, tag }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withImageTag', + rpcArgs + ); + return new AzureEventHubsEmulatorResource(result, this._client); + } + + /** Sets the container image tag */ + withImageTag(tag: string): AzureEventHubsEmulatorResourcePromise { + return new AzureEventHubsEmulatorResourcePromise(this._withImageTagInternal(tag)); + } + + /** @internal */ + private async _withImageRegistryInternal(registry: string): Promise { + const rpcArgs: Record = { builder: this._handle, registry }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withImageRegistry', + rpcArgs + ); + return new AzureEventHubsEmulatorResource(result, this._client); + } + + /** Sets the container image registry */ + withImageRegistry(registry: string): AzureEventHubsEmulatorResourcePromise { + return new AzureEventHubsEmulatorResourcePromise(this._withImageRegistryInternal(registry)); + } + + /** @internal */ + private async _withImageInternal(image: string, tag?: string): Promise { + const rpcArgs: Record = { builder: this._handle, image }; + if (tag !== undefined) rpcArgs.tag = tag; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withImage', + rpcArgs + ); + return new AzureEventHubsEmulatorResource(result, this._client); + } + + /** Sets the container image */ + withImage(image: string, options?: WithImageOptions): AzureEventHubsEmulatorResourcePromise { + const tag = options?.tag; + return new AzureEventHubsEmulatorResourcePromise(this._withImageInternal(image, tag)); + } + + /** @internal */ + private async _withImageSHA256Internal(sha256: string): Promise { + const rpcArgs: Record = { builder: this._handle, sha256 }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withImageSHA256', + rpcArgs + ); + return new AzureEventHubsEmulatorResource(result, this._client); + } + + /** Sets the image SHA256 digest */ + withImageSHA256(sha256: string): AzureEventHubsEmulatorResourcePromise { + return new AzureEventHubsEmulatorResourcePromise(this._withImageSHA256Internal(sha256)); + } + + /** @internal */ + private async _withContainerRuntimeArgsInternal(args: string[]): Promise { + const rpcArgs: Record = { builder: this._handle, args }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withContainerRuntimeArgs', + rpcArgs + ); + return new AzureEventHubsEmulatorResource(result, this._client); + } + + /** Adds runtime arguments for the container */ + withContainerRuntimeArgs(args: string[]): AzureEventHubsEmulatorResourcePromise { + return new AzureEventHubsEmulatorResourcePromise(this._withContainerRuntimeArgsInternal(args)); + } + + /** @internal */ + private async _withLifetimeInternal(lifetime: ContainerLifetime): Promise { + const rpcArgs: Record = { builder: this._handle, lifetime }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withLifetime', + rpcArgs + ); + return new AzureEventHubsEmulatorResource(result, this._client); + } + + /** Sets the lifetime behavior of the container resource */ + withLifetime(lifetime: ContainerLifetime): AzureEventHubsEmulatorResourcePromise { + return new AzureEventHubsEmulatorResourcePromise(this._withLifetimeInternal(lifetime)); + } + + /** @internal */ + private async _withImagePullPolicyInternal(pullPolicy: ImagePullPolicy): Promise { + const rpcArgs: Record = { builder: this._handle, pullPolicy }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withImagePullPolicy', + rpcArgs + ); + return new AzureEventHubsEmulatorResource(result, this._client); + } + + /** Sets the container image pull policy */ + withImagePullPolicy(pullPolicy: ImagePullPolicy): AzureEventHubsEmulatorResourcePromise { + return new AzureEventHubsEmulatorResourcePromise(this._withImagePullPolicyInternal(pullPolicy)); + } + + /** @internal */ + private async _publishAsContainerInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/publishAsContainer', + rpcArgs + ); + return new AzureEventHubsEmulatorResource(result, this._client); + } + + /** Configures the resource to be published as a container */ + publishAsContainer(): AzureEventHubsEmulatorResourcePromise { + return new AzureEventHubsEmulatorResourcePromise(this._publishAsContainerInternal()); + } + + /** @internal */ + private async _withDockerfileInternal(contextPath: string, dockerfilePath?: string, stage?: string): Promise { + const rpcArgs: Record = { builder: this._handle, contextPath }; + if (dockerfilePath !== undefined) rpcArgs.dockerfilePath = dockerfilePath; + if (stage !== undefined) rpcArgs.stage = stage; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withDockerfile', + rpcArgs + ); + return new AzureEventHubsEmulatorResource(result, this._client); + } + + /** Configures the resource to use a Dockerfile */ + withDockerfile(contextPath: string, options?: WithDockerfileOptions): AzureEventHubsEmulatorResourcePromise { + const dockerfilePath = options?.dockerfilePath; + const stage = options?.stage; + return new AzureEventHubsEmulatorResourcePromise(this._withDockerfileInternal(contextPath, dockerfilePath, stage)); + } + + /** @internal */ + private async _withContainerNameInternal(name: string): Promise { + const rpcArgs: Record = { builder: this._handle, name }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withContainerName', + rpcArgs + ); + return new AzureEventHubsEmulatorResource(result, this._client); + } + + /** Sets the container name */ + withContainerName(name: string): AzureEventHubsEmulatorResourcePromise { + return new AzureEventHubsEmulatorResourcePromise(this._withContainerNameInternal(name)); + } + + /** @internal */ + private async _withBuildArgInternal(name: string, value: ParameterResource): Promise { + const rpcArgs: Record = { builder: this._handle, name, value }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withBuildArg', + rpcArgs + ); + return new AzureEventHubsEmulatorResource(result, this._client); + } + + /** Adds a build argument from a parameter resource */ + withBuildArg(name: string, value: ParameterResource): AzureEventHubsEmulatorResourcePromise { + return new AzureEventHubsEmulatorResourcePromise(this._withBuildArgInternal(name, value)); + } + + /** @internal */ + private async _withBuildSecretInternal(name: string, value: ParameterResource): Promise { + const rpcArgs: Record = { builder: this._handle, name, value }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withBuildSecret', + rpcArgs + ); + return new AzureEventHubsEmulatorResource(result, this._client); + } + + /** Adds a build secret from a parameter resource */ + withBuildSecret(name: string, value: ParameterResource): AzureEventHubsEmulatorResourcePromise { + return new AzureEventHubsEmulatorResourcePromise(this._withBuildSecretInternal(name, value)); + } + + /** @internal */ + private async _withEndpointProxySupportInternal(proxyEnabled: boolean): Promise { + const rpcArgs: Record = { builder: this._handle, proxyEnabled }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withEndpointProxySupport', + rpcArgs + ); + return new AzureEventHubsEmulatorResource(result, this._client); + } + + /** Configures endpoint proxy support */ + withEndpointProxySupport(proxyEnabled: boolean): AzureEventHubsEmulatorResourcePromise { + return new AzureEventHubsEmulatorResourcePromise(this._withEndpointProxySupportInternal(proxyEnabled)); + } + + /** @internal */ + private async _withDockerfileBaseImageInternal(buildImage?: string, runtimeImage?: string): Promise { + const rpcArgs: Record = { builder: this._handle }; + if (buildImage !== undefined) rpcArgs.buildImage = buildImage; + if (runtimeImage !== undefined) rpcArgs.runtimeImage = runtimeImage; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withDockerfileBaseImage', + rpcArgs + ); + return new AzureEventHubsEmulatorResource(result, this._client); + } + + /** Sets the base image for a Dockerfile build */ + withDockerfileBaseImage(options?: WithDockerfileBaseImageOptions): AzureEventHubsEmulatorResourcePromise { + const buildImage = options?.buildImage; + const runtimeImage = options?.runtimeImage; + return new AzureEventHubsEmulatorResourcePromise(this._withDockerfileBaseImageInternal(buildImage, runtimeImage)); + } + + /** @internal */ + private async _withContainerNetworkAliasInternal(alias: string): Promise { + const rpcArgs: Record = { builder: this._handle, alias }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withContainerNetworkAlias', + rpcArgs + ); + return new AzureEventHubsEmulatorResource(result, this._client); + } + + /** Adds a network alias for the container */ + withContainerNetworkAlias(alias: string): AzureEventHubsEmulatorResourcePromise { + return new AzureEventHubsEmulatorResourcePromise(this._withContainerNetworkAliasInternal(alias)); + } + + /** @internal */ + private async _withMcpServerInternal(path?: string, endpointName?: string): Promise { + const rpcArgs: Record = { builder: this._handle }; + if (path !== undefined) rpcArgs.path = path; + if (endpointName !== undefined) rpcArgs.endpointName = endpointName; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withMcpServer', + rpcArgs + ); + return new AzureEventHubsEmulatorResource(result, this._client); + } + + /** Configures an MCP server endpoint on the resource */ + withMcpServer(options?: WithMcpServerOptions): AzureEventHubsEmulatorResourcePromise { + const path = options?.path; + const endpointName = options?.endpointName; + return new AzureEventHubsEmulatorResourcePromise(this._withMcpServerInternal(path, endpointName)); + } + + /** @internal */ + private async _withOtlpExporterInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withOtlpExporter', + rpcArgs + ); + return new AzureEventHubsEmulatorResource(result, this._client); + } + + /** Configures OTLP telemetry export */ + withOtlpExporter(): AzureEventHubsEmulatorResourcePromise { + return new AzureEventHubsEmulatorResourcePromise(this._withOtlpExporterInternal()); + } + + /** @internal */ + private async _withOtlpExporterProtocolInternal(protocol: OtlpProtocol): Promise { + const rpcArgs: Record = { builder: this._handle, protocol }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withOtlpExporterProtocol', + rpcArgs + ); + return new AzureEventHubsEmulatorResource(result, this._client); + } + + /** Configures OTLP telemetry export with specific protocol */ + withOtlpExporterProtocol(protocol: OtlpProtocol): AzureEventHubsEmulatorResourcePromise { + return new AzureEventHubsEmulatorResourcePromise(this._withOtlpExporterProtocolInternal(protocol)); + } + + /** @internal */ + private async _publishAsConnectionStringInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/publishAsConnectionString', + rpcArgs + ); + return new AzureEventHubsEmulatorResource(result, this._client); + } + + /** Publishes the resource as a connection string */ + publishAsConnectionString(): AzureEventHubsEmulatorResourcePromise { + return new AzureEventHubsEmulatorResourcePromise(this._publishAsConnectionStringInternal()); + } + + /** @internal */ + private async _withRequiredCommandInternal(command: string, helpLink?: string): Promise { + const rpcArgs: Record = { builder: this._handle, command }; + if (helpLink !== undefined) rpcArgs.helpLink = helpLink; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withRequiredCommand', + rpcArgs + ); + return new AzureEventHubsEmulatorResource(result, this._client); + } + + /** Adds a required command dependency */ + withRequiredCommand(command: string, options?: WithRequiredCommandOptions): AzureEventHubsEmulatorResourcePromise { + const helpLink = options?.helpLink; + return new AzureEventHubsEmulatorResourcePromise(this._withRequiredCommandInternal(command, helpLink)); + } + + /** @internal */ + private async _withEnvironmentInternal(name: string, value: string): Promise { + const rpcArgs: Record = { builder: this._handle, name, value }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withEnvironment', + rpcArgs + ); + return new AzureEventHubsEmulatorResource(result, this._client); + } + + /** Sets an environment variable */ + withEnvironment(name: string, value: string): AzureEventHubsEmulatorResourcePromise { + return new AzureEventHubsEmulatorResourcePromise(this._withEnvironmentInternal(name, value)); + } + + /** @internal */ + private async _withEnvironmentExpressionInternal(name: string, value: ReferenceExpression): Promise { + const rpcArgs: Record = { builder: this._handle, name, value }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withEnvironmentExpression', + rpcArgs + ); + return new AzureEventHubsEmulatorResource(result, this._client); + } + + /** Adds an environment variable with a reference expression */ + withEnvironmentExpression(name: string, value: ReferenceExpression): AzureEventHubsEmulatorResourcePromise { + return new AzureEventHubsEmulatorResourcePromise(this._withEnvironmentExpressionInternal(name, value)); + } + + /** @internal */ + private async _withEnvironmentCallbackInternal(callback: (obj: EnvironmentCallbackContext) => Promise): Promise { + const callbackId = registerCallback(async (objData: unknown) => { + const objHandle = wrapIfHandle(objData) as EnvironmentCallbackContextHandle; + const obj = new EnvironmentCallbackContext(objHandle, this._client); + await callback(obj); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withEnvironmentCallback', + rpcArgs + ); + return new AzureEventHubsEmulatorResource(result, this._client); + } + + /** Sets environment variables via callback */ + withEnvironmentCallback(callback: (obj: EnvironmentCallbackContext) => Promise): AzureEventHubsEmulatorResourcePromise { + return new AzureEventHubsEmulatorResourcePromise(this._withEnvironmentCallbackInternal(callback)); + } + + /** @internal */ + private async _withEnvironmentCallbackAsyncInternal(callback: (arg: EnvironmentCallbackContext) => Promise): Promise { + const callbackId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as EnvironmentCallbackContextHandle; + const arg = new EnvironmentCallbackContext(argHandle, this._client); + await callback(arg); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withEnvironmentCallbackAsync', + rpcArgs + ); + return new AzureEventHubsEmulatorResource(result, this._client); + } + + /** Sets environment variables via async callback */ + withEnvironmentCallbackAsync(callback: (arg: EnvironmentCallbackContext) => Promise): AzureEventHubsEmulatorResourcePromise { + return new AzureEventHubsEmulatorResourcePromise(this._withEnvironmentCallbackAsyncInternal(callback)); + } + + /** @internal */ + private async _withEnvironmentEndpointInternal(name: string, endpointReference: EndpointReference): Promise { + const rpcArgs: Record = { builder: this._handle, name, endpointReference }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withEnvironmentEndpoint', + rpcArgs + ); + return new AzureEventHubsEmulatorResource(result, this._client); + } + + /** Sets an environment variable from an endpoint reference */ + withEnvironmentEndpoint(name: string, endpointReference: EndpointReference): AzureEventHubsEmulatorResourcePromise { + return new AzureEventHubsEmulatorResourcePromise(this._withEnvironmentEndpointInternal(name, endpointReference)); + } + + /** @internal */ + private async _withEnvironmentParameterInternal(name: string, parameter: ParameterResource): Promise { + const rpcArgs: Record = { builder: this._handle, name, parameter }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withEnvironmentParameter', + rpcArgs + ); + return new AzureEventHubsEmulatorResource(result, this._client); + } + + /** Sets an environment variable from a parameter resource */ + withEnvironmentParameter(name: string, parameter: ParameterResource): AzureEventHubsEmulatorResourcePromise { + return new AzureEventHubsEmulatorResourcePromise(this._withEnvironmentParameterInternal(name, parameter)); + } + + /** @internal */ + private async _withEnvironmentConnectionStringInternal(envVarName: string, resource: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, envVarName, resource }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withEnvironmentConnectionString', + rpcArgs + ); + return new AzureEventHubsEmulatorResource(result, this._client); + } + + /** Sets an environment variable from a connection string resource */ + withEnvironmentConnectionString(envVarName: string, resource: ResourceBuilderBase): AzureEventHubsEmulatorResourcePromise { + return new AzureEventHubsEmulatorResourcePromise(this._withEnvironmentConnectionStringInternal(envVarName, resource)); + } + + /** @internal */ + private async _withArgsInternal(args: string[]): Promise { + const rpcArgs: Record = { builder: this._handle, args }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withArgs', + rpcArgs + ); + return new AzureEventHubsEmulatorResource(result, this._client); + } + + /** Adds arguments */ + withArgs(args: string[]): AzureEventHubsEmulatorResourcePromise { + return new AzureEventHubsEmulatorResourcePromise(this._withArgsInternal(args)); + } + + /** @internal */ + private async _withArgsCallbackInternal(callback: (obj: CommandLineArgsCallbackContext) => Promise): Promise { + const callbackId = registerCallback(async (objData: unknown) => { + const objHandle = wrapIfHandle(objData) as CommandLineArgsCallbackContextHandle; + const obj = new CommandLineArgsCallbackContext(objHandle, this._client); + await callback(obj); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withArgsCallback', + rpcArgs + ); + return new AzureEventHubsEmulatorResource(result, this._client); + } + + /** Sets command-line arguments via callback */ + withArgsCallback(callback: (obj: CommandLineArgsCallbackContext) => Promise): AzureEventHubsEmulatorResourcePromise { + return new AzureEventHubsEmulatorResourcePromise(this._withArgsCallbackInternal(callback)); + } + + /** @internal */ + private async _withArgsCallbackAsyncInternal(callback: (arg: CommandLineArgsCallbackContext) => Promise): Promise { + const callbackId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as CommandLineArgsCallbackContextHandle; + const arg = new CommandLineArgsCallbackContext(argHandle, this._client); + await callback(arg); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withArgsCallbackAsync', + rpcArgs + ); + return new AzureEventHubsEmulatorResource(result, this._client); + } + + /** Sets command-line arguments via async callback */ + withArgsCallbackAsync(callback: (arg: CommandLineArgsCallbackContext) => Promise): AzureEventHubsEmulatorResourcePromise { + return new AzureEventHubsEmulatorResourcePromise(this._withArgsCallbackAsyncInternal(callback)); + } + + /** @internal */ + private async _withReferenceInternal(source: ResourceBuilderBase, connectionName?: string, optional?: boolean): Promise { + const rpcArgs: Record = { builder: this._handle, source }; + if (connectionName !== undefined) rpcArgs.connectionName = connectionName; + if (optional !== undefined) rpcArgs.optional = optional; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withReference', + rpcArgs + ); + return new AzureEventHubsEmulatorResource(result, this._client); + } + + /** Adds a reference to another resource */ + withReference(source: ResourceBuilderBase, options?: WithReferenceOptions): AzureEventHubsEmulatorResourcePromise { + const connectionName = options?.connectionName; + const optional = options?.optional; + return new AzureEventHubsEmulatorResourcePromise(this._withReferenceInternal(source, connectionName, optional)); + } + + /** @internal */ + private async _withServiceReferenceInternal(source: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, source }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withServiceReference', + rpcArgs + ); + return new AzureEventHubsEmulatorResource(result, this._client); + } + + /** Adds a service discovery reference to another resource */ + withServiceReference(source: ResourceBuilderBase): AzureEventHubsEmulatorResourcePromise { + return new AzureEventHubsEmulatorResourcePromise(this._withServiceReferenceInternal(source)); + } + + /** @internal */ + private async _withServiceReferenceNamedInternal(source: ResourceBuilderBase, name: string): Promise { + const rpcArgs: Record = { builder: this._handle, source, name }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withServiceReferenceNamed', + rpcArgs + ); + return new AzureEventHubsEmulatorResource(result, this._client); + } + + /** Adds a named service discovery reference */ + withServiceReferenceNamed(source: ResourceBuilderBase, name: string): AzureEventHubsEmulatorResourcePromise { + return new AzureEventHubsEmulatorResourcePromise(this._withServiceReferenceNamedInternal(source, name)); + } + + /** @internal */ + private async _withReferenceUriInternal(name: string, uri: string): Promise { + const rpcArgs: Record = { builder: this._handle, name, uri }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withReferenceUri', + rpcArgs + ); + return new AzureEventHubsEmulatorResource(result, this._client); + } + + /** Adds a reference to a URI */ + withReferenceUri(name: string, uri: string): AzureEventHubsEmulatorResourcePromise { + return new AzureEventHubsEmulatorResourcePromise(this._withReferenceUriInternal(name, uri)); + } + + /** @internal */ + private async _withReferenceExternalServiceInternal(externalService: ExternalServiceResource): Promise { + const rpcArgs: Record = { builder: this._handle, externalService }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withReferenceExternalService', + rpcArgs + ); + return new AzureEventHubsEmulatorResource(result, this._client); + } + + /** Adds a reference to an external service */ + withReferenceExternalService(externalService: ExternalServiceResource): AzureEventHubsEmulatorResourcePromise { + return new AzureEventHubsEmulatorResourcePromise(this._withReferenceExternalServiceInternal(externalService)); + } + + /** @internal */ + private async _withReferenceEndpointInternal(endpointReference: EndpointReference): Promise { + const rpcArgs: Record = { builder: this._handle, endpointReference }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withReferenceEndpoint', + rpcArgs + ); + return new AzureEventHubsEmulatorResource(result, this._client); + } + + /** Adds a reference to an endpoint */ + withReferenceEndpoint(endpointReference: EndpointReference): AzureEventHubsEmulatorResourcePromise { + return new AzureEventHubsEmulatorResourcePromise(this._withReferenceEndpointInternal(endpointReference)); + } + + /** @internal */ + private async _withEndpointInternal(port?: number, targetPort?: number, scheme?: string, name?: string, env?: string, isProxied?: boolean, isExternal?: boolean, protocol?: ProtocolType): Promise { + const rpcArgs: Record = { builder: this._handle }; + if (port !== undefined) rpcArgs.port = port; + if (targetPort !== undefined) rpcArgs.targetPort = targetPort; + if (scheme !== undefined) rpcArgs.scheme = scheme; + if (name !== undefined) rpcArgs.name = name; + if (env !== undefined) rpcArgs.env = env; + if (isProxied !== undefined) rpcArgs.isProxied = isProxied; + if (isExternal !== undefined) rpcArgs.isExternal = isExternal; + if (protocol !== undefined) rpcArgs.protocol = protocol; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withEndpoint', + rpcArgs + ); + return new AzureEventHubsEmulatorResource(result, this._client); + } + + /** Adds a network endpoint */ + withEndpoint(options?: WithEndpointOptions): AzureEventHubsEmulatorResourcePromise { + const port = options?.port; + const targetPort = options?.targetPort; + const scheme = options?.scheme; + const name = options?.name; + const env = options?.env; + const isProxied = options?.isProxied; + const isExternal = options?.isExternal; + const protocol = options?.protocol; + return new AzureEventHubsEmulatorResourcePromise(this._withEndpointInternal(port, targetPort, scheme, name, env, isProxied, isExternal, protocol)); + } + + /** @internal */ + private async _withHttpEndpointInternal(port?: number, targetPort?: number, name?: string, env?: string, isProxied?: boolean): Promise { + const rpcArgs: Record = { builder: this._handle }; + if (port !== undefined) rpcArgs.port = port; + if (targetPort !== undefined) rpcArgs.targetPort = targetPort; + if (name !== undefined) rpcArgs.name = name; + if (env !== undefined) rpcArgs.env = env; + if (isProxied !== undefined) rpcArgs.isProxied = isProxied; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withHttpEndpoint', + rpcArgs + ); + return new AzureEventHubsEmulatorResource(result, this._client); + } + + /** Adds an HTTP endpoint */ + withHttpEndpoint(options?: WithHttpEndpointOptions): AzureEventHubsEmulatorResourcePromise { + const port = options?.port; + const targetPort = options?.targetPort; + const name = options?.name; + const env = options?.env; + const isProxied = options?.isProxied; + return new AzureEventHubsEmulatorResourcePromise(this._withHttpEndpointInternal(port, targetPort, name, env, isProxied)); + } + + /** @internal */ + private async _withHttpsEndpointInternal(port?: number, targetPort?: number, name?: string, env?: string, isProxied?: boolean): Promise { + const rpcArgs: Record = { builder: this._handle }; + if (port !== undefined) rpcArgs.port = port; + if (targetPort !== undefined) rpcArgs.targetPort = targetPort; + if (name !== undefined) rpcArgs.name = name; + if (env !== undefined) rpcArgs.env = env; + if (isProxied !== undefined) rpcArgs.isProxied = isProxied; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withHttpsEndpoint', + rpcArgs + ); + return new AzureEventHubsEmulatorResource(result, this._client); + } + + /** Adds an HTTPS endpoint */ + withHttpsEndpoint(options?: WithHttpsEndpointOptions): AzureEventHubsEmulatorResourcePromise { + const port = options?.port; + const targetPort = options?.targetPort; + const name = options?.name; + const env = options?.env; + const isProxied = options?.isProxied; + return new AzureEventHubsEmulatorResourcePromise(this._withHttpsEndpointInternal(port, targetPort, name, env, isProxied)); + } + + /** @internal */ + private async _withExternalHttpEndpointsInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withExternalHttpEndpoints', + rpcArgs + ); + return new AzureEventHubsEmulatorResource(result, this._client); + } + + /** Makes HTTP endpoints externally accessible */ + withExternalHttpEndpoints(): AzureEventHubsEmulatorResourcePromise { + return new AzureEventHubsEmulatorResourcePromise(this._withExternalHttpEndpointsInternal()); + } + + /** Gets an endpoint reference */ + async getEndpoint(name: string): Promise { + const rpcArgs: Record = { builder: this._handle, name }; + return await this._client.invokeCapability( + 'Aspire.Hosting/getEndpoint', + rpcArgs + ); + } + + /** @internal */ + private async _asHttp2ServiceInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/asHttp2Service', + rpcArgs + ); + return new AzureEventHubsEmulatorResource(result, this._client); + } + + /** Configures resource for HTTP/2 */ + asHttp2Service(): AzureEventHubsEmulatorResourcePromise { + return new AzureEventHubsEmulatorResourcePromise(this._asHttp2ServiceInternal()); + } + + /** @internal */ + private async _withUrlsCallbackInternal(callback: (obj: ResourceUrlsCallbackContext) => Promise): Promise { + const callbackId = registerCallback(async (objData: unknown) => { + const objHandle = wrapIfHandle(objData) as ResourceUrlsCallbackContextHandle; + const obj = new ResourceUrlsCallbackContext(objHandle, this._client); + await callback(obj); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrlsCallback', + rpcArgs + ); + return new AzureEventHubsEmulatorResource(result, this._client); + } + + /** Customizes displayed URLs via callback */ + withUrlsCallback(callback: (obj: ResourceUrlsCallbackContext) => Promise): AzureEventHubsEmulatorResourcePromise { + return new AzureEventHubsEmulatorResourcePromise(this._withUrlsCallbackInternal(callback)); + } + + /** @internal */ + private async _withUrlsCallbackAsyncInternal(callback: (arg: ResourceUrlsCallbackContext) => Promise): Promise { + const callbackId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as ResourceUrlsCallbackContextHandle; + const arg = new ResourceUrlsCallbackContext(argHandle, this._client); + await callback(arg); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrlsCallbackAsync', + rpcArgs + ); + return new AzureEventHubsEmulatorResource(result, this._client); + } + + /** Customizes displayed URLs via async callback */ + withUrlsCallbackAsync(callback: (arg: ResourceUrlsCallbackContext) => Promise): AzureEventHubsEmulatorResourcePromise { + return new AzureEventHubsEmulatorResourcePromise(this._withUrlsCallbackAsyncInternal(callback)); + } + + /** @internal */ + private async _withUrlInternal(url: string, displayText?: string): Promise { + const rpcArgs: Record = { builder: this._handle, url }; + if (displayText !== undefined) rpcArgs.displayText = displayText; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrl', + rpcArgs + ); + return new AzureEventHubsEmulatorResource(result, this._client); + } + + /** Adds or modifies displayed URLs */ + withUrl(url: string, options?: WithUrlOptions): AzureEventHubsEmulatorResourcePromise { + const displayText = options?.displayText; + return new AzureEventHubsEmulatorResourcePromise(this._withUrlInternal(url, displayText)); + } + + /** @internal */ + private async _withUrlExpressionInternal(url: ReferenceExpression, displayText?: string): Promise { + const rpcArgs: Record = { builder: this._handle, url }; + if (displayText !== undefined) rpcArgs.displayText = displayText; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrlExpression', + rpcArgs + ); + return new AzureEventHubsEmulatorResource(result, this._client); + } + + /** Adds a URL using a reference expression */ + withUrlExpression(url: ReferenceExpression, options?: WithUrlExpressionOptions): AzureEventHubsEmulatorResourcePromise { + const displayText = options?.displayText; + return new AzureEventHubsEmulatorResourcePromise(this._withUrlExpressionInternal(url, displayText)); + } + + /** @internal */ + private async _withUrlForEndpointInternal(endpointName: string, callback: (obj: ResourceUrlAnnotation) => Promise): Promise { + const callbackId = registerCallback(async (objData: unknown) => { + const obj = wrapIfHandle(objData) as ResourceUrlAnnotation; + await callback(obj); + }); + const rpcArgs: Record = { builder: this._handle, endpointName, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrlForEndpoint', + rpcArgs + ); + return new AzureEventHubsEmulatorResource(result, this._client); + } + + /** Customizes the URL for a specific endpoint via callback */ + withUrlForEndpoint(endpointName: string, callback: (obj: ResourceUrlAnnotation) => Promise): AzureEventHubsEmulatorResourcePromise { + return new AzureEventHubsEmulatorResourcePromise(this._withUrlForEndpointInternal(endpointName, callback)); + } + + /** @internal */ + private async _withUrlForEndpointFactoryInternal(endpointName: string, callback: (arg: EndpointReference) => Promise): Promise { + const callbackId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as EndpointReferenceHandle; + const arg = new EndpointReference(argHandle, this._client); + return await callback(arg); + }); + const rpcArgs: Record = { builder: this._handle, endpointName, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrlForEndpointFactory', + rpcArgs + ); + return new AzureEventHubsEmulatorResource(result, this._client); + } + + /** Adds a URL for a specific endpoint via factory callback */ + withUrlForEndpointFactory(endpointName: string, callback: (arg: EndpointReference) => Promise): AzureEventHubsEmulatorResourcePromise { + return new AzureEventHubsEmulatorResourcePromise(this._withUrlForEndpointFactoryInternal(endpointName, callback)); + } + + /** @internal */ + private async _excludeFromManifestInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/excludeFromManifest', + rpcArgs + ); + return new AzureEventHubsEmulatorResource(result, this._client); + } + + /** Excludes the resource from the deployment manifest */ + excludeFromManifest(): AzureEventHubsEmulatorResourcePromise { + return new AzureEventHubsEmulatorResourcePromise(this._excludeFromManifestInternal()); + } + + /** @internal */ + private async _waitForInternal(dependency: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, dependency }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/waitFor', + rpcArgs + ); + return new AzureEventHubsEmulatorResource(result, this._client); + } + + /** Waits for another resource to be ready */ + waitFor(dependency: ResourceBuilderBase): AzureEventHubsEmulatorResourcePromise { + return new AzureEventHubsEmulatorResourcePromise(this._waitForInternal(dependency)); + } + + /** @internal */ + private async _waitForWithBehaviorInternal(dependency: ResourceBuilderBase, waitBehavior: WaitBehavior): Promise { + const rpcArgs: Record = { builder: this._handle, dependency, waitBehavior }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/waitForWithBehavior', + rpcArgs + ); + return new AzureEventHubsEmulatorResource(result, this._client); + } + + /** Waits for another resource with specific behavior */ + waitForWithBehavior(dependency: ResourceBuilderBase, waitBehavior: WaitBehavior): AzureEventHubsEmulatorResourcePromise { + return new AzureEventHubsEmulatorResourcePromise(this._waitForWithBehaviorInternal(dependency, waitBehavior)); + } + + /** @internal */ + private async _waitForStartInternal(dependency: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, dependency }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/waitForStart', + rpcArgs + ); + return new AzureEventHubsEmulatorResource(result, this._client); + } + + /** Waits for another resource to start */ + waitForStart(dependency: ResourceBuilderBase): AzureEventHubsEmulatorResourcePromise { + return new AzureEventHubsEmulatorResourcePromise(this._waitForStartInternal(dependency)); + } + + /** @internal */ + private async _waitForStartWithBehaviorInternal(dependency: ResourceBuilderBase, waitBehavior: WaitBehavior): Promise { + const rpcArgs: Record = { builder: this._handle, dependency, waitBehavior }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/waitForStartWithBehavior', + rpcArgs + ); + return new AzureEventHubsEmulatorResource(result, this._client); + } + + /** Waits for another resource to start with specific behavior */ + waitForStartWithBehavior(dependency: ResourceBuilderBase, waitBehavior: WaitBehavior): AzureEventHubsEmulatorResourcePromise { + return new AzureEventHubsEmulatorResourcePromise(this._waitForStartWithBehaviorInternal(dependency, waitBehavior)); + } + + /** @internal */ + private async _withExplicitStartInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withExplicitStart', + rpcArgs + ); + return new AzureEventHubsEmulatorResource(result, this._client); + } + + /** Prevents resource from starting automatically */ + withExplicitStart(): AzureEventHubsEmulatorResourcePromise { + return new AzureEventHubsEmulatorResourcePromise(this._withExplicitStartInternal()); + } + + /** @internal */ + private async _waitForCompletionInternal(dependency: ResourceBuilderBase, exitCode?: number): Promise { + const rpcArgs: Record = { builder: this._handle, dependency }; + if (exitCode !== undefined) rpcArgs.exitCode = exitCode; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/waitForCompletion', + rpcArgs + ); + return new AzureEventHubsEmulatorResource(result, this._client); + } + + /** Waits for resource completion */ + waitForCompletion(dependency: ResourceBuilderBase, options?: WaitForCompletionOptions): AzureEventHubsEmulatorResourcePromise { + const exitCode = options?.exitCode; + return new AzureEventHubsEmulatorResourcePromise(this._waitForCompletionInternal(dependency, exitCode)); + } + + /** @internal */ + private async _withHealthCheckInternal(key: string): Promise { + const rpcArgs: Record = { builder: this._handle, key }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withHealthCheck', + rpcArgs + ); + return new AzureEventHubsEmulatorResource(result, this._client); + } + + /** Adds a health check by key */ + withHealthCheck(key: string): AzureEventHubsEmulatorResourcePromise { + return new AzureEventHubsEmulatorResourcePromise(this._withHealthCheckInternal(key)); + } + + /** @internal */ + private async _withHttpHealthCheckInternal(path?: string, statusCode?: number, endpointName?: string): Promise { + const rpcArgs: Record = { builder: this._handle }; + if (path !== undefined) rpcArgs.path = path; + if (statusCode !== undefined) rpcArgs.statusCode = statusCode; + if (endpointName !== undefined) rpcArgs.endpointName = endpointName; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withHttpHealthCheck', + rpcArgs + ); + return new AzureEventHubsEmulatorResource(result, this._client); + } + + /** Adds an HTTP health check */ + withHttpHealthCheck(options?: WithHttpHealthCheckOptions): AzureEventHubsEmulatorResourcePromise { + const path = options?.path; + const statusCode = options?.statusCode; + const endpointName = options?.endpointName; + return new AzureEventHubsEmulatorResourcePromise(this._withHttpHealthCheckInternal(path, statusCode, endpointName)); + } + + /** @internal */ + private async _withCommandInternal(name: string, displayName: string, executeCommand: (arg: ExecuteCommandContext) => Promise, commandOptions?: CommandOptions): Promise { + const executeCommandId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as ExecuteCommandContextHandle; + const arg = new ExecuteCommandContext(argHandle, this._client); + return await executeCommand(arg); + }); + const rpcArgs: Record = { builder: this._handle, name, displayName, executeCommand: executeCommandId }; + if (commandOptions !== undefined) rpcArgs.commandOptions = commandOptions; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withCommand', + rpcArgs + ); + return new AzureEventHubsEmulatorResource(result, this._client); + } + + /** Adds a resource command */ + withCommand(name: string, displayName: string, executeCommand: (arg: ExecuteCommandContext) => Promise, options?: WithCommandOptions): AzureEventHubsEmulatorResourcePromise { + const commandOptions = options?.commandOptions; + return new AzureEventHubsEmulatorResourcePromise(this._withCommandInternal(name, displayName, executeCommand, commandOptions)); + } + + /** @internal */ + private async _withDeveloperCertificateTrustInternal(trust: boolean): Promise { + const rpcArgs: Record = { builder: this._handle, trust }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withDeveloperCertificateTrust', + rpcArgs + ); + return new AzureEventHubsEmulatorResource(result, this._client); + } + + /** Configures developer certificate trust */ + withDeveloperCertificateTrust(trust: boolean): AzureEventHubsEmulatorResourcePromise { + return new AzureEventHubsEmulatorResourcePromise(this._withDeveloperCertificateTrustInternal(trust)); + } + + /** @internal */ + private async _withCertificateTrustScopeInternal(scope: CertificateTrustScope): Promise { + const rpcArgs: Record = { builder: this._handle, scope }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withCertificateTrustScope', + rpcArgs + ); + return new AzureEventHubsEmulatorResource(result, this._client); + } + + /** Sets the certificate trust scope */ + withCertificateTrustScope(scope: CertificateTrustScope): AzureEventHubsEmulatorResourcePromise { + return new AzureEventHubsEmulatorResourcePromise(this._withCertificateTrustScopeInternal(scope)); + } + + /** @internal */ + private async _withHttpsDeveloperCertificateInternal(password?: ParameterResource): Promise { + const rpcArgs: Record = { builder: this._handle }; + if (password !== undefined) rpcArgs.password = password; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withHttpsDeveloperCertificate', + rpcArgs + ); + return new AzureEventHubsEmulatorResource(result, this._client); + } + + /** Configures HTTPS with a developer certificate */ + withHttpsDeveloperCertificate(options?: WithHttpsDeveloperCertificateOptions): AzureEventHubsEmulatorResourcePromise { + const password = options?.password; + return new AzureEventHubsEmulatorResourcePromise(this._withHttpsDeveloperCertificateInternal(password)); + } + + /** @internal */ + private async _withoutHttpsCertificateInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withoutHttpsCertificate', + rpcArgs + ); + return new AzureEventHubsEmulatorResource(result, this._client); + } + + /** Removes HTTPS certificate configuration */ + withoutHttpsCertificate(): AzureEventHubsEmulatorResourcePromise { + return new AzureEventHubsEmulatorResourcePromise(this._withoutHttpsCertificateInternal()); + } + + /** @internal */ + private async _withParentRelationshipInternal(parent: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, parent }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withParentRelationship', + rpcArgs + ); + return new AzureEventHubsEmulatorResource(result, this._client); + } + + /** Sets the parent relationship */ + withParentRelationship(parent: ResourceBuilderBase): AzureEventHubsEmulatorResourcePromise { + return new AzureEventHubsEmulatorResourcePromise(this._withParentRelationshipInternal(parent)); + } + + /** @internal */ + private async _withChildRelationshipInternal(child: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, child }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withChildRelationship', + rpcArgs + ); + return new AzureEventHubsEmulatorResource(result, this._client); + } + + /** Sets a child relationship */ + withChildRelationship(child: ResourceBuilderBase): AzureEventHubsEmulatorResourcePromise { + return new AzureEventHubsEmulatorResourcePromise(this._withChildRelationshipInternal(child)); + } + + /** @internal */ + private async _withIconNameInternal(iconName: string, iconVariant?: IconVariant): Promise { + const rpcArgs: Record = { builder: this._handle, iconName }; + if (iconVariant !== undefined) rpcArgs.iconVariant = iconVariant; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withIconName', + rpcArgs + ); + return new AzureEventHubsEmulatorResource(result, this._client); + } + + /** Sets the icon for the resource */ + withIconName(iconName: string, options?: WithIconNameOptions): AzureEventHubsEmulatorResourcePromise { + const iconVariant = options?.iconVariant; + return new AzureEventHubsEmulatorResourcePromise(this._withIconNameInternal(iconName, iconVariant)); + } + + /** @internal */ + private async _withHttpProbeInternal(probeType: ProbeType, path?: string, initialDelaySeconds?: number, periodSeconds?: number, timeoutSeconds?: number, failureThreshold?: number, successThreshold?: number, endpointName?: string): Promise { + const rpcArgs: Record = { builder: this._handle, probeType }; + if (path !== undefined) rpcArgs.path = path; + if (initialDelaySeconds !== undefined) rpcArgs.initialDelaySeconds = initialDelaySeconds; + if (periodSeconds !== undefined) rpcArgs.periodSeconds = periodSeconds; + if (timeoutSeconds !== undefined) rpcArgs.timeoutSeconds = timeoutSeconds; + if (failureThreshold !== undefined) rpcArgs.failureThreshold = failureThreshold; + if (successThreshold !== undefined) rpcArgs.successThreshold = successThreshold; + if (endpointName !== undefined) rpcArgs.endpointName = endpointName; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withHttpProbe', + rpcArgs + ); + return new AzureEventHubsEmulatorResource(result, this._client); + } + + /** Adds an HTTP health probe to the resource */ + withHttpProbe(probeType: ProbeType, options?: WithHttpProbeOptions): AzureEventHubsEmulatorResourcePromise { + const path = options?.path; + const initialDelaySeconds = options?.initialDelaySeconds; + const periodSeconds = options?.periodSeconds; + const timeoutSeconds = options?.timeoutSeconds; + const failureThreshold = options?.failureThreshold; + const successThreshold = options?.successThreshold; + const endpointName = options?.endpointName; + return new AzureEventHubsEmulatorResourcePromise(this._withHttpProbeInternal(probeType, path, initialDelaySeconds, periodSeconds, timeoutSeconds, failureThreshold, successThreshold, endpointName)); + } + + /** @internal */ + private async _excludeFromMcpInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/excludeFromMcp', + rpcArgs + ); + return new AzureEventHubsEmulatorResource(result, this._client); + } + + /** Excludes the resource from MCP server exposure */ + excludeFromMcp(): AzureEventHubsEmulatorResourcePromise { + return new AzureEventHubsEmulatorResourcePromise(this._excludeFromMcpInternal()); + } + + /** @internal */ + private async _withRemoteImageNameInternal(remoteImageName: string): Promise { + const rpcArgs: Record = { builder: this._handle, remoteImageName }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withRemoteImageName', + rpcArgs + ); + return new AzureEventHubsEmulatorResource(result, this._client); + } + + /** Sets the remote image name for publishing */ + withRemoteImageName(remoteImageName: string): AzureEventHubsEmulatorResourcePromise { + return new AzureEventHubsEmulatorResourcePromise(this._withRemoteImageNameInternal(remoteImageName)); + } + + /** @internal */ + private async _withRemoteImageTagInternal(remoteImageTag: string): Promise { + const rpcArgs: Record = { builder: this._handle, remoteImageTag }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withRemoteImageTag', + rpcArgs + ); + return new AzureEventHubsEmulatorResource(result, this._client); + } + + /** Sets the remote image tag for publishing */ + withRemoteImageTag(remoteImageTag: string): AzureEventHubsEmulatorResourcePromise { + return new AzureEventHubsEmulatorResourcePromise(this._withRemoteImageTagInternal(remoteImageTag)); + } + + /** @internal */ + private async _withPipelineStepFactoryInternal(stepName: string, callback: (arg: PipelineStepContext) => Promise, dependsOn?: string[], requiredBy?: string[], tags?: string[], description?: string): Promise { + const callbackId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as PipelineStepContextHandle; + const arg = new PipelineStepContext(argHandle, this._client); + await callback(arg); + }); + const rpcArgs: Record = { builder: this._handle, stepName, callback: callbackId }; + if (dependsOn !== undefined) rpcArgs.dependsOn = dependsOn; + if (requiredBy !== undefined) rpcArgs.requiredBy = requiredBy; + if (tags !== undefined) rpcArgs.tags = tags; + if (description !== undefined) rpcArgs.description = description; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withPipelineStepFactory', + rpcArgs + ); + return new AzureEventHubsEmulatorResource(result, this._client); + } + + /** Adds a pipeline step to the resource */ + withPipelineStepFactory(stepName: string, callback: (arg: PipelineStepContext) => Promise, options?: WithPipelineStepFactoryOptions): AzureEventHubsEmulatorResourcePromise { + const dependsOn = options?.dependsOn; + const requiredBy = options?.requiredBy; + const tags = options?.tags; + const description = options?.description; + return new AzureEventHubsEmulatorResourcePromise(this._withPipelineStepFactoryInternal(stepName, callback, dependsOn, requiredBy, tags, description)); + } + + /** @internal */ + private async _withPipelineConfigurationAsyncInternal(callback: (arg: PipelineConfigurationContext) => Promise): Promise { + const callbackId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as PipelineConfigurationContextHandle; + const arg = new PipelineConfigurationContext(argHandle, this._client); + await callback(arg); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withPipelineConfigurationAsync', + rpcArgs + ); + return new AzureEventHubsEmulatorResource(result, this._client); + } + + /** Configures pipeline step dependencies via an async callback */ + withPipelineConfigurationAsync(callback: (arg: PipelineConfigurationContext) => Promise): AzureEventHubsEmulatorResourcePromise { + return new AzureEventHubsEmulatorResourcePromise(this._withPipelineConfigurationAsyncInternal(callback)); + } + + /** @internal */ + private async _withPipelineConfigurationInternal(callback: (obj: PipelineConfigurationContext) => Promise): Promise { + const callbackId = registerCallback(async (objData: unknown) => { + const objHandle = wrapIfHandle(objData) as PipelineConfigurationContextHandle; + const obj = new PipelineConfigurationContext(objHandle, this._client); + await callback(obj); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withPipelineConfiguration', + rpcArgs + ); + return new AzureEventHubsEmulatorResource(result, this._client); + } + + /** Configures pipeline step dependencies via a callback */ + withPipelineConfiguration(callback: (obj: PipelineConfigurationContext) => Promise): AzureEventHubsEmulatorResourcePromise { + return new AzureEventHubsEmulatorResourcePromise(this._withPipelineConfigurationInternal(callback)); + } + + /** @internal */ + private async _withVolumeInternal(target: string, name?: string, isReadOnly?: boolean): Promise { + const rpcArgs: Record = { resource: this._handle, target }; + if (name !== undefined) rpcArgs.name = name; + if (isReadOnly !== undefined) rpcArgs.isReadOnly = isReadOnly; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withVolume', + rpcArgs + ); + return new AzureEventHubsEmulatorResource(result, this._client); + } + + /** Adds a volume */ + withVolume(target: string, options?: WithVolumeOptions): AzureEventHubsEmulatorResourcePromise { + const name = options?.name; + const isReadOnly = options?.isReadOnly; + return new AzureEventHubsEmulatorResourcePromise(this._withVolumeInternal(target, name, isReadOnly)); + } + + /** Gets the resource name */ + async getResourceName(): Promise { + const rpcArgs: Record = { resource: this._handle }; + return await this._client.invokeCapability( + 'Aspire.Hosting/getResourceName', + rpcArgs + ); + } + + /** @internal */ + private async _withStorageRoleAssignmentsInternal(target: AzureStorageResource, roles: AzureStorageRole[]): Promise { + const rpcArgs: Record = { builder: this._handle, target, roles }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure.Storage/withStorageRoleAssignments', + rpcArgs + ); + return new AzureEventHubsEmulatorResource(result, this._client); + } + + /** Assigns Azure Storage roles to a resource */ + withStorageRoleAssignments(target: AzureStorageResource, roles: AzureStorageRole[]): AzureEventHubsEmulatorResourcePromise { + return new AzureEventHubsEmulatorResourcePromise(this._withStorageRoleAssignmentsInternal(target, roles)); + } + + /** @internal */ + private async _withHostPortInternal(port?: number): Promise { + const rpcArgs: Record = { builder: this._handle }; + if (port !== undefined) rpcArgs.port = port; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure.EventHubs/withHostPort', + rpcArgs + ); + return new AzureEventHubsEmulatorResource(result, this._client); + } + + /** Sets the host port for the Event Hubs emulator endpoint */ + withHostPort(options?: WithHostPortOptions): AzureEventHubsEmulatorResourcePromise { + const port = options?.port; + return new AzureEventHubsEmulatorResourcePromise(this._withHostPortInternal(port)); + } + + /** @internal */ + private async _withConfigurationFileInternal(path: string): Promise { + const rpcArgs: Record = { builder: this._handle, path }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure.EventHubs/withConfigurationFile', + rpcArgs + ); + return new AzureEventHubsEmulatorResource(result, this._client); + } + + /** Sets the emulator configuration file path */ + withConfigurationFile(path: string): AzureEventHubsEmulatorResourcePromise { + return new AzureEventHubsEmulatorResourcePromise(this._withConfigurationFileInternal(path)); + } + + /** @internal */ + private async _withEventHubsRoleAssignmentsInternal(target: AzureEventHubsResource, roles: AzureEventHubsRole[]): Promise { + const rpcArgs: Record = { builder: this._handle, target, roles }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure.EventHubs/withEventHubsRoleAssignments', + rpcArgs + ); + return new AzureEventHubsEmulatorResource(result, this._client); + } + + /** Assigns Event Hubs roles to a resource */ + withEventHubsRoleAssignments(target: AzureEventHubsResource, roles: AzureEventHubsRole[]): AzureEventHubsEmulatorResourcePromise { + return new AzureEventHubsEmulatorResourcePromise(this._withEventHubsRoleAssignmentsInternal(target, roles)); + } + + /** @internal */ + private async _withEnvironmentFromOutputInternal(name: string, bicepOutputReference: BicepOutputReference): Promise { + const rpcArgs: Record = { builder: this._handle, name, bicepOutputReference }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure/withEnvironmentFromOutput', + rpcArgs + ); + return new AzureEventHubsEmulatorResource(result, this._client); + } + + /** Sets an environment variable from a Bicep output reference */ + withEnvironmentFromOutput(name: string, bicepOutputReference: BicepOutputReference): AzureEventHubsEmulatorResourcePromise { + return new AzureEventHubsEmulatorResourcePromise(this._withEnvironmentFromOutputInternal(name, bicepOutputReference)); + } + + /** @internal */ + private async _withEnvironmentFromKeyVaultSecretInternal(name: string, secretReference: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, name, secretReference }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure/withEnvironmentFromKeyVaultSecret', + rpcArgs + ); + return new AzureEventHubsEmulatorResource(result, this._client); + } + + /** Sets an environment variable from an Azure Key Vault secret reference */ + withEnvironmentFromKeyVaultSecret(name: string, secretReference: ResourceBuilderBase): AzureEventHubsEmulatorResourcePromise { + return new AzureEventHubsEmulatorResourcePromise(this._withEnvironmentFromKeyVaultSecretInternal(name, secretReference)); + } + + /** @internal */ + private async _withAzureUserAssignedIdentityInternal(identityResourceBuilder: AzureUserAssignedIdentityResource): Promise { + const rpcArgs: Record = { builder: this._handle, identityResourceBuilder }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure/withUserAssignedIdentityAzureUserAssignedIdentity', + rpcArgs + ); + return new AzureEventHubsEmulatorResource(result, this._client); + } + + /** Associates an Azure user-assigned identity with a compute resource */ + withAzureUserAssignedIdentity(identityResourceBuilder: AzureUserAssignedIdentityResource): AzureEventHubsEmulatorResourcePromise { + return new AzureEventHubsEmulatorResourcePromise(this._withAzureUserAssignedIdentityInternal(identityResourceBuilder)); + } + +} + +/** + * Thenable wrapper for AzureEventHubsEmulatorResource that enables fluent chaining. + * @example + * await builder.addSomething().withX().withY(); + */ +export class AzureEventHubsEmulatorResourcePromise implements PromiseLike { + constructor(private _promise: Promise) {} + + then( + onfulfilled?: ((value: AzureEventHubsEmulatorResource) => TResult1 | PromiseLike) | null, + onrejected?: ((reason: unknown) => TResult2 | PromiseLike) | null + ): PromiseLike { + return this._promise.then(onfulfilled, onrejected); + } + + /** Configures a resource to use a container registry */ + withContainerRegistry(registry: ResourceBuilderBase): AzureEventHubsEmulatorResourcePromise { + return new AzureEventHubsEmulatorResourcePromise(this._promise.then(obj => obj.withContainerRegistry(registry))); + } + + /** Adds a bind mount */ + withBindMount(source: string, target: string, options?: WithBindMountOptions): AzureEventHubsEmulatorResourcePromise { + return new AzureEventHubsEmulatorResourcePromise(this._promise.then(obj => obj.withBindMount(source, target, options))); + } + + /** Sets the container entrypoint */ + withEntrypoint(entrypoint: string): AzureEventHubsEmulatorResourcePromise { + return new AzureEventHubsEmulatorResourcePromise(this._promise.then(obj => obj.withEntrypoint(entrypoint))); + } + + /** Sets the container image tag */ + withImageTag(tag: string): AzureEventHubsEmulatorResourcePromise { + return new AzureEventHubsEmulatorResourcePromise(this._promise.then(obj => obj.withImageTag(tag))); + } + + /** Sets the container image registry */ + withImageRegistry(registry: string): AzureEventHubsEmulatorResourcePromise { + return new AzureEventHubsEmulatorResourcePromise(this._promise.then(obj => obj.withImageRegistry(registry))); + } + + /** Sets the container image */ + withImage(image: string, options?: WithImageOptions): AzureEventHubsEmulatorResourcePromise { + return new AzureEventHubsEmulatorResourcePromise(this._promise.then(obj => obj.withImage(image, options))); + } + + /** Sets the image SHA256 digest */ + withImageSHA256(sha256: string): AzureEventHubsEmulatorResourcePromise { + return new AzureEventHubsEmulatorResourcePromise(this._promise.then(obj => obj.withImageSHA256(sha256))); + } + + /** Adds runtime arguments for the container */ + withContainerRuntimeArgs(args: string[]): AzureEventHubsEmulatorResourcePromise { + return new AzureEventHubsEmulatorResourcePromise(this._promise.then(obj => obj.withContainerRuntimeArgs(args))); + } + + /** Sets the lifetime behavior of the container resource */ + withLifetime(lifetime: ContainerLifetime): AzureEventHubsEmulatorResourcePromise { + return new AzureEventHubsEmulatorResourcePromise(this._promise.then(obj => obj.withLifetime(lifetime))); + } + + /** Sets the container image pull policy */ + withImagePullPolicy(pullPolicy: ImagePullPolicy): AzureEventHubsEmulatorResourcePromise { + return new AzureEventHubsEmulatorResourcePromise(this._promise.then(obj => obj.withImagePullPolicy(pullPolicy))); + } + + /** Configures the resource to be published as a container */ + publishAsContainer(): AzureEventHubsEmulatorResourcePromise { + return new AzureEventHubsEmulatorResourcePromise(this._promise.then(obj => obj.publishAsContainer())); + } + + /** Configures the resource to use a Dockerfile */ + withDockerfile(contextPath: string, options?: WithDockerfileOptions): AzureEventHubsEmulatorResourcePromise { + return new AzureEventHubsEmulatorResourcePromise(this._promise.then(obj => obj.withDockerfile(contextPath, options))); + } + + /** Sets the container name */ + withContainerName(name: string): AzureEventHubsEmulatorResourcePromise { + return new AzureEventHubsEmulatorResourcePromise(this._promise.then(obj => obj.withContainerName(name))); + } + + /** Adds a build argument from a parameter resource */ + withBuildArg(name: string, value: ParameterResource): AzureEventHubsEmulatorResourcePromise { + return new AzureEventHubsEmulatorResourcePromise(this._promise.then(obj => obj.withBuildArg(name, value))); + } + + /** Adds a build secret from a parameter resource */ + withBuildSecret(name: string, value: ParameterResource): AzureEventHubsEmulatorResourcePromise { + return new AzureEventHubsEmulatorResourcePromise(this._promise.then(obj => obj.withBuildSecret(name, value))); + } + + /** Configures endpoint proxy support */ + withEndpointProxySupport(proxyEnabled: boolean): AzureEventHubsEmulatorResourcePromise { + return new AzureEventHubsEmulatorResourcePromise(this._promise.then(obj => obj.withEndpointProxySupport(proxyEnabled))); + } + + /** Sets the base image for a Dockerfile build */ + withDockerfileBaseImage(options?: WithDockerfileBaseImageOptions): AzureEventHubsEmulatorResourcePromise { + return new AzureEventHubsEmulatorResourcePromise(this._promise.then(obj => obj.withDockerfileBaseImage(options))); + } + + /** Adds a network alias for the container */ + withContainerNetworkAlias(alias: string): AzureEventHubsEmulatorResourcePromise { + return new AzureEventHubsEmulatorResourcePromise(this._promise.then(obj => obj.withContainerNetworkAlias(alias))); + } + + /** Configures an MCP server endpoint on the resource */ + withMcpServer(options?: WithMcpServerOptions): AzureEventHubsEmulatorResourcePromise { + return new AzureEventHubsEmulatorResourcePromise(this._promise.then(obj => obj.withMcpServer(options))); + } + + /** Configures OTLP telemetry export */ + withOtlpExporter(): AzureEventHubsEmulatorResourcePromise { + return new AzureEventHubsEmulatorResourcePromise(this._promise.then(obj => obj.withOtlpExporter())); + } + + /** Configures OTLP telemetry export with specific protocol */ + withOtlpExporterProtocol(protocol: OtlpProtocol): AzureEventHubsEmulatorResourcePromise { + return new AzureEventHubsEmulatorResourcePromise(this._promise.then(obj => obj.withOtlpExporterProtocol(protocol))); + } + + /** Publishes the resource as a connection string */ + publishAsConnectionString(): AzureEventHubsEmulatorResourcePromise { + return new AzureEventHubsEmulatorResourcePromise(this._promise.then(obj => obj.publishAsConnectionString())); + } + + /** Adds a required command dependency */ + withRequiredCommand(command: string, options?: WithRequiredCommandOptions): AzureEventHubsEmulatorResourcePromise { + return new AzureEventHubsEmulatorResourcePromise(this._promise.then(obj => obj.withRequiredCommand(command, options))); + } + + /** Sets an environment variable */ + withEnvironment(name: string, value: string): AzureEventHubsEmulatorResourcePromise { + return new AzureEventHubsEmulatorResourcePromise(this._promise.then(obj => obj.withEnvironment(name, value))); + } + + /** Adds an environment variable with a reference expression */ + withEnvironmentExpression(name: string, value: ReferenceExpression): AzureEventHubsEmulatorResourcePromise { + return new AzureEventHubsEmulatorResourcePromise(this._promise.then(obj => obj.withEnvironmentExpression(name, value))); + } + + /** Sets environment variables via callback */ + withEnvironmentCallback(callback: (obj: EnvironmentCallbackContext) => Promise): AzureEventHubsEmulatorResourcePromise { + return new AzureEventHubsEmulatorResourcePromise(this._promise.then(obj => obj.withEnvironmentCallback(callback))); + } + + /** Sets environment variables via async callback */ + withEnvironmentCallbackAsync(callback: (arg: EnvironmentCallbackContext) => Promise): AzureEventHubsEmulatorResourcePromise { + return new AzureEventHubsEmulatorResourcePromise(this._promise.then(obj => obj.withEnvironmentCallbackAsync(callback))); + } + + /** Sets an environment variable from an endpoint reference */ + withEnvironmentEndpoint(name: string, endpointReference: EndpointReference): AzureEventHubsEmulatorResourcePromise { + return new AzureEventHubsEmulatorResourcePromise(this._promise.then(obj => obj.withEnvironmentEndpoint(name, endpointReference))); + } + + /** Sets an environment variable from a parameter resource */ + withEnvironmentParameter(name: string, parameter: ParameterResource): AzureEventHubsEmulatorResourcePromise { + return new AzureEventHubsEmulatorResourcePromise(this._promise.then(obj => obj.withEnvironmentParameter(name, parameter))); + } + + /** Sets an environment variable from a connection string resource */ + withEnvironmentConnectionString(envVarName: string, resource: ResourceBuilderBase): AzureEventHubsEmulatorResourcePromise { + return new AzureEventHubsEmulatorResourcePromise(this._promise.then(obj => obj.withEnvironmentConnectionString(envVarName, resource))); + } + + /** Adds arguments */ + withArgs(args: string[]): AzureEventHubsEmulatorResourcePromise { + return new AzureEventHubsEmulatorResourcePromise(this._promise.then(obj => obj.withArgs(args))); + } + + /** Sets command-line arguments via callback */ + withArgsCallback(callback: (obj: CommandLineArgsCallbackContext) => Promise): AzureEventHubsEmulatorResourcePromise { + return new AzureEventHubsEmulatorResourcePromise(this._promise.then(obj => obj.withArgsCallback(callback))); + } + + /** Sets command-line arguments via async callback */ + withArgsCallbackAsync(callback: (arg: CommandLineArgsCallbackContext) => Promise): AzureEventHubsEmulatorResourcePromise { + return new AzureEventHubsEmulatorResourcePromise(this._promise.then(obj => obj.withArgsCallbackAsync(callback))); + } + + /** Adds a reference to another resource */ + withReference(source: ResourceBuilderBase, options?: WithReferenceOptions): AzureEventHubsEmulatorResourcePromise { + return new AzureEventHubsEmulatorResourcePromise(this._promise.then(obj => obj.withReference(source, options))); + } + + /** Adds a service discovery reference to another resource */ + withServiceReference(source: ResourceBuilderBase): AzureEventHubsEmulatorResourcePromise { + return new AzureEventHubsEmulatorResourcePromise(this._promise.then(obj => obj.withServiceReference(source))); + } + + /** Adds a named service discovery reference */ + withServiceReferenceNamed(source: ResourceBuilderBase, name: string): AzureEventHubsEmulatorResourcePromise { + return new AzureEventHubsEmulatorResourcePromise(this._promise.then(obj => obj.withServiceReferenceNamed(source, name))); + } + + /** Adds a reference to a URI */ + withReferenceUri(name: string, uri: string): AzureEventHubsEmulatorResourcePromise { + return new AzureEventHubsEmulatorResourcePromise(this._promise.then(obj => obj.withReferenceUri(name, uri))); + } + + /** Adds a reference to an external service */ + withReferenceExternalService(externalService: ExternalServiceResource): AzureEventHubsEmulatorResourcePromise { + return new AzureEventHubsEmulatorResourcePromise(this._promise.then(obj => obj.withReferenceExternalService(externalService))); + } + + /** Adds a reference to an endpoint */ + withReferenceEndpoint(endpointReference: EndpointReference): AzureEventHubsEmulatorResourcePromise { + return new AzureEventHubsEmulatorResourcePromise(this._promise.then(obj => obj.withReferenceEndpoint(endpointReference))); + } + + /** Adds a network endpoint */ + withEndpoint(options?: WithEndpointOptions): AzureEventHubsEmulatorResourcePromise { + return new AzureEventHubsEmulatorResourcePromise(this._promise.then(obj => obj.withEndpoint(options))); + } + + /** Adds an HTTP endpoint */ + withHttpEndpoint(options?: WithHttpEndpointOptions): AzureEventHubsEmulatorResourcePromise { + return new AzureEventHubsEmulatorResourcePromise(this._promise.then(obj => obj.withHttpEndpoint(options))); + } + + /** Adds an HTTPS endpoint */ + withHttpsEndpoint(options?: WithHttpsEndpointOptions): AzureEventHubsEmulatorResourcePromise { + return new AzureEventHubsEmulatorResourcePromise(this._promise.then(obj => obj.withHttpsEndpoint(options))); + } + + /** Makes HTTP endpoints externally accessible */ + withExternalHttpEndpoints(): AzureEventHubsEmulatorResourcePromise { + return new AzureEventHubsEmulatorResourcePromise(this._promise.then(obj => obj.withExternalHttpEndpoints())); + } + + /** Gets an endpoint reference */ + getEndpoint(name: string): Promise { + return this._promise.then(obj => obj.getEndpoint(name)); + } + + /** Configures resource for HTTP/2 */ + asHttp2Service(): AzureEventHubsEmulatorResourcePromise { + return new AzureEventHubsEmulatorResourcePromise(this._promise.then(obj => obj.asHttp2Service())); + } + + /** Customizes displayed URLs via callback */ + withUrlsCallback(callback: (obj: ResourceUrlsCallbackContext) => Promise): AzureEventHubsEmulatorResourcePromise { + return new AzureEventHubsEmulatorResourcePromise(this._promise.then(obj => obj.withUrlsCallback(callback))); + } + + /** Customizes displayed URLs via async callback */ + withUrlsCallbackAsync(callback: (arg: ResourceUrlsCallbackContext) => Promise): AzureEventHubsEmulatorResourcePromise { + return new AzureEventHubsEmulatorResourcePromise(this._promise.then(obj => obj.withUrlsCallbackAsync(callback))); + } + + /** Adds or modifies displayed URLs */ + withUrl(url: string, options?: WithUrlOptions): AzureEventHubsEmulatorResourcePromise { + return new AzureEventHubsEmulatorResourcePromise(this._promise.then(obj => obj.withUrl(url, options))); + } + + /** Adds a URL using a reference expression */ + withUrlExpression(url: ReferenceExpression, options?: WithUrlExpressionOptions): AzureEventHubsEmulatorResourcePromise { + return new AzureEventHubsEmulatorResourcePromise(this._promise.then(obj => obj.withUrlExpression(url, options))); + } + + /** Customizes the URL for a specific endpoint via callback */ + withUrlForEndpoint(endpointName: string, callback: (obj: ResourceUrlAnnotation) => Promise): AzureEventHubsEmulatorResourcePromise { + return new AzureEventHubsEmulatorResourcePromise(this._promise.then(obj => obj.withUrlForEndpoint(endpointName, callback))); + } + + /** Adds a URL for a specific endpoint via factory callback */ + withUrlForEndpointFactory(endpointName: string, callback: (arg: EndpointReference) => Promise): AzureEventHubsEmulatorResourcePromise { + return new AzureEventHubsEmulatorResourcePromise(this._promise.then(obj => obj.withUrlForEndpointFactory(endpointName, callback))); + } + + /** Excludes the resource from the deployment manifest */ + excludeFromManifest(): AzureEventHubsEmulatorResourcePromise { + return new AzureEventHubsEmulatorResourcePromise(this._promise.then(obj => obj.excludeFromManifest())); + } + + /** Waits for another resource to be ready */ + waitFor(dependency: ResourceBuilderBase): AzureEventHubsEmulatorResourcePromise { + return new AzureEventHubsEmulatorResourcePromise(this._promise.then(obj => obj.waitFor(dependency))); + } + + /** Waits for another resource with specific behavior */ + waitForWithBehavior(dependency: ResourceBuilderBase, waitBehavior: WaitBehavior): AzureEventHubsEmulatorResourcePromise { + return new AzureEventHubsEmulatorResourcePromise(this._promise.then(obj => obj.waitForWithBehavior(dependency, waitBehavior))); + } + + /** Waits for another resource to start */ + waitForStart(dependency: ResourceBuilderBase): AzureEventHubsEmulatorResourcePromise { + return new AzureEventHubsEmulatorResourcePromise(this._promise.then(obj => obj.waitForStart(dependency))); + } + + /** Waits for another resource to start with specific behavior */ + waitForStartWithBehavior(dependency: ResourceBuilderBase, waitBehavior: WaitBehavior): AzureEventHubsEmulatorResourcePromise { + return new AzureEventHubsEmulatorResourcePromise(this._promise.then(obj => obj.waitForStartWithBehavior(dependency, waitBehavior))); + } + + /** Prevents resource from starting automatically */ + withExplicitStart(): AzureEventHubsEmulatorResourcePromise { + return new AzureEventHubsEmulatorResourcePromise(this._promise.then(obj => obj.withExplicitStart())); + } + + /** Waits for resource completion */ + waitForCompletion(dependency: ResourceBuilderBase, options?: WaitForCompletionOptions): AzureEventHubsEmulatorResourcePromise { + return new AzureEventHubsEmulatorResourcePromise(this._promise.then(obj => obj.waitForCompletion(dependency, options))); + } + + /** Adds a health check by key */ + withHealthCheck(key: string): AzureEventHubsEmulatorResourcePromise { + return new AzureEventHubsEmulatorResourcePromise(this._promise.then(obj => obj.withHealthCheck(key))); + } + + /** Adds an HTTP health check */ + withHttpHealthCheck(options?: WithHttpHealthCheckOptions): AzureEventHubsEmulatorResourcePromise { + return new AzureEventHubsEmulatorResourcePromise(this._promise.then(obj => obj.withHttpHealthCheck(options))); + } + + /** Adds a resource command */ + withCommand(name: string, displayName: string, executeCommand: (arg: ExecuteCommandContext) => Promise, options?: WithCommandOptions): AzureEventHubsEmulatorResourcePromise { + return new AzureEventHubsEmulatorResourcePromise(this._promise.then(obj => obj.withCommand(name, displayName, executeCommand, options))); + } + + /** Configures developer certificate trust */ + withDeveloperCertificateTrust(trust: boolean): AzureEventHubsEmulatorResourcePromise { + return new AzureEventHubsEmulatorResourcePromise(this._promise.then(obj => obj.withDeveloperCertificateTrust(trust))); + } + + /** Sets the certificate trust scope */ + withCertificateTrustScope(scope: CertificateTrustScope): AzureEventHubsEmulatorResourcePromise { + return new AzureEventHubsEmulatorResourcePromise(this._promise.then(obj => obj.withCertificateTrustScope(scope))); + } + + /** Configures HTTPS with a developer certificate */ + withHttpsDeveloperCertificate(options?: WithHttpsDeveloperCertificateOptions): AzureEventHubsEmulatorResourcePromise { + return new AzureEventHubsEmulatorResourcePromise(this._promise.then(obj => obj.withHttpsDeveloperCertificate(options))); + } + + /** Removes HTTPS certificate configuration */ + withoutHttpsCertificate(): AzureEventHubsEmulatorResourcePromise { + return new AzureEventHubsEmulatorResourcePromise(this._promise.then(obj => obj.withoutHttpsCertificate())); + } + + /** Sets the parent relationship */ + withParentRelationship(parent: ResourceBuilderBase): AzureEventHubsEmulatorResourcePromise { + return new AzureEventHubsEmulatorResourcePromise(this._promise.then(obj => obj.withParentRelationship(parent))); + } + + /** Sets a child relationship */ + withChildRelationship(child: ResourceBuilderBase): AzureEventHubsEmulatorResourcePromise { + return new AzureEventHubsEmulatorResourcePromise(this._promise.then(obj => obj.withChildRelationship(child))); + } + + /** Sets the icon for the resource */ + withIconName(iconName: string, options?: WithIconNameOptions): AzureEventHubsEmulatorResourcePromise { + return new AzureEventHubsEmulatorResourcePromise(this._promise.then(obj => obj.withIconName(iconName, options))); + } + + /** Adds an HTTP health probe to the resource */ + withHttpProbe(probeType: ProbeType, options?: WithHttpProbeOptions): AzureEventHubsEmulatorResourcePromise { + return new AzureEventHubsEmulatorResourcePromise(this._promise.then(obj => obj.withHttpProbe(probeType, options))); + } + + /** Excludes the resource from MCP server exposure */ + excludeFromMcp(): AzureEventHubsEmulatorResourcePromise { + return new AzureEventHubsEmulatorResourcePromise(this._promise.then(obj => obj.excludeFromMcp())); + } + + /** Sets the remote image name for publishing */ + withRemoteImageName(remoteImageName: string): AzureEventHubsEmulatorResourcePromise { + return new AzureEventHubsEmulatorResourcePromise(this._promise.then(obj => obj.withRemoteImageName(remoteImageName))); + } + + /** Sets the remote image tag for publishing */ + withRemoteImageTag(remoteImageTag: string): AzureEventHubsEmulatorResourcePromise { + return new AzureEventHubsEmulatorResourcePromise(this._promise.then(obj => obj.withRemoteImageTag(remoteImageTag))); + } + + /** Adds a pipeline step to the resource */ + withPipelineStepFactory(stepName: string, callback: (arg: PipelineStepContext) => Promise, options?: WithPipelineStepFactoryOptions): AzureEventHubsEmulatorResourcePromise { + return new AzureEventHubsEmulatorResourcePromise(this._promise.then(obj => obj.withPipelineStepFactory(stepName, callback, options))); + } + + /** Configures pipeline step dependencies via an async callback */ + withPipelineConfigurationAsync(callback: (arg: PipelineConfigurationContext) => Promise): AzureEventHubsEmulatorResourcePromise { + return new AzureEventHubsEmulatorResourcePromise(this._promise.then(obj => obj.withPipelineConfigurationAsync(callback))); + } + + /** Configures pipeline step dependencies via a callback */ + withPipelineConfiguration(callback: (obj: PipelineConfigurationContext) => Promise): AzureEventHubsEmulatorResourcePromise { + return new AzureEventHubsEmulatorResourcePromise(this._promise.then(obj => obj.withPipelineConfiguration(callback))); + } + + /** Adds a volume */ + withVolume(target: string, options?: WithVolumeOptions): AzureEventHubsEmulatorResourcePromise { + return new AzureEventHubsEmulatorResourcePromise(this._promise.then(obj => obj.withVolume(target, options))); + } + + /** Gets the resource name */ + getResourceName(): Promise { + return this._promise.then(obj => obj.getResourceName()); + } + + /** Assigns Azure Storage roles to a resource */ + withStorageRoleAssignments(target: AzureStorageResource, roles: AzureStorageRole[]): AzureEventHubsEmulatorResourcePromise { + return new AzureEventHubsEmulatorResourcePromise(this._promise.then(obj => obj.withStorageRoleAssignments(target, roles))); + } + + /** Sets the host port for the Event Hubs emulator endpoint */ + withHostPort(options?: WithHostPortOptions): AzureEventHubsEmulatorResourcePromise { + return new AzureEventHubsEmulatorResourcePromise(this._promise.then(obj => obj.withHostPort(options))); + } + + /** Sets the emulator configuration file path */ + withConfigurationFile(path: string): AzureEventHubsEmulatorResourcePromise { + return new AzureEventHubsEmulatorResourcePromise(this._promise.then(obj => obj.withConfigurationFile(path))); + } + + /** Assigns Event Hubs roles to a resource */ + withEventHubsRoleAssignments(target: AzureEventHubsResource, roles: AzureEventHubsRole[]): AzureEventHubsEmulatorResourcePromise { + return new AzureEventHubsEmulatorResourcePromise(this._promise.then(obj => obj.withEventHubsRoleAssignments(target, roles))); + } + + /** Sets an environment variable from a Bicep output reference */ + withEnvironmentFromOutput(name: string, bicepOutputReference: BicepOutputReference): AzureEventHubsEmulatorResourcePromise { + return new AzureEventHubsEmulatorResourcePromise(this._promise.then(obj => obj.withEnvironmentFromOutput(name, bicepOutputReference))); + } + + /** Sets an environment variable from an Azure Key Vault secret reference */ + withEnvironmentFromKeyVaultSecret(name: string, secretReference: ResourceBuilderBase): AzureEventHubsEmulatorResourcePromise { + return new AzureEventHubsEmulatorResourcePromise(this._promise.then(obj => obj.withEnvironmentFromKeyVaultSecret(name, secretReference))); + } + + /** Associates an Azure user-assigned identity with a compute resource */ + withAzureUserAssignedIdentity(identityResourceBuilder: AzureUserAssignedIdentityResource): AzureEventHubsEmulatorResourcePromise { + return new AzureEventHubsEmulatorResourcePromise(this._promise.then(obj => obj.withAzureUserAssignedIdentity(identityResourceBuilder))); + } + +} + +// ============================================================================ +// AzureEventHubsResource +// ============================================================================ + +export class AzureEventHubsResource extends ResourceBuilderBase { + constructor(handle: AzureEventHubsResourceHandle, client: AspireClientRpc) { + super(handle, client); + } + + /** @internal */ + private async _withContainerRegistryInternal(registry: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, registry }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withContainerRegistry', + rpcArgs + ); + return new AzureEventHubsResource(result, this._client); + } + + /** Configures a resource to use a container registry */ + withContainerRegistry(registry: ResourceBuilderBase): AzureEventHubsResourcePromise { + return new AzureEventHubsResourcePromise(this._withContainerRegistryInternal(registry)); + } + + /** @internal */ + private async _withDockerfileBaseImageInternal(buildImage?: string, runtimeImage?: string): Promise { + const rpcArgs: Record = { builder: this._handle }; + if (buildImage !== undefined) rpcArgs.buildImage = buildImage; + if (runtimeImage !== undefined) rpcArgs.runtimeImage = runtimeImage; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withDockerfileBaseImage', + rpcArgs + ); + return new AzureEventHubsResource(result, this._client); + } + + /** Sets the base image for a Dockerfile build */ + withDockerfileBaseImage(options?: WithDockerfileBaseImageOptions): AzureEventHubsResourcePromise { + const buildImage = options?.buildImage; + const runtimeImage = options?.runtimeImage; + return new AzureEventHubsResourcePromise(this._withDockerfileBaseImageInternal(buildImage, runtimeImage)); + } + + /** @internal */ + private async _withMcpServerInternal(path?: string, endpointName?: string): Promise { + const rpcArgs: Record = { builder: this._handle }; + if (path !== undefined) rpcArgs.path = path; + if (endpointName !== undefined) rpcArgs.endpointName = endpointName; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withMcpServer', + rpcArgs + ); + return new AzureEventHubsResource(result, this._client); + } + + /** Configures an MCP server endpoint on the resource */ + withMcpServer(options?: WithMcpServerOptions): AzureEventHubsResourcePromise { + const path = options?.path; + const endpointName = options?.endpointName; + return new AzureEventHubsResourcePromise(this._withMcpServerInternal(path, endpointName)); + } + + /** @internal */ + private async _withRequiredCommandInternal(command: string, helpLink?: string): Promise { + const rpcArgs: Record = { builder: this._handle, command }; + if (helpLink !== undefined) rpcArgs.helpLink = helpLink; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withRequiredCommand', + rpcArgs + ); + return new AzureEventHubsResource(result, this._client); + } + + /** Adds a required command dependency */ + withRequiredCommand(command: string, options?: WithRequiredCommandOptions): AzureEventHubsResourcePromise { + const helpLink = options?.helpLink; + return new AzureEventHubsResourcePromise(this._withRequiredCommandInternal(command, helpLink)); + } + + /** @internal */ + private async _withConnectionPropertyInternal(name: string, value: ReferenceExpression): Promise { + const rpcArgs: Record = { builder: this._handle, name, value }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withConnectionProperty', + rpcArgs + ); + return new AzureEventHubsResource(result, this._client); + } + + /** Adds a connection property with a reference expression */ + withConnectionProperty(name: string, value: ReferenceExpression): AzureEventHubsResourcePromise { + return new AzureEventHubsResourcePromise(this._withConnectionPropertyInternal(name, value)); + } + + /** @internal */ + private async _withConnectionPropertyValueInternal(name: string, value: string): Promise { + const rpcArgs: Record = { builder: this._handle, name, value }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withConnectionPropertyValue', + rpcArgs + ); + return new AzureEventHubsResource(result, this._client); + } + + /** Adds a connection property with a string value */ + withConnectionPropertyValue(name: string, value: string): AzureEventHubsResourcePromise { + return new AzureEventHubsResourcePromise(this._withConnectionPropertyValueInternal(name, value)); + } + + /** @internal */ + private async _withEndpointInternal(port?: number, targetPort?: number, scheme?: string, name?: string, env?: string, isProxied?: boolean, isExternal?: boolean, protocol?: ProtocolType): Promise { + const rpcArgs: Record = { builder: this._handle }; + if (port !== undefined) rpcArgs.port = port; + if (targetPort !== undefined) rpcArgs.targetPort = targetPort; + if (scheme !== undefined) rpcArgs.scheme = scheme; + if (name !== undefined) rpcArgs.name = name; + if (env !== undefined) rpcArgs.env = env; + if (isProxied !== undefined) rpcArgs.isProxied = isProxied; + if (isExternal !== undefined) rpcArgs.isExternal = isExternal; + if (protocol !== undefined) rpcArgs.protocol = protocol; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withEndpoint', + rpcArgs + ); + return new AzureEventHubsResource(result, this._client); + } + + /** Adds a network endpoint */ + withEndpoint(options?: WithEndpointOptions): AzureEventHubsResourcePromise { + const port = options?.port; + const targetPort = options?.targetPort; + const scheme = options?.scheme; + const name = options?.name; + const env = options?.env; + const isProxied = options?.isProxied; + const isExternal = options?.isExternal; + const protocol = options?.protocol; + return new AzureEventHubsResourcePromise(this._withEndpointInternal(port, targetPort, scheme, name, env, isProxied, isExternal, protocol)); + } + + /** @internal */ + private async _withHttpEndpointInternal(port?: number, targetPort?: number, name?: string, env?: string, isProxied?: boolean): Promise { + const rpcArgs: Record = { builder: this._handle }; + if (port !== undefined) rpcArgs.port = port; + if (targetPort !== undefined) rpcArgs.targetPort = targetPort; + if (name !== undefined) rpcArgs.name = name; + if (env !== undefined) rpcArgs.env = env; + if (isProxied !== undefined) rpcArgs.isProxied = isProxied; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withHttpEndpoint', + rpcArgs + ); + return new AzureEventHubsResource(result, this._client); + } + + /** Adds an HTTP endpoint */ + withHttpEndpoint(options?: WithHttpEndpointOptions): AzureEventHubsResourcePromise { + const port = options?.port; + const targetPort = options?.targetPort; + const name = options?.name; + const env = options?.env; + const isProxied = options?.isProxied; + return new AzureEventHubsResourcePromise(this._withHttpEndpointInternal(port, targetPort, name, env, isProxied)); + } + + /** @internal */ + private async _withHttpsEndpointInternal(port?: number, targetPort?: number, name?: string, env?: string, isProxied?: boolean): Promise { + const rpcArgs: Record = { builder: this._handle }; + if (port !== undefined) rpcArgs.port = port; + if (targetPort !== undefined) rpcArgs.targetPort = targetPort; + if (name !== undefined) rpcArgs.name = name; + if (env !== undefined) rpcArgs.env = env; + if (isProxied !== undefined) rpcArgs.isProxied = isProxied; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withHttpsEndpoint', + rpcArgs + ); + return new AzureEventHubsResource(result, this._client); + } + + /** Adds an HTTPS endpoint */ + withHttpsEndpoint(options?: WithHttpsEndpointOptions): AzureEventHubsResourcePromise { + const port = options?.port; + const targetPort = options?.targetPort; + const name = options?.name; + const env = options?.env; + const isProxied = options?.isProxied; + return new AzureEventHubsResourcePromise(this._withHttpsEndpointInternal(port, targetPort, name, env, isProxied)); + } + + /** @internal */ + private async _withExternalHttpEndpointsInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withExternalHttpEndpoints', + rpcArgs + ); + return new AzureEventHubsResource(result, this._client); + } + + /** Makes HTTP endpoints externally accessible */ + withExternalHttpEndpoints(): AzureEventHubsResourcePromise { + return new AzureEventHubsResourcePromise(this._withExternalHttpEndpointsInternal()); + } + + /** Gets an endpoint reference */ + async getEndpoint(name: string): Promise { + const rpcArgs: Record = { builder: this._handle, name }; + return await this._client.invokeCapability( + 'Aspire.Hosting/getEndpoint', + rpcArgs + ); + } + + /** @internal */ + private async _asHttp2ServiceInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/asHttp2Service', + rpcArgs + ); + return new AzureEventHubsResource(result, this._client); + } + + /** Configures resource for HTTP/2 */ + asHttp2Service(): AzureEventHubsResourcePromise { + return new AzureEventHubsResourcePromise(this._asHttp2ServiceInternal()); + } + + /** @internal */ + private async _withUrlsCallbackInternal(callback: (obj: ResourceUrlsCallbackContext) => Promise): Promise { + const callbackId = registerCallback(async (objData: unknown) => { + const objHandle = wrapIfHandle(objData) as ResourceUrlsCallbackContextHandle; + const obj = new ResourceUrlsCallbackContext(objHandle, this._client); + await callback(obj); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrlsCallback', + rpcArgs + ); + return new AzureEventHubsResource(result, this._client); + } + + /** Customizes displayed URLs via callback */ + withUrlsCallback(callback: (obj: ResourceUrlsCallbackContext) => Promise): AzureEventHubsResourcePromise { + return new AzureEventHubsResourcePromise(this._withUrlsCallbackInternal(callback)); + } + + /** @internal */ + private async _withUrlsCallbackAsyncInternal(callback: (arg: ResourceUrlsCallbackContext) => Promise): Promise { + const callbackId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as ResourceUrlsCallbackContextHandle; + const arg = new ResourceUrlsCallbackContext(argHandle, this._client); + await callback(arg); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrlsCallbackAsync', + rpcArgs + ); + return new AzureEventHubsResource(result, this._client); + } + + /** Customizes displayed URLs via async callback */ + withUrlsCallbackAsync(callback: (arg: ResourceUrlsCallbackContext) => Promise): AzureEventHubsResourcePromise { + return new AzureEventHubsResourcePromise(this._withUrlsCallbackAsyncInternal(callback)); + } + + /** @internal */ + private async _withUrlInternal(url: string, displayText?: string): Promise { + const rpcArgs: Record = { builder: this._handle, url }; + if (displayText !== undefined) rpcArgs.displayText = displayText; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrl', + rpcArgs + ); + return new AzureEventHubsResource(result, this._client); + } + + /** Adds or modifies displayed URLs */ + withUrl(url: string, options?: WithUrlOptions): AzureEventHubsResourcePromise { + const displayText = options?.displayText; + return new AzureEventHubsResourcePromise(this._withUrlInternal(url, displayText)); + } + + /** @internal */ + private async _withUrlExpressionInternal(url: ReferenceExpression, displayText?: string): Promise { + const rpcArgs: Record = { builder: this._handle, url }; + if (displayText !== undefined) rpcArgs.displayText = displayText; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrlExpression', + rpcArgs + ); + return new AzureEventHubsResource(result, this._client); + } + + /** Adds a URL using a reference expression */ + withUrlExpression(url: ReferenceExpression, options?: WithUrlExpressionOptions): AzureEventHubsResourcePromise { + const displayText = options?.displayText; + return new AzureEventHubsResourcePromise(this._withUrlExpressionInternal(url, displayText)); + } + + /** @internal */ + private async _withUrlForEndpointInternal(endpointName: string, callback: (obj: ResourceUrlAnnotation) => Promise): Promise { + const callbackId = registerCallback(async (objData: unknown) => { + const obj = wrapIfHandle(objData) as ResourceUrlAnnotation; + await callback(obj); + }); + const rpcArgs: Record = { builder: this._handle, endpointName, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrlForEndpoint', + rpcArgs + ); + return new AzureEventHubsResource(result, this._client); + } + + /** Customizes the URL for a specific endpoint via callback */ + withUrlForEndpoint(endpointName: string, callback: (obj: ResourceUrlAnnotation) => Promise): AzureEventHubsResourcePromise { + return new AzureEventHubsResourcePromise(this._withUrlForEndpointInternal(endpointName, callback)); + } + + /** @internal */ + private async _withUrlForEndpointFactoryInternal(endpointName: string, callback: (arg: EndpointReference) => Promise): Promise { + const callbackId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as EndpointReferenceHandle; + const arg = new EndpointReference(argHandle, this._client); + return await callback(arg); + }); + const rpcArgs: Record = { builder: this._handle, endpointName, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrlForEndpointFactory', + rpcArgs + ); + return new AzureEventHubsResource(result, this._client); + } + + /** Adds a URL for a specific endpoint via factory callback */ + withUrlForEndpointFactory(endpointName: string, callback: (arg: EndpointReference) => Promise): AzureEventHubsResourcePromise { + return new AzureEventHubsResourcePromise(this._withUrlForEndpointFactoryInternal(endpointName, callback)); + } + + /** @internal */ + private async _excludeFromManifestInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/excludeFromManifest', + rpcArgs + ); + return new AzureEventHubsResource(result, this._client); + } + + /** Excludes the resource from the deployment manifest */ + excludeFromManifest(): AzureEventHubsResourcePromise { + return new AzureEventHubsResourcePromise(this._excludeFromManifestInternal()); + } + + /** @internal */ + private async _withExplicitStartInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withExplicitStart', + rpcArgs + ); + return new AzureEventHubsResource(result, this._client); + } + + /** Prevents resource from starting automatically */ + withExplicitStart(): AzureEventHubsResourcePromise { + return new AzureEventHubsResourcePromise(this._withExplicitStartInternal()); + } + + /** @internal */ + private async _withHealthCheckInternal(key: string): Promise { + const rpcArgs: Record = { builder: this._handle, key }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withHealthCheck', + rpcArgs + ); + return new AzureEventHubsResource(result, this._client); + } + + /** Adds a health check by key */ + withHealthCheck(key: string): AzureEventHubsResourcePromise { + return new AzureEventHubsResourcePromise(this._withHealthCheckInternal(key)); + } + + /** @internal */ + private async _withHttpHealthCheckInternal(path?: string, statusCode?: number, endpointName?: string): Promise { + const rpcArgs: Record = { builder: this._handle }; + if (path !== undefined) rpcArgs.path = path; + if (statusCode !== undefined) rpcArgs.statusCode = statusCode; + if (endpointName !== undefined) rpcArgs.endpointName = endpointName; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withHttpHealthCheck', + rpcArgs + ); + return new AzureEventHubsResource(result, this._client); + } + + /** Adds an HTTP health check */ + withHttpHealthCheck(options?: WithHttpHealthCheckOptions): AzureEventHubsResourcePromise { + const path = options?.path; + const statusCode = options?.statusCode; + const endpointName = options?.endpointName; + return new AzureEventHubsResourcePromise(this._withHttpHealthCheckInternal(path, statusCode, endpointName)); + } + + /** @internal */ + private async _withCommandInternal(name: string, displayName: string, executeCommand: (arg: ExecuteCommandContext) => Promise, commandOptions?: CommandOptions): Promise { + const executeCommandId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as ExecuteCommandContextHandle; + const arg = new ExecuteCommandContext(argHandle, this._client); + return await executeCommand(arg); + }); + const rpcArgs: Record = { builder: this._handle, name, displayName, executeCommand: executeCommandId }; + if (commandOptions !== undefined) rpcArgs.commandOptions = commandOptions; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withCommand', + rpcArgs + ); + return new AzureEventHubsResource(result, this._client); + } + + /** Adds a resource command */ + withCommand(name: string, displayName: string, executeCommand: (arg: ExecuteCommandContext) => Promise, options?: WithCommandOptions): AzureEventHubsResourcePromise { + const commandOptions = options?.commandOptions; + return new AzureEventHubsResourcePromise(this._withCommandInternal(name, displayName, executeCommand, commandOptions)); + } + + /** @internal */ + private async _withParentRelationshipInternal(parent: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, parent }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withParentRelationship', + rpcArgs + ); + return new AzureEventHubsResource(result, this._client); + } + + /** Sets the parent relationship */ + withParentRelationship(parent: ResourceBuilderBase): AzureEventHubsResourcePromise { + return new AzureEventHubsResourcePromise(this._withParentRelationshipInternal(parent)); + } + + /** @internal */ + private async _withChildRelationshipInternal(child: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, child }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withChildRelationship', + rpcArgs + ); + return new AzureEventHubsResource(result, this._client); + } + + /** Sets a child relationship */ + withChildRelationship(child: ResourceBuilderBase): AzureEventHubsResourcePromise { + return new AzureEventHubsResourcePromise(this._withChildRelationshipInternal(child)); + } + + /** @internal */ + private async _withIconNameInternal(iconName: string, iconVariant?: IconVariant): Promise { + const rpcArgs: Record = { builder: this._handle, iconName }; + if (iconVariant !== undefined) rpcArgs.iconVariant = iconVariant; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withIconName', + rpcArgs + ); + return new AzureEventHubsResource(result, this._client); + } + + /** Sets the icon for the resource */ + withIconName(iconName: string, options?: WithIconNameOptions): AzureEventHubsResourcePromise { + const iconVariant = options?.iconVariant; + return new AzureEventHubsResourcePromise(this._withIconNameInternal(iconName, iconVariant)); + } + + /** @internal */ + private async _withHttpProbeInternal(probeType: ProbeType, path?: string, initialDelaySeconds?: number, periodSeconds?: number, timeoutSeconds?: number, failureThreshold?: number, successThreshold?: number, endpointName?: string): Promise { + const rpcArgs: Record = { builder: this._handle, probeType }; + if (path !== undefined) rpcArgs.path = path; + if (initialDelaySeconds !== undefined) rpcArgs.initialDelaySeconds = initialDelaySeconds; + if (periodSeconds !== undefined) rpcArgs.periodSeconds = periodSeconds; + if (timeoutSeconds !== undefined) rpcArgs.timeoutSeconds = timeoutSeconds; + if (failureThreshold !== undefined) rpcArgs.failureThreshold = failureThreshold; + if (successThreshold !== undefined) rpcArgs.successThreshold = successThreshold; + if (endpointName !== undefined) rpcArgs.endpointName = endpointName; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withHttpProbe', + rpcArgs + ); + return new AzureEventHubsResource(result, this._client); + } + + /** Adds an HTTP health probe to the resource */ + withHttpProbe(probeType: ProbeType, options?: WithHttpProbeOptions): AzureEventHubsResourcePromise { + const path = options?.path; + const initialDelaySeconds = options?.initialDelaySeconds; + const periodSeconds = options?.periodSeconds; + const timeoutSeconds = options?.timeoutSeconds; + const failureThreshold = options?.failureThreshold; + const successThreshold = options?.successThreshold; + const endpointName = options?.endpointName; + return new AzureEventHubsResourcePromise(this._withHttpProbeInternal(probeType, path, initialDelaySeconds, periodSeconds, timeoutSeconds, failureThreshold, successThreshold, endpointName)); + } + + /** @internal */ + private async _excludeFromMcpInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/excludeFromMcp', + rpcArgs + ); + return new AzureEventHubsResource(result, this._client); + } + + /** Excludes the resource from MCP server exposure */ + excludeFromMcp(): AzureEventHubsResourcePromise { + return new AzureEventHubsResourcePromise(this._excludeFromMcpInternal()); + } + + /** @internal */ + private async _withPipelineStepFactoryInternal(stepName: string, callback: (arg: PipelineStepContext) => Promise, dependsOn?: string[], requiredBy?: string[], tags?: string[], description?: string): Promise { + const callbackId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as PipelineStepContextHandle; + const arg = new PipelineStepContext(argHandle, this._client); + await callback(arg); + }); + const rpcArgs: Record = { builder: this._handle, stepName, callback: callbackId }; + if (dependsOn !== undefined) rpcArgs.dependsOn = dependsOn; + if (requiredBy !== undefined) rpcArgs.requiredBy = requiredBy; + if (tags !== undefined) rpcArgs.tags = tags; + if (description !== undefined) rpcArgs.description = description; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withPipelineStepFactory', + rpcArgs + ); + return new AzureEventHubsResource(result, this._client); + } + + /** Adds a pipeline step to the resource */ + withPipelineStepFactory(stepName: string, callback: (arg: PipelineStepContext) => Promise, options?: WithPipelineStepFactoryOptions): AzureEventHubsResourcePromise { + const dependsOn = options?.dependsOn; + const requiredBy = options?.requiredBy; + const tags = options?.tags; + const description = options?.description; + return new AzureEventHubsResourcePromise(this._withPipelineStepFactoryInternal(stepName, callback, dependsOn, requiredBy, tags, description)); + } + + /** @internal */ + private async _withPipelineConfigurationAsyncInternal(callback: (arg: PipelineConfigurationContext) => Promise): Promise { + const callbackId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as PipelineConfigurationContextHandle; + const arg = new PipelineConfigurationContext(argHandle, this._client); + await callback(arg); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withPipelineConfigurationAsync', + rpcArgs + ); + return new AzureEventHubsResource(result, this._client); + } + + /** Configures pipeline step dependencies via an async callback */ + withPipelineConfigurationAsync(callback: (arg: PipelineConfigurationContext) => Promise): AzureEventHubsResourcePromise { + return new AzureEventHubsResourcePromise(this._withPipelineConfigurationAsyncInternal(callback)); + } + + /** @internal */ + private async _withPipelineConfigurationInternal(callback: (obj: PipelineConfigurationContext) => Promise): Promise { + const callbackId = registerCallback(async (objData: unknown) => { + const objHandle = wrapIfHandle(objData) as PipelineConfigurationContextHandle; + const obj = new PipelineConfigurationContext(objHandle, this._client); + await callback(obj); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withPipelineConfiguration', + rpcArgs + ); + return new AzureEventHubsResource(result, this._client); + } + + /** Configures pipeline step dependencies via a callback */ + withPipelineConfiguration(callback: (obj: PipelineConfigurationContext) => Promise): AzureEventHubsResourcePromise { + return new AzureEventHubsResourcePromise(this._withPipelineConfigurationInternal(callback)); + } + + /** Gets the resource name */ + async getResourceName(): Promise { + const rpcArgs: Record = { resource: this._handle }; + return await this._client.invokeCapability( + 'Aspire.Hosting/getResourceName', + rpcArgs + ); + } + + /** @internal */ + private async _withStorageRoleAssignmentsInternal(target: AzureStorageResource, roles: AzureStorageRole[]): Promise { + const rpcArgs: Record = { builder: this._handle, target, roles }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure.Storage/withStorageRoleAssignments', + rpcArgs + ); + return new AzureEventHubsResource(result, this._client); + } + + /** Assigns Azure Storage roles to a resource */ + withStorageRoleAssignments(target: AzureStorageResource, roles: AzureStorageRole[]): AzureEventHubsResourcePromise { + return new AzureEventHubsResourcePromise(this._withStorageRoleAssignmentsInternal(target, roles)); + } + + /** @internal */ + private async _addHubInternal(name: string, hubName?: string): Promise { + const rpcArgs: Record = { builder: this._handle, name }; + if (hubName !== undefined) rpcArgs.hubName = hubName; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure.EventHubs/addHub', + rpcArgs + ); + return new AzureEventHubResource(result, this._client); + } + + /** Adds an Azure Event Hub resource */ + addHub(name: string, options?: AddHubOptions): AzureEventHubResourcePromise { + const hubName = options?.hubName; + return new AzureEventHubResourcePromise(this._addHubInternal(name, hubName)); + } + + /** @internal */ + private async _runAsEmulatorInternal(configureContainer?: (obj: AzureEventHubsEmulatorResource) => Promise): Promise { + const configureContainerId = configureContainer ? registerCallback(async (objData: unknown) => { + const objHandle = wrapIfHandle(objData) as AzureEventHubsEmulatorResourceHandle; + const obj = new AzureEventHubsEmulatorResource(objHandle, this._client); + await configureContainer(obj); + }) : undefined; + const rpcArgs: Record = { builder: this._handle }; + if (configureContainer !== undefined) rpcArgs.configureContainer = configureContainerId; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure.EventHubs/runAsEmulator', + rpcArgs + ); + return new AzureEventHubsResource(result, this._client); + } + + /** Configures the Azure Event Hubs resource to run with the local emulator */ + runAsEmulator(options?: RunAsEmulatorOptions): AzureEventHubsResourcePromise { + const configureContainer = options?.configureContainer; + return new AzureEventHubsResourcePromise(this._runAsEmulatorInternal(configureContainer)); + } + + /** @internal */ + private async _withEventHubsRoleAssignmentsInternal(target: AzureEventHubsResource, roles: AzureEventHubsRole[]): Promise { + const rpcArgs: Record = { builder: this._handle, target, roles }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure.EventHubs/withEventHubsRoleAssignments', + rpcArgs + ); + return new AzureEventHubsResource(result, this._client); + } + + /** Assigns Event Hubs roles to a resource */ + withEventHubsRoleAssignments(target: AzureEventHubsResource, roles: AzureEventHubsRole[]): AzureEventHubsResourcePromise { + return new AzureEventHubsResourcePromise(this._withEventHubsRoleAssignmentsInternal(target, roles)); + } + + /** Gets an output reference from an Azure Bicep template resource */ + async getOutput(name: string): Promise { + const rpcArgs: Record = { builder: this._handle, name }; + return await this._client.invokeCapability( + 'Aspire.Hosting.Azure/getOutput', + rpcArgs + ); + } + + /** @internal */ + private async _withParameterInternal(name: string): Promise { + const rpcArgs: Record = { builder: this._handle, name }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure/withParameter', + rpcArgs + ); + return new AzureEventHubsResource(result, this._client); + } + + /** Adds a Bicep parameter without a value */ + withParameter(name: string): AzureEventHubsResourcePromise { + return new AzureEventHubsResourcePromise(this._withParameterInternal(name)); + } + + /** @internal */ + private async _withParameterStringValueInternal(name: string, value: string): Promise { + const rpcArgs: Record = { builder: this._handle, name, value }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure/withParameterStringValue', + rpcArgs + ); + return new AzureEventHubsResource(result, this._client); + } + + /** Adds a Bicep parameter with a string value */ + withParameterStringValue(name: string, value: string): AzureEventHubsResourcePromise { + return new AzureEventHubsResourcePromise(this._withParameterStringValueInternal(name, value)); + } + + /** @internal */ + private async _withParameterStringValuesInternal(name: string, value: string[]): Promise { + const rpcArgs: Record = { builder: this._handle, name, value }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure/withParameterStringValues', + rpcArgs + ); + return new AzureEventHubsResource(result, this._client); + } + + /** Adds a Bicep parameter with a string list value */ + withParameterStringValues(name: string, value: string[]): AzureEventHubsResourcePromise { + return new AzureEventHubsResourcePromise(this._withParameterStringValuesInternal(name, value)); + } + + /** @internal */ + private async _withParameterFromParameterInternal(name: string, value: ParameterResource): Promise { + const rpcArgs: Record = { builder: this._handle, name, value }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure/withParameterFromParameter', + rpcArgs + ); + return new AzureEventHubsResource(result, this._client); + } + + /** Adds a Bicep parameter from a parameter resource builder */ + withParameterFromParameter(name: string, value: ParameterResource): AzureEventHubsResourcePromise { + return new AzureEventHubsResourcePromise(this._withParameterFromParameterInternal(name, value)); + } + + /** @internal */ + private async _withParameterFromConnectionStringInternal(name: string, value: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, name, value }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure/withParameterFromConnectionString', + rpcArgs + ); + return new AzureEventHubsResource(result, this._client); + } + + /** Adds a Bicep parameter from a connection string resource builder */ + withParameterFromConnectionString(name: string, value: ResourceBuilderBase): AzureEventHubsResourcePromise { + return new AzureEventHubsResourcePromise(this._withParameterFromConnectionStringInternal(name, value)); + } + + /** @internal */ + private async _withParameterFromOutputInternal(name: string, value: BicepOutputReference): Promise { + const rpcArgs: Record = { builder: this._handle, name, value }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure/withParameterFromOutput', + rpcArgs + ); + return new AzureEventHubsResource(result, this._client); + } + + /** Adds a Bicep parameter from another Bicep output reference */ + withParameterFromOutput(name: string, value: BicepOutputReference): AzureEventHubsResourcePromise { + return new AzureEventHubsResourcePromise(this._withParameterFromOutputInternal(name, value)); + } + + /** @internal */ + private async _withParameterFromReferenceExpressionInternal(name: string, value: ReferenceExpression): Promise { + const rpcArgs: Record = { builder: this._handle, name, value }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure/withParameterFromReferenceExpression', + rpcArgs + ); + return new AzureEventHubsResource(result, this._client); + } + + /** Adds a Bicep parameter from a reference expression */ + withParameterFromReferenceExpression(name: string, value: ReferenceExpression): AzureEventHubsResourcePromise { + return new AzureEventHubsResourcePromise(this._withParameterFromReferenceExpressionInternal(name, value)); + } + + /** @internal */ + private async _withParameterFromEndpointInternal(name: string, value: EndpointReference): Promise { + const rpcArgs: Record = { builder: this._handle, name, value }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure/withParameterFromEndpoint', + rpcArgs + ); + return new AzureEventHubsResource(result, this._client); + } + + /** Adds a Bicep parameter from an endpoint reference */ + withParameterFromEndpoint(name: string, value: EndpointReference): AzureEventHubsResourcePromise { + return new AzureEventHubsResourcePromise(this._withParameterFromEndpointInternal(name, value)); + } + + /** @internal */ + private async _configureInfrastructureInternal(configure: (obj: AzureResourceInfrastructure) => Promise): Promise { + const configureId = registerCallback(async (objData: unknown) => { + const objHandle = wrapIfHandle(objData) as AzureResourceInfrastructureHandle; + const obj = new AzureResourceInfrastructure(objHandle, this._client); + await configure(obj); + }); + const rpcArgs: Record = { builder: this._handle, configure: configureId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure/configureInfrastructure', + rpcArgs + ); + return new AzureEventHubsResource(result, this._client); + } + + /** Configures the Azure provisioning infrastructure callback */ + configureInfrastructure(configure: (obj: AzureResourceInfrastructure) => Promise): AzureEventHubsResourcePromise { + return new AzureEventHubsResourcePromise(this._configureInfrastructureInternal(configure)); + } + + /** @internal */ + private async _publishAsConnectionStringInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure/publishAsConnectionString', + rpcArgs + ); + return new AzureEventHubsResource(result, this._client); + } + + /** Publishes an Azure resource to the manifest as a connection string */ + publishAsConnectionString(): AzureEventHubsResourcePromise { + return new AzureEventHubsResourcePromise(this._publishAsConnectionStringInternal()); + } + + /** Gets the normalized Bicep identifier for an Azure resource */ + async getBicepIdentifier(): Promise { + const rpcArgs: Record = { resource: this._handle }; + return await this._client.invokeCapability( + 'Aspire.Hosting.Azure/getBicepIdentifier', + rpcArgs + ); + } + + /** @internal */ + private async _clearDefaultRoleAssignmentsInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure/clearDefaultRoleAssignments', + rpcArgs + ); + return new AzureEventHubsResource(result, this._client); + } + + /** Clears the default Azure role assignments from a resource */ + clearDefaultRoleAssignments(): AzureEventHubsResourcePromise { + return new AzureEventHubsResourcePromise(this._clearDefaultRoleAssignmentsInternal()); + } + + /** Determines whether a resource is marked as existing */ + async isExisting(): Promise { + const rpcArgs: Record = { resource: this._handle }; + return await this._client.invokeCapability( + 'Aspire.Hosting.Azure/isExisting', + rpcArgs + ); + } + + /** @internal */ + private async _runAsExistingFromParametersInternal(nameParameter: ParameterResource, resourceGroupParameter: ParameterResource): Promise { + const rpcArgs: Record = { builder: this._handle, nameParameter, resourceGroupParameter }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure/runAsExistingFromParameters', + rpcArgs + ); + return new AzureEventHubsResource(result, this._client); + } + + /** Marks an Azure resource as existing in run mode by using parameter resources */ + runAsExistingFromParameters(nameParameter: ParameterResource, resourceGroupParameter: ParameterResource): AzureEventHubsResourcePromise { + return new AzureEventHubsResourcePromise(this._runAsExistingFromParametersInternal(nameParameter, resourceGroupParameter)); + } + + /** @internal */ + private async _runAsExistingInternal(name: string, resourceGroup: string): Promise { + const rpcArgs: Record = { builder: this._handle, name, resourceGroup }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure/runAsExisting', + rpcArgs + ); + return new AzureEventHubsResource(result, this._client); + } + + /** Marks an Azure resource as existing in run mode */ + runAsExisting(name: string, resourceGroup: string): AzureEventHubsResourcePromise { + return new AzureEventHubsResourcePromise(this._runAsExistingInternal(name, resourceGroup)); + } + + /** @internal */ + private async _publishAsExistingFromParametersInternal(nameParameter: ParameterResource, resourceGroupParameter: ParameterResource): Promise { + const rpcArgs: Record = { builder: this._handle, nameParameter, resourceGroupParameter }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure/publishAsExistingFromParameters', + rpcArgs + ); + return new AzureEventHubsResource(result, this._client); + } + + /** Marks an Azure resource as existing in publish mode by using parameter resources */ + publishAsExistingFromParameters(nameParameter: ParameterResource, resourceGroupParameter: ParameterResource): AzureEventHubsResourcePromise { + return new AzureEventHubsResourcePromise(this._publishAsExistingFromParametersInternal(nameParameter, resourceGroupParameter)); + } + + /** @internal */ + private async _publishAsExistingInternal(name: string, resourceGroup: string): Promise { + const rpcArgs: Record = { builder: this._handle, name, resourceGroup }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure/publishAsExisting', + rpcArgs + ); + return new AzureEventHubsResource(result, this._client); + } + + /** Marks an Azure resource as existing in publish mode */ + publishAsExisting(name: string, resourceGroup: string): AzureEventHubsResourcePromise { + return new AzureEventHubsResourcePromise(this._publishAsExistingInternal(name, resourceGroup)); + } + + /** @internal */ + private async _asExistingInternal(nameParameter: ParameterResource, resourceGroupParameter: ParameterResource): Promise { + const rpcArgs: Record = { builder: this._handle, nameParameter, resourceGroupParameter }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure/asExistingFromParameters', + rpcArgs + ); + return new AzureEventHubsResource(result, this._client); + } + + /** Marks an Azure resource as existing in both run and publish modes by using parameter resources */ + asExisting(nameParameter: ParameterResource, resourceGroupParameter: ParameterResource): AzureEventHubsResourcePromise { + return new AzureEventHubsResourcePromise(this._asExistingInternal(nameParameter, resourceGroupParameter)); + } + +} + +/** + * Thenable wrapper for AzureEventHubsResource that enables fluent chaining. + * @example + * await builder.addSomething().withX().withY(); + */ +export class AzureEventHubsResourcePromise implements PromiseLike { + constructor(private _promise: Promise) {} + + then( + onfulfilled?: ((value: AzureEventHubsResource) => TResult1 | PromiseLike) | null, + onrejected?: ((reason: unknown) => TResult2 | PromiseLike) | null + ): PromiseLike { + return this._promise.then(onfulfilled, onrejected); + } + + /** Configures a resource to use a container registry */ + withContainerRegistry(registry: ResourceBuilderBase): AzureEventHubsResourcePromise { + return new AzureEventHubsResourcePromise(this._promise.then(obj => obj.withContainerRegistry(registry))); + } + + /** Sets the base image for a Dockerfile build */ + withDockerfileBaseImage(options?: WithDockerfileBaseImageOptions): AzureEventHubsResourcePromise { + return new AzureEventHubsResourcePromise(this._promise.then(obj => obj.withDockerfileBaseImage(options))); + } + + /** Configures an MCP server endpoint on the resource */ + withMcpServer(options?: WithMcpServerOptions): AzureEventHubsResourcePromise { + return new AzureEventHubsResourcePromise(this._promise.then(obj => obj.withMcpServer(options))); + } + + /** Adds a required command dependency */ + withRequiredCommand(command: string, options?: WithRequiredCommandOptions): AzureEventHubsResourcePromise { + return new AzureEventHubsResourcePromise(this._promise.then(obj => obj.withRequiredCommand(command, options))); + } + + /** Adds a connection property with a reference expression */ + withConnectionProperty(name: string, value: ReferenceExpression): AzureEventHubsResourcePromise { + return new AzureEventHubsResourcePromise(this._promise.then(obj => obj.withConnectionProperty(name, value))); + } + + /** Adds a connection property with a string value */ + withConnectionPropertyValue(name: string, value: string): AzureEventHubsResourcePromise { + return new AzureEventHubsResourcePromise(this._promise.then(obj => obj.withConnectionPropertyValue(name, value))); + } + + /** Adds a network endpoint */ + withEndpoint(options?: WithEndpointOptions): AzureEventHubsResourcePromise { + return new AzureEventHubsResourcePromise(this._promise.then(obj => obj.withEndpoint(options))); + } + + /** Adds an HTTP endpoint */ + withHttpEndpoint(options?: WithHttpEndpointOptions): AzureEventHubsResourcePromise { + return new AzureEventHubsResourcePromise(this._promise.then(obj => obj.withHttpEndpoint(options))); + } + + /** Adds an HTTPS endpoint */ + withHttpsEndpoint(options?: WithHttpsEndpointOptions): AzureEventHubsResourcePromise { + return new AzureEventHubsResourcePromise(this._promise.then(obj => obj.withHttpsEndpoint(options))); + } + + /** Makes HTTP endpoints externally accessible */ + withExternalHttpEndpoints(): AzureEventHubsResourcePromise { + return new AzureEventHubsResourcePromise(this._promise.then(obj => obj.withExternalHttpEndpoints())); + } + + /** Gets an endpoint reference */ + getEndpoint(name: string): Promise { + return this._promise.then(obj => obj.getEndpoint(name)); + } + + /** Configures resource for HTTP/2 */ + asHttp2Service(): AzureEventHubsResourcePromise { + return new AzureEventHubsResourcePromise(this._promise.then(obj => obj.asHttp2Service())); + } + + /** Customizes displayed URLs via callback */ + withUrlsCallback(callback: (obj: ResourceUrlsCallbackContext) => Promise): AzureEventHubsResourcePromise { + return new AzureEventHubsResourcePromise(this._promise.then(obj => obj.withUrlsCallback(callback))); + } + + /** Customizes displayed URLs via async callback */ + withUrlsCallbackAsync(callback: (arg: ResourceUrlsCallbackContext) => Promise): AzureEventHubsResourcePromise { + return new AzureEventHubsResourcePromise(this._promise.then(obj => obj.withUrlsCallbackAsync(callback))); + } + + /** Adds or modifies displayed URLs */ + withUrl(url: string, options?: WithUrlOptions): AzureEventHubsResourcePromise { + return new AzureEventHubsResourcePromise(this._promise.then(obj => obj.withUrl(url, options))); + } + + /** Adds a URL using a reference expression */ + withUrlExpression(url: ReferenceExpression, options?: WithUrlExpressionOptions): AzureEventHubsResourcePromise { + return new AzureEventHubsResourcePromise(this._promise.then(obj => obj.withUrlExpression(url, options))); + } + + /** Customizes the URL for a specific endpoint via callback */ + withUrlForEndpoint(endpointName: string, callback: (obj: ResourceUrlAnnotation) => Promise): AzureEventHubsResourcePromise { + return new AzureEventHubsResourcePromise(this._promise.then(obj => obj.withUrlForEndpoint(endpointName, callback))); + } + + /** Adds a URL for a specific endpoint via factory callback */ + withUrlForEndpointFactory(endpointName: string, callback: (arg: EndpointReference) => Promise): AzureEventHubsResourcePromise { + return new AzureEventHubsResourcePromise(this._promise.then(obj => obj.withUrlForEndpointFactory(endpointName, callback))); + } + + /** Excludes the resource from the deployment manifest */ + excludeFromManifest(): AzureEventHubsResourcePromise { + return new AzureEventHubsResourcePromise(this._promise.then(obj => obj.excludeFromManifest())); + } + + /** Prevents resource from starting automatically */ + withExplicitStart(): AzureEventHubsResourcePromise { + return new AzureEventHubsResourcePromise(this._promise.then(obj => obj.withExplicitStart())); + } + + /** Adds a health check by key */ + withHealthCheck(key: string): AzureEventHubsResourcePromise { + return new AzureEventHubsResourcePromise(this._promise.then(obj => obj.withHealthCheck(key))); + } + + /** Adds an HTTP health check */ + withHttpHealthCheck(options?: WithHttpHealthCheckOptions): AzureEventHubsResourcePromise { + return new AzureEventHubsResourcePromise(this._promise.then(obj => obj.withHttpHealthCheck(options))); + } + + /** Adds a resource command */ + withCommand(name: string, displayName: string, executeCommand: (arg: ExecuteCommandContext) => Promise, options?: WithCommandOptions): AzureEventHubsResourcePromise { + return new AzureEventHubsResourcePromise(this._promise.then(obj => obj.withCommand(name, displayName, executeCommand, options))); + } + + /** Sets the parent relationship */ + withParentRelationship(parent: ResourceBuilderBase): AzureEventHubsResourcePromise { + return new AzureEventHubsResourcePromise(this._promise.then(obj => obj.withParentRelationship(parent))); + } + + /** Sets a child relationship */ + withChildRelationship(child: ResourceBuilderBase): AzureEventHubsResourcePromise { + return new AzureEventHubsResourcePromise(this._promise.then(obj => obj.withChildRelationship(child))); + } + + /** Sets the icon for the resource */ + withIconName(iconName: string, options?: WithIconNameOptions): AzureEventHubsResourcePromise { + return new AzureEventHubsResourcePromise(this._promise.then(obj => obj.withIconName(iconName, options))); + } + + /** Adds an HTTP health probe to the resource */ + withHttpProbe(probeType: ProbeType, options?: WithHttpProbeOptions): AzureEventHubsResourcePromise { + return new AzureEventHubsResourcePromise(this._promise.then(obj => obj.withHttpProbe(probeType, options))); + } + + /** Excludes the resource from MCP server exposure */ + excludeFromMcp(): AzureEventHubsResourcePromise { + return new AzureEventHubsResourcePromise(this._promise.then(obj => obj.excludeFromMcp())); + } + + /** Adds a pipeline step to the resource */ + withPipelineStepFactory(stepName: string, callback: (arg: PipelineStepContext) => Promise, options?: WithPipelineStepFactoryOptions): AzureEventHubsResourcePromise { + return new AzureEventHubsResourcePromise(this._promise.then(obj => obj.withPipelineStepFactory(stepName, callback, options))); + } + + /** Configures pipeline step dependencies via an async callback */ + withPipelineConfigurationAsync(callback: (arg: PipelineConfigurationContext) => Promise): AzureEventHubsResourcePromise { + return new AzureEventHubsResourcePromise(this._promise.then(obj => obj.withPipelineConfigurationAsync(callback))); + } + + /** Configures pipeline step dependencies via a callback */ + withPipelineConfiguration(callback: (obj: PipelineConfigurationContext) => Promise): AzureEventHubsResourcePromise { + return new AzureEventHubsResourcePromise(this._promise.then(obj => obj.withPipelineConfiguration(callback))); + } + + /** Gets the resource name */ + getResourceName(): Promise { + return this._promise.then(obj => obj.getResourceName()); + } + + /** Assigns Azure Storage roles to a resource */ + withStorageRoleAssignments(target: AzureStorageResource, roles: AzureStorageRole[]): AzureEventHubsResourcePromise { + return new AzureEventHubsResourcePromise(this._promise.then(obj => obj.withStorageRoleAssignments(target, roles))); + } + + /** Adds an Azure Event Hub resource */ + addHub(name: string, options?: AddHubOptions): AzureEventHubResourcePromise { + return new AzureEventHubResourcePromise(this._promise.then(obj => obj.addHub(name, options))); + } + + /** Configures the Azure Event Hubs resource to run with the local emulator */ + runAsEmulator(options?: RunAsEmulatorOptions): AzureEventHubsResourcePromise { + return new AzureEventHubsResourcePromise(this._promise.then(obj => obj.runAsEmulator(options))); + } + + /** Assigns Event Hubs roles to a resource */ + withEventHubsRoleAssignments(target: AzureEventHubsResource, roles: AzureEventHubsRole[]): AzureEventHubsResourcePromise { + return new AzureEventHubsResourcePromise(this._promise.then(obj => obj.withEventHubsRoleAssignments(target, roles))); + } + + /** Gets an output reference from an Azure Bicep template resource */ + getOutput(name: string): Promise { + return this._promise.then(obj => obj.getOutput(name)); + } + + /** Adds a Bicep parameter without a value */ + withParameter(name: string): AzureEventHubsResourcePromise { + return new AzureEventHubsResourcePromise(this._promise.then(obj => obj.withParameter(name))); + } + + /** Adds a Bicep parameter with a string value */ + withParameterStringValue(name: string, value: string): AzureEventHubsResourcePromise { + return new AzureEventHubsResourcePromise(this._promise.then(obj => obj.withParameterStringValue(name, value))); + } + + /** Adds a Bicep parameter with a string list value */ + withParameterStringValues(name: string, value: string[]): AzureEventHubsResourcePromise { + return new AzureEventHubsResourcePromise(this._promise.then(obj => obj.withParameterStringValues(name, value))); + } + + /** Adds a Bicep parameter from a parameter resource builder */ + withParameterFromParameter(name: string, value: ParameterResource): AzureEventHubsResourcePromise { + return new AzureEventHubsResourcePromise(this._promise.then(obj => obj.withParameterFromParameter(name, value))); + } + + /** Adds a Bicep parameter from a connection string resource builder */ + withParameterFromConnectionString(name: string, value: ResourceBuilderBase): AzureEventHubsResourcePromise { + return new AzureEventHubsResourcePromise(this._promise.then(obj => obj.withParameterFromConnectionString(name, value))); + } + + /** Adds a Bicep parameter from another Bicep output reference */ + withParameterFromOutput(name: string, value: BicepOutputReference): AzureEventHubsResourcePromise { + return new AzureEventHubsResourcePromise(this._promise.then(obj => obj.withParameterFromOutput(name, value))); + } + + /** Adds a Bicep parameter from a reference expression */ + withParameterFromReferenceExpression(name: string, value: ReferenceExpression): AzureEventHubsResourcePromise { + return new AzureEventHubsResourcePromise(this._promise.then(obj => obj.withParameterFromReferenceExpression(name, value))); + } + + /** Adds a Bicep parameter from an endpoint reference */ + withParameterFromEndpoint(name: string, value: EndpointReference): AzureEventHubsResourcePromise { + return new AzureEventHubsResourcePromise(this._promise.then(obj => obj.withParameterFromEndpoint(name, value))); + } + + /** Configures the Azure provisioning infrastructure callback */ + configureInfrastructure(configure: (obj: AzureResourceInfrastructure) => Promise): AzureEventHubsResourcePromise { + return new AzureEventHubsResourcePromise(this._promise.then(obj => obj.configureInfrastructure(configure))); + } + + /** Publishes an Azure resource to the manifest as a connection string */ + publishAsConnectionString(): AzureEventHubsResourcePromise { + return new AzureEventHubsResourcePromise(this._promise.then(obj => obj.publishAsConnectionString())); + } + + /** Gets the normalized Bicep identifier for an Azure resource */ + getBicepIdentifier(): Promise { + return this._promise.then(obj => obj.getBicepIdentifier()); + } + + /** Clears the default Azure role assignments from a resource */ + clearDefaultRoleAssignments(): AzureEventHubsResourcePromise { + return new AzureEventHubsResourcePromise(this._promise.then(obj => obj.clearDefaultRoleAssignments())); + } + + /** Determines whether a resource is marked as existing */ + isExisting(): Promise { + return this._promise.then(obj => obj.isExisting()); + } + + /** Marks an Azure resource as existing in run mode by using parameter resources */ + runAsExistingFromParameters(nameParameter: ParameterResource, resourceGroupParameter: ParameterResource): AzureEventHubsResourcePromise { + return new AzureEventHubsResourcePromise(this._promise.then(obj => obj.runAsExistingFromParameters(nameParameter, resourceGroupParameter))); + } + + /** Marks an Azure resource as existing in run mode */ + runAsExisting(name: string, resourceGroup: string): AzureEventHubsResourcePromise { + return new AzureEventHubsResourcePromise(this._promise.then(obj => obj.runAsExisting(name, resourceGroup))); + } + + /** Marks an Azure resource as existing in publish mode by using parameter resources */ + publishAsExistingFromParameters(nameParameter: ParameterResource, resourceGroupParameter: ParameterResource): AzureEventHubsResourcePromise { + return new AzureEventHubsResourcePromise(this._promise.then(obj => obj.publishAsExistingFromParameters(nameParameter, resourceGroupParameter))); + } + + /** Marks an Azure resource as existing in publish mode */ + publishAsExisting(name: string, resourceGroup: string): AzureEventHubsResourcePromise { + return new AzureEventHubsResourcePromise(this._promise.then(obj => obj.publishAsExisting(name, resourceGroup))); + } + + /** Marks an Azure resource as existing in both run and publish modes by using parameter resources */ + asExisting(nameParameter: ParameterResource, resourceGroupParameter: ParameterResource): AzureEventHubsResourcePromise { + return new AzureEventHubsResourcePromise(this._promise.then(obj => obj.asExisting(nameParameter, resourceGroupParameter))); + } + +} + +// ============================================================================ +// AzureProvisioningResource +// ============================================================================ + +export class AzureProvisioningResource extends ResourceBuilderBase { + constructor(handle: AzureProvisioningResourceHandle, client: AspireClientRpc) { + super(handle, client); + } + + /** @internal */ + private async _withContainerRegistryInternal(registry: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, registry }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withContainerRegistry', + rpcArgs + ); + return new AzureProvisioningResource(result, this._client); + } + + /** Configures a resource to use a container registry */ + withContainerRegistry(registry: ResourceBuilderBase): AzureProvisioningResourcePromise { + return new AzureProvisioningResourcePromise(this._withContainerRegistryInternal(registry)); + } + + /** @internal */ + private async _withDockerfileBaseImageInternal(buildImage?: string, runtimeImage?: string): Promise { + const rpcArgs: Record = { builder: this._handle }; + if (buildImage !== undefined) rpcArgs.buildImage = buildImage; + if (runtimeImage !== undefined) rpcArgs.runtimeImage = runtimeImage; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withDockerfileBaseImage', + rpcArgs + ); + return new AzureProvisioningResource(result, this._client); + } + + /** Sets the base image for a Dockerfile build */ + withDockerfileBaseImage(options?: WithDockerfileBaseImageOptions): AzureProvisioningResourcePromise { + const buildImage = options?.buildImage; + const runtimeImage = options?.runtimeImage; + return new AzureProvisioningResourcePromise(this._withDockerfileBaseImageInternal(buildImage, runtimeImage)); + } + + /** @internal */ + private async _withRequiredCommandInternal(command: string, helpLink?: string): Promise { + const rpcArgs: Record = { builder: this._handle, command }; + if (helpLink !== undefined) rpcArgs.helpLink = helpLink; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withRequiredCommand', + rpcArgs + ); + return new AzureProvisioningResource(result, this._client); + } + + /** Adds a required command dependency */ + withRequiredCommand(command: string, options?: WithRequiredCommandOptions): AzureProvisioningResourcePromise { + const helpLink = options?.helpLink; + return new AzureProvisioningResourcePromise(this._withRequiredCommandInternal(command, helpLink)); + } + + /** @internal */ + private async _withUrlsCallbackInternal(callback: (obj: ResourceUrlsCallbackContext) => Promise): Promise { + const callbackId = registerCallback(async (objData: unknown) => { + const objHandle = wrapIfHandle(objData) as ResourceUrlsCallbackContextHandle; + const obj = new ResourceUrlsCallbackContext(objHandle, this._client); + await callback(obj); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrlsCallback', + rpcArgs + ); + return new AzureProvisioningResource(result, this._client); + } + + /** Customizes displayed URLs via callback */ + withUrlsCallback(callback: (obj: ResourceUrlsCallbackContext) => Promise): AzureProvisioningResourcePromise { + return new AzureProvisioningResourcePromise(this._withUrlsCallbackInternal(callback)); + } + + /** @internal */ + private async _withUrlsCallbackAsyncInternal(callback: (arg: ResourceUrlsCallbackContext) => Promise): Promise { + const callbackId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as ResourceUrlsCallbackContextHandle; + const arg = new ResourceUrlsCallbackContext(argHandle, this._client); + await callback(arg); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrlsCallbackAsync', + rpcArgs + ); + return new AzureProvisioningResource(result, this._client); + } + + /** Customizes displayed URLs via async callback */ + withUrlsCallbackAsync(callback: (arg: ResourceUrlsCallbackContext) => Promise): AzureProvisioningResourcePromise { + return new AzureProvisioningResourcePromise(this._withUrlsCallbackAsyncInternal(callback)); + } + + /** @internal */ + private async _withUrlInternal(url: string, displayText?: string): Promise { + const rpcArgs: Record = { builder: this._handle, url }; + if (displayText !== undefined) rpcArgs.displayText = displayText; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrl', + rpcArgs + ); + return new AzureProvisioningResource(result, this._client); + } + + /** Adds or modifies displayed URLs */ + withUrl(url: string, options?: WithUrlOptions): AzureProvisioningResourcePromise { + const displayText = options?.displayText; + return new AzureProvisioningResourcePromise(this._withUrlInternal(url, displayText)); + } + + /** @internal */ + private async _withUrlExpressionInternal(url: ReferenceExpression, displayText?: string): Promise { + const rpcArgs: Record = { builder: this._handle, url }; + if (displayText !== undefined) rpcArgs.displayText = displayText; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrlExpression', + rpcArgs + ); + return new AzureProvisioningResource(result, this._client); + } + + /** Adds a URL using a reference expression */ + withUrlExpression(url: ReferenceExpression, options?: WithUrlExpressionOptions): AzureProvisioningResourcePromise { + const displayText = options?.displayText; + return new AzureProvisioningResourcePromise(this._withUrlExpressionInternal(url, displayText)); + } + + /** @internal */ + private async _withUrlForEndpointInternal(endpointName: string, callback: (obj: ResourceUrlAnnotation) => Promise): Promise { + const callbackId = registerCallback(async (objData: unknown) => { + const obj = wrapIfHandle(objData) as ResourceUrlAnnotation; + await callback(obj); + }); + const rpcArgs: Record = { builder: this._handle, endpointName, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrlForEndpoint', + rpcArgs + ); + return new AzureProvisioningResource(result, this._client); + } + + /** Customizes the URL for a specific endpoint via callback */ + withUrlForEndpoint(endpointName: string, callback: (obj: ResourceUrlAnnotation) => Promise): AzureProvisioningResourcePromise { + return new AzureProvisioningResourcePromise(this._withUrlForEndpointInternal(endpointName, callback)); + } + + /** @internal */ + private async _excludeFromManifestInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/excludeFromManifest', + rpcArgs + ); + return new AzureProvisioningResource(result, this._client); + } + + /** Excludes the resource from the deployment manifest */ + excludeFromManifest(): AzureProvisioningResourcePromise { + return new AzureProvisioningResourcePromise(this._excludeFromManifestInternal()); + } + + /** @internal */ + private async _withExplicitStartInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withExplicitStart', + rpcArgs + ); + return new AzureProvisioningResource(result, this._client); + } + + /** Prevents resource from starting automatically */ + withExplicitStart(): AzureProvisioningResourcePromise { + return new AzureProvisioningResourcePromise(this._withExplicitStartInternal()); + } + + /** @internal */ + private async _withHealthCheckInternal(key: string): Promise { + const rpcArgs: Record = { builder: this._handle, key }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withHealthCheck', + rpcArgs + ); + return new AzureProvisioningResource(result, this._client); + } + + /** Adds a health check by key */ + withHealthCheck(key: string): AzureProvisioningResourcePromise { + return new AzureProvisioningResourcePromise(this._withHealthCheckInternal(key)); + } + + /** @internal */ + private async _withCommandInternal(name: string, displayName: string, executeCommand: (arg: ExecuteCommandContext) => Promise, commandOptions?: CommandOptions): Promise { + const executeCommandId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as ExecuteCommandContextHandle; + const arg = new ExecuteCommandContext(argHandle, this._client); + return await executeCommand(arg); + }); + const rpcArgs: Record = { builder: this._handle, name, displayName, executeCommand: executeCommandId }; + if (commandOptions !== undefined) rpcArgs.commandOptions = commandOptions; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withCommand', + rpcArgs + ); + return new AzureProvisioningResource(result, this._client); + } + + /** Adds a resource command */ + withCommand(name: string, displayName: string, executeCommand: (arg: ExecuteCommandContext) => Promise, options?: WithCommandOptions): AzureProvisioningResourcePromise { + const commandOptions = options?.commandOptions; + return new AzureProvisioningResourcePromise(this._withCommandInternal(name, displayName, executeCommand, commandOptions)); + } + + /** @internal */ + private async _withParentRelationshipInternal(parent: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, parent }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withParentRelationship', + rpcArgs + ); + return new AzureProvisioningResource(result, this._client); + } + + /** Sets the parent relationship */ + withParentRelationship(parent: ResourceBuilderBase): AzureProvisioningResourcePromise { + return new AzureProvisioningResourcePromise(this._withParentRelationshipInternal(parent)); + } + + /** @internal */ + private async _withChildRelationshipInternal(child: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, child }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withChildRelationship', + rpcArgs + ); + return new AzureProvisioningResource(result, this._client); + } + + /** Sets a child relationship */ + withChildRelationship(child: ResourceBuilderBase): AzureProvisioningResourcePromise { + return new AzureProvisioningResourcePromise(this._withChildRelationshipInternal(child)); + } + + /** @internal */ + private async _withIconNameInternal(iconName: string, iconVariant?: IconVariant): Promise { + const rpcArgs: Record = { builder: this._handle, iconName }; + if (iconVariant !== undefined) rpcArgs.iconVariant = iconVariant; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withIconName', + rpcArgs + ); + return new AzureProvisioningResource(result, this._client); + } + + /** Sets the icon for the resource */ + withIconName(iconName: string, options?: WithIconNameOptions): AzureProvisioningResourcePromise { + const iconVariant = options?.iconVariant; + return new AzureProvisioningResourcePromise(this._withIconNameInternal(iconName, iconVariant)); + } + + /** @internal */ + private async _excludeFromMcpInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/excludeFromMcp', + rpcArgs + ); + return new AzureProvisioningResource(result, this._client); + } + + /** Excludes the resource from MCP server exposure */ + excludeFromMcp(): AzureProvisioningResourcePromise { + return new AzureProvisioningResourcePromise(this._excludeFromMcpInternal()); + } + + /** @internal */ + private async _withPipelineStepFactoryInternal(stepName: string, callback: (arg: PipelineStepContext) => Promise, dependsOn?: string[], requiredBy?: string[], tags?: string[], description?: string): Promise { + const callbackId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as PipelineStepContextHandle; + const arg = new PipelineStepContext(argHandle, this._client); + await callback(arg); + }); + const rpcArgs: Record = { builder: this._handle, stepName, callback: callbackId }; + if (dependsOn !== undefined) rpcArgs.dependsOn = dependsOn; + if (requiredBy !== undefined) rpcArgs.requiredBy = requiredBy; + if (tags !== undefined) rpcArgs.tags = tags; + if (description !== undefined) rpcArgs.description = description; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withPipelineStepFactory', + rpcArgs + ); + return new AzureProvisioningResource(result, this._client); + } + + /** Adds a pipeline step to the resource */ + withPipelineStepFactory(stepName: string, callback: (arg: PipelineStepContext) => Promise, options?: WithPipelineStepFactoryOptions): AzureProvisioningResourcePromise { + const dependsOn = options?.dependsOn; + const requiredBy = options?.requiredBy; + const tags = options?.tags; + const description = options?.description; + return new AzureProvisioningResourcePromise(this._withPipelineStepFactoryInternal(stepName, callback, dependsOn, requiredBy, tags, description)); + } + + /** @internal */ + private async _withPipelineConfigurationAsyncInternal(callback: (arg: PipelineConfigurationContext) => Promise): Promise { + const callbackId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as PipelineConfigurationContextHandle; + const arg = new PipelineConfigurationContext(argHandle, this._client); + await callback(arg); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withPipelineConfigurationAsync', + rpcArgs + ); + return new AzureProvisioningResource(result, this._client); + } + + /** Configures pipeline step dependencies via an async callback */ + withPipelineConfigurationAsync(callback: (arg: PipelineConfigurationContext) => Promise): AzureProvisioningResourcePromise { + return new AzureProvisioningResourcePromise(this._withPipelineConfigurationAsyncInternal(callback)); + } + + /** @internal */ + private async _withPipelineConfigurationInternal(callback: (obj: PipelineConfigurationContext) => Promise): Promise { + const callbackId = registerCallback(async (objData: unknown) => { + const objHandle = wrapIfHandle(objData) as PipelineConfigurationContextHandle; + const obj = new PipelineConfigurationContext(objHandle, this._client); + await callback(obj); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withPipelineConfiguration', + rpcArgs + ); + return new AzureProvisioningResource(result, this._client); + } + + /** Configures pipeline step dependencies via a callback */ + withPipelineConfiguration(callback: (obj: PipelineConfigurationContext) => Promise): AzureProvisioningResourcePromise { + return new AzureProvisioningResourcePromise(this._withPipelineConfigurationInternal(callback)); + } + + /** Gets the resource name */ + async getResourceName(): Promise { + const rpcArgs: Record = { resource: this._handle }; + return await this._client.invokeCapability( + 'Aspire.Hosting/getResourceName', + rpcArgs + ); + } + + /** @internal */ + private async _withStorageRoleAssignmentsInternal(target: AzureStorageResource, roles: AzureStorageRole[]): Promise { + const rpcArgs: Record = { builder: this._handle, target, roles }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure.Storage/withStorageRoleAssignments', + rpcArgs + ); + return new AzureProvisioningResource(result, this._client); + } + + /** Assigns Azure Storage roles to a resource */ + withStorageRoleAssignments(target: AzureStorageResource, roles: AzureStorageRole[]): AzureProvisioningResourcePromise { + return new AzureProvisioningResourcePromise(this._withStorageRoleAssignmentsInternal(target, roles)); + } + + /** @internal */ + private async _withEventHubsRoleAssignmentsInternal(target: AzureEventHubsResource, roles: AzureEventHubsRole[]): Promise { + const rpcArgs: Record = { builder: this._handle, target, roles }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure.EventHubs/withEventHubsRoleAssignments', + rpcArgs + ); + return new AzureProvisioningResource(result, this._client); + } + + /** Assigns Event Hubs roles to a resource */ + withEventHubsRoleAssignments(target: AzureEventHubsResource, roles: AzureEventHubsRole[]): AzureProvisioningResourcePromise { + return new AzureProvisioningResourcePromise(this._withEventHubsRoleAssignmentsInternal(target, roles)); + } + + /** Gets an output reference from an Azure Bicep template resource */ + async getOutput(name: string): Promise { + const rpcArgs: Record = { builder: this._handle, name }; + return await this._client.invokeCapability( + 'Aspire.Hosting.Azure/getOutput', + rpcArgs + ); + } + + /** @internal */ + private async _withParameterInternal(name: string): Promise { + const rpcArgs: Record = { builder: this._handle, name }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure/withParameter', + rpcArgs + ); + return new AzureProvisioningResource(result, this._client); + } + + /** Adds a Bicep parameter without a value */ + withParameter(name: string): AzureProvisioningResourcePromise { + return new AzureProvisioningResourcePromise(this._withParameterInternal(name)); + } + + /** @internal */ + private async _withParameterStringValueInternal(name: string, value: string): Promise { + const rpcArgs: Record = { builder: this._handle, name, value }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure/withParameterStringValue', + rpcArgs + ); + return new AzureProvisioningResource(result, this._client); + } + + /** Adds a Bicep parameter with a string value */ + withParameterStringValue(name: string, value: string): AzureProvisioningResourcePromise { + return new AzureProvisioningResourcePromise(this._withParameterStringValueInternal(name, value)); + } + + /** @internal */ + private async _withParameterStringValuesInternal(name: string, value: string[]): Promise { + const rpcArgs: Record = { builder: this._handle, name, value }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure/withParameterStringValues', + rpcArgs + ); + return new AzureProvisioningResource(result, this._client); + } + + /** Adds a Bicep parameter with a string list value */ + withParameterStringValues(name: string, value: string[]): AzureProvisioningResourcePromise { + return new AzureProvisioningResourcePromise(this._withParameterStringValuesInternal(name, value)); + } + + /** @internal */ + private async _withParameterFromParameterInternal(name: string, value: ParameterResource): Promise { + const rpcArgs: Record = { builder: this._handle, name, value }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure/withParameterFromParameter', + rpcArgs + ); + return new AzureProvisioningResource(result, this._client); + } + + /** Adds a Bicep parameter from a parameter resource builder */ + withParameterFromParameter(name: string, value: ParameterResource): AzureProvisioningResourcePromise { + return new AzureProvisioningResourcePromise(this._withParameterFromParameterInternal(name, value)); + } + + /** @internal */ + private async _withParameterFromConnectionStringInternal(name: string, value: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, name, value }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure/withParameterFromConnectionString', + rpcArgs + ); + return new AzureProvisioningResource(result, this._client); + } + + /** Adds a Bicep parameter from a connection string resource builder */ + withParameterFromConnectionString(name: string, value: ResourceBuilderBase): AzureProvisioningResourcePromise { + return new AzureProvisioningResourcePromise(this._withParameterFromConnectionStringInternal(name, value)); + } + + /** @internal */ + private async _withParameterFromOutputInternal(name: string, value: BicepOutputReference): Promise { + const rpcArgs: Record = { builder: this._handle, name, value }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure/withParameterFromOutput', + rpcArgs + ); + return new AzureProvisioningResource(result, this._client); + } + + /** Adds a Bicep parameter from another Bicep output reference */ + withParameterFromOutput(name: string, value: BicepOutputReference): AzureProvisioningResourcePromise { + return new AzureProvisioningResourcePromise(this._withParameterFromOutputInternal(name, value)); + } + + /** @internal */ + private async _withParameterFromReferenceExpressionInternal(name: string, value: ReferenceExpression): Promise { + const rpcArgs: Record = { builder: this._handle, name, value }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure/withParameterFromReferenceExpression', + rpcArgs + ); + return new AzureProvisioningResource(result, this._client); + } + + /** Adds a Bicep parameter from a reference expression */ + withParameterFromReferenceExpression(name: string, value: ReferenceExpression): AzureProvisioningResourcePromise { + return new AzureProvisioningResourcePromise(this._withParameterFromReferenceExpressionInternal(name, value)); + } + + /** @internal */ + private async _withParameterFromEndpointInternal(name: string, value: EndpointReference): Promise { + const rpcArgs: Record = { builder: this._handle, name, value }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure/withParameterFromEndpoint', + rpcArgs + ); + return new AzureProvisioningResource(result, this._client); + } + + /** Adds a Bicep parameter from an endpoint reference */ + withParameterFromEndpoint(name: string, value: EndpointReference): AzureProvisioningResourcePromise { + return new AzureProvisioningResourcePromise(this._withParameterFromEndpointInternal(name, value)); + } + + /** @internal */ + private async _publishAsConnectionStringInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure/publishAsConnectionString', + rpcArgs + ); + return new AzureProvisioningResource(result, this._client); + } + + /** Publishes an Azure resource to the manifest as a connection string */ + publishAsConnectionString(): AzureProvisioningResourcePromise { + return new AzureProvisioningResourcePromise(this._publishAsConnectionStringInternal()); + } + + /** Gets the normalized Bicep identifier for an Azure resource */ + async getBicepIdentifier(): Promise { + const rpcArgs: Record = { resource: this._handle }; + return await this._client.invokeCapability( + 'Aspire.Hosting.Azure/getBicepIdentifier', + rpcArgs + ); + } + + /** @internal */ + private async _clearDefaultRoleAssignmentsInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure/clearDefaultRoleAssignments', + rpcArgs + ); + return new AzureProvisioningResource(result, this._client); + } + + /** Clears the default Azure role assignments from a resource */ + clearDefaultRoleAssignments(): AzureProvisioningResourcePromise { + return new AzureProvisioningResourcePromise(this._clearDefaultRoleAssignmentsInternal()); + } + + /** Determines whether a resource is marked as existing */ + async isExisting(): Promise { + const rpcArgs: Record = { resource: this._handle }; + return await this._client.invokeCapability( + 'Aspire.Hosting.Azure/isExisting', + rpcArgs + ); + } + + /** @internal */ + private async _runAsExistingFromParametersInternal(nameParameter: ParameterResource, resourceGroupParameter: ParameterResource): Promise { + const rpcArgs: Record = { builder: this._handle, nameParameter, resourceGroupParameter }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure/runAsExistingFromParameters', + rpcArgs + ); + return new AzureProvisioningResource(result, this._client); + } + + /** Marks an Azure resource as existing in run mode by using parameter resources */ + runAsExistingFromParameters(nameParameter: ParameterResource, resourceGroupParameter: ParameterResource): AzureProvisioningResourcePromise { + return new AzureProvisioningResourcePromise(this._runAsExistingFromParametersInternal(nameParameter, resourceGroupParameter)); + } + + /** @internal */ + private async _runAsExistingInternal(name: string, resourceGroup: string): Promise { + const rpcArgs: Record = { builder: this._handle, name, resourceGroup }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure/runAsExisting', + rpcArgs + ); + return new AzureProvisioningResource(result, this._client); + } + + /** Marks an Azure resource as existing in run mode */ + runAsExisting(name: string, resourceGroup: string): AzureProvisioningResourcePromise { + return new AzureProvisioningResourcePromise(this._runAsExistingInternal(name, resourceGroup)); + } + + /** @internal */ + private async _publishAsExistingFromParametersInternal(nameParameter: ParameterResource, resourceGroupParameter: ParameterResource): Promise { + const rpcArgs: Record = { builder: this._handle, nameParameter, resourceGroupParameter }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure/publishAsExistingFromParameters', + rpcArgs + ); + return new AzureProvisioningResource(result, this._client); + } + + /** Marks an Azure resource as existing in publish mode by using parameter resources */ + publishAsExistingFromParameters(nameParameter: ParameterResource, resourceGroupParameter: ParameterResource): AzureProvisioningResourcePromise { + return new AzureProvisioningResourcePromise(this._publishAsExistingFromParametersInternal(nameParameter, resourceGroupParameter)); + } + + /** @internal */ + private async _publishAsExistingInternal(name: string, resourceGroup: string): Promise { + const rpcArgs: Record = { builder: this._handle, name, resourceGroup }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure/publishAsExisting', + rpcArgs + ); + return new AzureProvisioningResource(result, this._client); + } + + /** Marks an Azure resource as existing in publish mode */ + publishAsExisting(name: string, resourceGroup: string): AzureProvisioningResourcePromise { + return new AzureProvisioningResourcePromise(this._publishAsExistingInternal(name, resourceGroup)); + } + + /** @internal */ + private async _asExistingInternal(nameParameter: ParameterResource, resourceGroupParameter: ParameterResource): Promise { + const rpcArgs: Record = { builder: this._handle, nameParameter, resourceGroupParameter }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure/asExistingFromParameters', + rpcArgs + ); + return new AzureProvisioningResource(result, this._client); + } + + /** Marks an Azure resource as existing in both run and publish modes by using parameter resources */ + asExisting(nameParameter: ParameterResource, resourceGroupParameter: ParameterResource): AzureProvisioningResourcePromise { + return new AzureProvisioningResourcePromise(this._asExistingInternal(nameParameter, resourceGroupParameter)); + } + +} + +/** + * Thenable wrapper for AzureProvisioningResource that enables fluent chaining. + * @example + * await builder.addSomething().withX().withY(); + */ +export class AzureProvisioningResourcePromise implements PromiseLike { + constructor(private _promise: Promise) {} + + then( + onfulfilled?: ((value: AzureProvisioningResource) => TResult1 | PromiseLike) | null, + onrejected?: ((reason: unknown) => TResult2 | PromiseLike) | null + ): PromiseLike { + return this._promise.then(onfulfilled, onrejected); + } + + /** Configures a resource to use a container registry */ + withContainerRegistry(registry: ResourceBuilderBase): AzureProvisioningResourcePromise { + return new AzureProvisioningResourcePromise(this._promise.then(obj => obj.withContainerRegistry(registry))); + } + + /** Sets the base image for a Dockerfile build */ + withDockerfileBaseImage(options?: WithDockerfileBaseImageOptions): AzureProvisioningResourcePromise { + return new AzureProvisioningResourcePromise(this._promise.then(obj => obj.withDockerfileBaseImage(options))); + } + + /** Adds a required command dependency */ + withRequiredCommand(command: string, options?: WithRequiredCommandOptions): AzureProvisioningResourcePromise { + return new AzureProvisioningResourcePromise(this._promise.then(obj => obj.withRequiredCommand(command, options))); + } + + /** Customizes displayed URLs via callback */ + withUrlsCallback(callback: (obj: ResourceUrlsCallbackContext) => Promise): AzureProvisioningResourcePromise { + return new AzureProvisioningResourcePromise(this._promise.then(obj => obj.withUrlsCallback(callback))); + } + + /** Customizes displayed URLs via async callback */ + withUrlsCallbackAsync(callback: (arg: ResourceUrlsCallbackContext) => Promise): AzureProvisioningResourcePromise { + return new AzureProvisioningResourcePromise(this._promise.then(obj => obj.withUrlsCallbackAsync(callback))); + } + + /** Adds or modifies displayed URLs */ + withUrl(url: string, options?: WithUrlOptions): AzureProvisioningResourcePromise { + return new AzureProvisioningResourcePromise(this._promise.then(obj => obj.withUrl(url, options))); + } + + /** Adds a URL using a reference expression */ + withUrlExpression(url: ReferenceExpression, options?: WithUrlExpressionOptions): AzureProvisioningResourcePromise { + return new AzureProvisioningResourcePromise(this._promise.then(obj => obj.withUrlExpression(url, options))); + } + + /** Customizes the URL for a specific endpoint via callback */ + withUrlForEndpoint(endpointName: string, callback: (obj: ResourceUrlAnnotation) => Promise): AzureProvisioningResourcePromise { + return new AzureProvisioningResourcePromise(this._promise.then(obj => obj.withUrlForEndpoint(endpointName, callback))); + } + + /** Excludes the resource from the deployment manifest */ + excludeFromManifest(): AzureProvisioningResourcePromise { + return new AzureProvisioningResourcePromise(this._promise.then(obj => obj.excludeFromManifest())); + } + + /** Prevents resource from starting automatically */ + withExplicitStart(): AzureProvisioningResourcePromise { + return new AzureProvisioningResourcePromise(this._promise.then(obj => obj.withExplicitStart())); + } + + /** Adds a health check by key */ + withHealthCheck(key: string): AzureProvisioningResourcePromise { + return new AzureProvisioningResourcePromise(this._promise.then(obj => obj.withHealthCheck(key))); + } + + /** Adds a resource command */ + withCommand(name: string, displayName: string, executeCommand: (arg: ExecuteCommandContext) => Promise, options?: WithCommandOptions): AzureProvisioningResourcePromise { + return new AzureProvisioningResourcePromise(this._promise.then(obj => obj.withCommand(name, displayName, executeCommand, options))); + } + + /** Sets the parent relationship */ + withParentRelationship(parent: ResourceBuilderBase): AzureProvisioningResourcePromise { + return new AzureProvisioningResourcePromise(this._promise.then(obj => obj.withParentRelationship(parent))); + } + + /** Sets a child relationship */ + withChildRelationship(child: ResourceBuilderBase): AzureProvisioningResourcePromise { + return new AzureProvisioningResourcePromise(this._promise.then(obj => obj.withChildRelationship(child))); + } + + /** Sets the icon for the resource */ + withIconName(iconName: string, options?: WithIconNameOptions): AzureProvisioningResourcePromise { + return new AzureProvisioningResourcePromise(this._promise.then(obj => obj.withIconName(iconName, options))); + } + + /** Excludes the resource from MCP server exposure */ + excludeFromMcp(): AzureProvisioningResourcePromise { + return new AzureProvisioningResourcePromise(this._promise.then(obj => obj.excludeFromMcp())); + } + + /** Adds a pipeline step to the resource */ + withPipelineStepFactory(stepName: string, callback: (arg: PipelineStepContext) => Promise, options?: WithPipelineStepFactoryOptions): AzureProvisioningResourcePromise { + return new AzureProvisioningResourcePromise(this._promise.then(obj => obj.withPipelineStepFactory(stepName, callback, options))); + } + + /** Configures pipeline step dependencies via an async callback */ + withPipelineConfigurationAsync(callback: (arg: PipelineConfigurationContext) => Promise): AzureProvisioningResourcePromise { + return new AzureProvisioningResourcePromise(this._promise.then(obj => obj.withPipelineConfigurationAsync(callback))); + } + + /** Configures pipeline step dependencies via a callback */ + withPipelineConfiguration(callback: (obj: PipelineConfigurationContext) => Promise): AzureProvisioningResourcePromise { + return new AzureProvisioningResourcePromise(this._promise.then(obj => obj.withPipelineConfiguration(callback))); + } + + /** Gets the resource name */ + getResourceName(): Promise { + return this._promise.then(obj => obj.getResourceName()); + } + + /** Assigns Azure Storage roles to a resource */ + withStorageRoleAssignments(target: AzureStorageResource, roles: AzureStorageRole[]): AzureProvisioningResourcePromise { + return new AzureProvisioningResourcePromise(this._promise.then(obj => obj.withStorageRoleAssignments(target, roles))); + } + + /** Assigns Event Hubs roles to a resource */ + withEventHubsRoleAssignments(target: AzureEventHubsResource, roles: AzureEventHubsRole[]): AzureProvisioningResourcePromise { + return new AzureProvisioningResourcePromise(this._promise.then(obj => obj.withEventHubsRoleAssignments(target, roles))); + } + + /** Gets an output reference from an Azure Bicep template resource */ + getOutput(name: string): Promise { + return this._promise.then(obj => obj.getOutput(name)); + } + + /** Adds a Bicep parameter without a value */ + withParameter(name: string): AzureProvisioningResourcePromise { + return new AzureProvisioningResourcePromise(this._promise.then(obj => obj.withParameter(name))); + } + + /** Adds a Bicep parameter with a string value */ + withParameterStringValue(name: string, value: string): AzureProvisioningResourcePromise { + return new AzureProvisioningResourcePromise(this._promise.then(obj => obj.withParameterStringValue(name, value))); + } + + /** Adds a Bicep parameter with a string list value */ + withParameterStringValues(name: string, value: string[]): AzureProvisioningResourcePromise { + return new AzureProvisioningResourcePromise(this._promise.then(obj => obj.withParameterStringValues(name, value))); + } + + /** Adds a Bicep parameter from a parameter resource builder */ + withParameterFromParameter(name: string, value: ParameterResource): AzureProvisioningResourcePromise { + return new AzureProvisioningResourcePromise(this._promise.then(obj => obj.withParameterFromParameter(name, value))); + } + + /** Adds a Bicep parameter from a connection string resource builder */ + withParameterFromConnectionString(name: string, value: ResourceBuilderBase): AzureProvisioningResourcePromise { + return new AzureProvisioningResourcePromise(this._promise.then(obj => obj.withParameterFromConnectionString(name, value))); + } + + /** Adds a Bicep parameter from another Bicep output reference */ + withParameterFromOutput(name: string, value: BicepOutputReference): AzureProvisioningResourcePromise { + return new AzureProvisioningResourcePromise(this._promise.then(obj => obj.withParameterFromOutput(name, value))); + } + + /** Adds a Bicep parameter from a reference expression */ + withParameterFromReferenceExpression(name: string, value: ReferenceExpression): AzureProvisioningResourcePromise { + return new AzureProvisioningResourcePromise(this._promise.then(obj => obj.withParameterFromReferenceExpression(name, value))); + } + + /** Adds a Bicep parameter from an endpoint reference */ + withParameterFromEndpoint(name: string, value: EndpointReference): AzureProvisioningResourcePromise { + return new AzureProvisioningResourcePromise(this._promise.then(obj => obj.withParameterFromEndpoint(name, value))); + } + + /** Publishes an Azure resource to the manifest as a connection string */ + publishAsConnectionString(): AzureProvisioningResourcePromise { + return new AzureProvisioningResourcePromise(this._promise.then(obj => obj.publishAsConnectionString())); + } + + /** Gets the normalized Bicep identifier for an Azure resource */ + getBicepIdentifier(): Promise { + return this._promise.then(obj => obj.getBicepIdentifier()); + } + + /** Clears the default Azure role assignments from a resource */ + clearDefaultRoleAssignments(): AzureProvisioningResourcePromise { + return new AzureProvisioningResourcePromise(this._promise.then(obj => obj.clearDefaultRoleAssignments())); + } + + /** Determines whether a resource is marked as existing */ + isExisting(): Promise { + return this._promise.then(obj => obj.isExisting()); + } + + /** Marks an Azure resource as existing in run mode by using parameter resources */ + runAsExistingFromParameters(nameParameter: ParameterResource, resourceGroupParameter: ParameterResource): AzureProvisioningResourcePromise { + return new AzureProvisioningResourcePromise(this._promise.then(obj => obj.runAsExistingFromParameters(nameParameter, resourceGroupParameter))); + } + + /** Marks an Azure resource as existing in run mode */ + runAsExisting(name: string, resourceGroup: string): AzureProvisioningResourcePromise { + return new AzureProvisioningResourcePromise(this._promise.then(obj => obj.runAsExisting(name, resourceGroup))); + } + + /** Marks an Azure resource as existing in publish mode by using parameter resources */ + publishAsExistingFromParameters(nameParameter: ParameterResource, resourceGroupParameter: ParameterResource): AzureProvisioningResourcePromise { + return new AzureProvisioningResourcePromise(this._promise.then(obj => obj.publishAsExistingFromParameters(nameParameter, resourceGroupParameter))); + } + + /** Marks an Azure resource as existing in publish mode */ + publishAsExisting(name: string, resourceGroup: string): AzureProvisioningResourcePromise { + return new AzureProvisioningResourcePromise(this._promise.then(obj => obj.publishAsExisting(name, resourceGroup))); + } + + /** Marks an Azure resource as existing in both run and publish modes by using parameter resources */ + asExisting(nameParameter: ParameterResource, resourceGroupParameter: ParameterResource): AzureProvisioningResourcePromise { + return new AzureProvisioningResourcePromise(this._promise.then(obj => obj.asExisting(nameParameter, resourceGroupParameter))); + } + +} + +// ============================================================================ +// AzureQueueStorageQueueResource +// ============================================================================ + +export class AzureQueueStorageQueueResource extends ResourceBuilderBase { + constructor(handle: AzureQueueStorageQueueResourceHandle, client: AspireClientRpc) { + super(handle, client); + } + + /** @internal */ + private async _withContainerRegistryInternal(registry: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, registry }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withContainerRegistry', + rpcArgs + ); + return new AzureQueueStorageQueueResource(result, this._client); + } + + /** Configures a resource to use a container registry */ + withContainerRegistry(registry: ResourceBuilderBase): AzureQueueStorageQueueResourcePromise { + return new AzureQueueStorageQueueResourcePromise(this._withContainerRegistryInternal(registry)); + } + + /** @internal */ + private async _withDockerfileBaseImageInternal(buildImage?: string, runtimeImage?: string): Promise { + const rpcArgs: Record = { builder: this._handle }; + if (buildImage !== undefined) rpcArgs.buildImage = buildImage; + if (runtimeImage !== undefined) rpcArgs.runtimeImage = runtimeImage; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withDockerfileBaseImage', + rpcArgs + ); + return new AzureQueueStorageQueueResource(result, this._client); + } + + /** Sets the base image for a Dockerfile build */ + withDockerfileBaseImage(options?: WithDockerfileBaseImageOptions): AzureQueueStorageQueueResourcePromise { + const buildImage = options?.buildImage; + const runtimeImage = options?.runtimeImage; + return new AzureQueueStorageQueueResourcePromise(this._withDockerfileBaseImageInternal(buildImage, runtimeImage)); + } + + /** @internal */ + private async _withRequiredCommandInternal(command: string, helpLink?: string): Promise { + const rpcArgs: Record = { builder: this._handle, command }; + if (helpLink !== undefined) rpcArgs.helpLink = helpLink; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withRequiredCommand', + rpcArgs + ); + return new AzureQueueStorageQueueResource(result, this._client); + } + + /** Adds a required command dependency */ + withRequiredCommand(command: string, options?: WithRequiredCommandOptions): AzureQueueStorageQueueResourcePromise { + const helpLink = options?.helpLink; + return new AzureQueueStorageQueueResourcePromise(this._withRequiredCommandInternal(command, helpLink)); + } + + /** @internal */ + private async _withConnectionPropertyInternal(name: string, value: ReferenceExpression): Promise { + const rpcArgs: Record = { builder: this._handle, name, value }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withConnectionProperty', + rpcArgs + ); + return new AzureQueueStorageQueueResource(result, this._client); + } + + /** Adds a connection property with a reference expression */ + withConnectionProperty(name: string, value: ReferenceExpression): AzureQueueStorageQueueResourcePromise { + return new AzureQueueStorageQueueResourcePromise(this._withConnectionPropertyInternal(name, value)); + } + + /** @internal */ + private async _withConnectionPropertyValueInternal(name: string, value: string): Promise { + const rpcArgs: Record = { builder: this._handle, name, value }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withConnectionPropertyValue', + rpcArgs + ); + return new AzureQueueStorageQueueResource(result, this._client); + } + + /** Adds a connection property with a string value */ + withConnectionPropertyValue(name: string, value: string): AzureQueueStorageQueueResourcePromise { + return new AzureQueueStorageQueueResourcePromise(this._withConnectionPropertyValueInternal(name, value)); + } + + /** @internal */ + private async _withUrlsCallbackInternal(callback: (obj: ResourceUrlsCallbackContext) => Promise): Promise { + const callbackId = registerCallback(async (objData: unknown) => { + const objHandle = wrapIfHandle(objData) as ResourceUrlsCallbackContextHandle; + const obj = new ResourceUrlsCallbackContext(objHandle, this._client); + await callback(obj); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrlsCallback', + rpcArgs + ); + return new AzureQueueStorageQueueResource(result, this._client); + } + + /** Customizes displayed URLs via callback */ + withUrlsCallback(callback: (obj: ResourceUrlsCallbackContext) => Promise): AzureQueueStorageQueueResourcePromise { + return new AzureQueueStorageQueueResourcePromise(this._withUrlsCallbackInternal(callback)); + } + + /** @internal */ + private async _withUrlsCallbackAsyncInternal(callback: (arg: ResourceUrlsCallbackContext) => Promise): Promise { + const callbackId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as ResourceUrlsCallbackContextHandle; + const arg = new ResourceUrlsCallbackContext(argHandle, this._client); + await callback(arg); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrlsCallbackAsync', + rpcArgs + ); + return new AzureQueueStorageQueueResource(result, this._client); + } + + /** Customizes displayed URLs via async callback */ + withUrlsCallbackAsync(callback: (arg: ResourceUrlsCallbackContext) => Promise): AzureQueueStorageQueueResourcePromise { + return new AzureQueueStorageQueueResourcePromise(this._withUrlsCallbackAsyncInternal(callback)); + } + + /** @internal */ + private async _withUrlInternal(url: string, displayText?: string): Promise { + const rpcArgs: Record = { builder: this._handle, url }; + if (displayText !== undefined) rpcArgs.displayText = displayText; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrl', + rpcArgs + ); + return new AzureQueueStorageQueueResource(result, this._client); + } + + /** Adds or modifies displayed URLs */ + withUrl(url: string, options?: WithUrlOptions): AzureQueueStorageQueueResourcePromise { + const displayText = options?.displayText; + return new AzureQueueStorageQueueResourcePromise(this._withUrlInternal(url, displayText)); + } + + /** @internal */ + private async _withUrlExpressionInternal(url: ReferenceExpression, displayText?: string): Promise { + const rpcArgs: Record = { builder: this._handle, url }; + if (displayText !== undefined) rpcArgs.displayText = displayText; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrlExpression', + rpcArgs + ); + return new AzureQueueStorageQueueResource(result, this._client); + } + + /** Adds a URL using a reference expression */ + withUrlExpression(url: ReferenceExpression, options?: WithUrlExpressionOptions): AzureQueueStorageQueueResourcePromise { + const displayText = options?.displayText; + return new AzureQueueStorageQueueResourcePromise(this._withUrlExpressionInternal(url, displayText)); + } + + /** @internal */ + private async _withUrlForEndpointInternal(endpointName: string, callback: (obj: ResourceUrlAnnotation) => Promise): Promise { + const callbackId = registerCallback(async (objData: unknown) => { + const obj = wrapIfHandle(objData) as ResourceUrlAnnotation; + await callback(obj); + }); + const rpcArgs: Record = { builder: this._handle, endpointName, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrlForEndpoint', + rpcArgs + ); + return new AzureQueueStorageQueueResource(result, this._client); + } + + /** Customizes the URL for a specific endpoint via callback */ + withUrlForEndpoint(endpointName: string, callback: (obj: ResourceUrlAnnotation) => Promise): AzureQueueStorageQueueResourcePromise { + return new AzureQueueStorageQueueResourcePromise(this._withUrlForEndpointInternal(endpointName, callback)); + } + + /** @internal */ + private async _excludeFromManifestInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/excludeFromManifest', + rpcArgs + ); + return new AzureQueueStorageQueueResource(result, this._client); + } + + /** Excludes the resource from the deployment manifest */ + excludeFromManifest(): AzureQueueStorageQueueResourcePromise { + return new AzureQueueStorageQueueResourcePromise(this._excludeFromManifestInternal()); + } + + /** @internal */ + private async _withExplicitStartInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withExplicitStart', + rpcArgs + ); + return new AzureQueueStorageQueueResource(result, this._client); + } + + /** Prevents resource from starting automatically */ + withExplicitStart(): AzureQueueStorageQueueResourcePromise { + return new AzureQueueStorageQueueResourcePromise(this._withExplicitStartInternal()); + } + + /** @internal */ + private async _withHealthCheckInternal(key: string): Promise { + const rpcArgs: Record = { builder: this._handle, key }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withHealthCheck', + rpcArgs + ); + return new AzureQueueStorageQueueResource(result, this._client); + } + + /** Adds a health check by key */ + withHealthCheck(key: string): AzureQueueStorageQueueResourcePromise { + return new AzureQueueStorageQueueResourcePromise(this._withHealthCheckInternal(key)); + } + + /** @internal */ + private async _withCommandInternal(name: string, displayName: string, executeCommand: (arg: ExecuteCommandContext) => Promise, commandOptions?: CommandOptions): Promise { + const executeCommandId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as ExecuteCommandContextHandle; + const arg = new ExecuteCommandContext(argHandle, this._client); + return await executeCommand(arg); + }); + const rpcArgs: Record = { builder: this._handle, name, displayName, executeCommand: executeCommandId }; + if (commandOptions !== undefined) rpcArgs.commandOptions = commandOptions; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withCommand', + rpcArgs + ); + return new AzureQueueStorageQueueResource(result, this._client); + } + + /** Adds a resource command */ + withCommand(name: string, displayName: string, executeCommand: (arg: ExecuteCommandContext) => Promise, options?: WithCommandOptions): AzureQueueStorageQueueResourcePromise { + const commandOptions = options?.commandOptions; + return new AzureQueueStorageQueueResourcePromise(this._withCommandInternal(name, displayName, executeCommand, commandOptions)); + } + + /** @internal */ + private async _withParentRelationshipInternal(parent: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, parent }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withParentRelationship', + rpcArgs + ); + return new AzureQueueStorageQueueResource(result, this._client); + } + + /** Sets the parent relationship */ + withParentRelationship(parent: ResourceBuilderBase): AzureQueueStorageQueueResourcePromise { + return new AzureQueueStorageQueueResourcePromise(this._withParentRelationshipInternal(parent)); + } + + /** @internal */ + private async _withChildRelationshipInternal(child: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, child }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withChildRelationship', + rpcArgs + ); + return new AzureQueueStorageQueueResource(result, this._client); + } + + /** Sets a child relationship */ + withChildRelationship(child: ResourceBuilderBase): AzureQueueStorageQueueResourcePromise { + return new AzureQueueStorageQueueResourcePromise(this._withChildRelationshipInternal(child)); + } + + /** @internal */ + private async _withIconNameInternal(iconName: string, iconVariant?: IconVariant): Promise { + const rpcArgs: Record = { builder: this._handle, iconName }; + if (iconVariant !== undefined) rpcArgs.iconVariant = iconVariant; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withIconName', + rpcArgs + ); + return new AzureQueueStorageQueueResource(result, this._client); + } + + /** Sets the icon for the resource */ + withIconName(iconName: string, options?: WithIconNameOptions): AzureQueueStorageQueueResourcePromise { + const iconVariant = options?.iconVariant; + return new AzureQueueStorageQueueResourcePromise(this._withIconNameInternal(iconName, iconVariant)); + } + + /** @internal */ + private async _excludeFromMcpInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/excludeFromMcp', + rpcArgs + ); + return new AzureQueueStorageQueueResource(result, this._client); + } + + /** Excludes the resource from MCP server exposure */ + excludeFromMcp(): AzureQueueStorageQueueResourcePromise { + return new AzureQueueStorageQueueResourcePromise(this._excludeFromMcpInternal()); + } + + /** @internal */ + private async _withPipelineStepFactoryInternal(stepName: string, callback: (arg: PipelineStepContext) => Promise, dependsOn?: string[], requiredBy?: string[], tags?: string[], description?: string): Promise { + const callbackId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as PipelineStepContextHandle; + const arg = new PipelineStepContext(argHandle, this._client); + await callback(arg); + }); + const rpcArgs: Record = { builder: this._handle, stepName, callback: callbackId }; + if (dependsOn !== undefined) rpcArgs.dependsOn = dependsOn; + if (requiredBy !== undefined) rpcArgs.requiredBy = requiredBy; + if (tags !== undefined) rpcArgs.tags = tags; + if (description !== undefined) rpcArgs.description = description; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withPipelineStepFactory', + rpcArgs + ); + return new AzureQueueStorageQueueResource(result, this._client); + } + + /** Adds a pipeline step to the resource */ + withPipelineStepFactory(stepName: string, callback: (arg: PipelineStepContext) => Promise, options?: WithPipelineStepFactoryOptions): AzureQueueStorageQueueResourcePromise { + const dependsOn = options?.dependsOn; + const requiredBy = options?.requiredBy; + const tags = options?.tags; + const description = options?.description; + return new AzureQueueStorageQueueResourcePromise(this._withPipelineStepFactoryInternal(stepName, callback, dependsOn, requiredBy, tags, description)); + } + + /** @internal */ + private async _withPipelineConfigurationAsyncInternal(callback: (arg: PipelineConfigurationContext) => Promise): Promise { + const callbackId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as PipelineConfigurationContextHandle; + const arg = new PipelineConfigurationContext(argHandle, this._client); + await callback(arg); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withPipelineConfigurationAsync', + rpcArgs + ); + return new AzureQueueStorageQueueResource(result, this._client); + } + + /** Configures pipeline step dependencies via an async callback */ + withPipelineConfigurationAsync(callback: (arg: PipelineConfigurationContext) => Promise): AzureQueueStorageQueueResourcePromise { + return new AzureQueueStorageQueueResourcePromise(this._withPipelineConfigurationAsyncInternal(callback)); + } + + /** @internal */ + private async _withPipelineConfigurationInternal(callback: (obj: PipelineConfigurationContext) => Promise): Promise { + const callbackId = registerCallback(async (objData: unknown) => { + const objHandle = wrapIfHandle(objData) as PipelineConfigurationContextHandle; + const obj = new PipelineConfigurationContext(objHandle, this._client); + await callback(obj); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withPipelineConfiguration', + rpcArgs + ); + return new AzureQueueStorageQueueResource(result, this._client); + } + + /** Configures pipeline step dependencies via a callback */ + withPipelineConfiguration(callback: (obj: PipelineConfigurationContext) => Promise): AzureQueueStorageQueueResourcePromise { + return new AzureQueueStorageQueueResourcePromise(this._withPipelineConfigurationInternal(callback)); + } + + /** Gets the resource name */ + async getResourceName(): Promise { + const rpcArgs: Record = { resource: this._handle }; + return await this._client.invokeCapability( + 'Aspire.Hosting/getResourceName', + rpcArgs + ); + } + + /** @internal */ + private async _withStorageRoleAssignmentsInternal(target: AzureStorageResource, roles: AzureStorageRole[]): Promise { + const rpcArgs: Record = { builder: this._handle, target, roles }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure.Storage/withStorageRoleAssignments', + rpcArgs + ); + return new AzureQueueStorageQueueResource(result, this._client); + } + + /** Assigns Azure Storage roles to a resource */ + withStorageRoleAssignments(target: AzureStorageResource, roles: AzureStorageRole[]): AzureQueueStorageQueueResourcePromise { + return new AzureQueueStorageQueueResourcePromise(this._withStorageRoleAssignmentsInternal(target, roles)); + } + + /** @internal */ + private async _withEventHubsRoleAssignmentsInternal(target: AzureEventHubsResource, roles: AzureEventHubsRole[]): Promise { + const rpcArgs: Record = { builder: this._handle, target, roles }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure.EventHubs/withEventHubsRoleAssignments', + rpcArgs + ); + return new AzureQueueStorageQueueResource(result, this._client); + } + + /** Assigns Event Hubs roles to a resource */ + withEventHubsRoleAssignments(target: AzureEventHubsResource, roles: AzureEventHubsRole[]): AzureQueueStorageQueueResourcePromise { + return new AzureQueueStorageQueueResourcePromise(this._withEventHubsRoleAssignmentsInternal(target, roles)); + } + +} + +/** + * Thenable wrapper for AzureQueueStorageQueueResource that enables fluent chaining. + * @example + * await builder.addSomething().withX().withY(); + */ +export class AzureQueueStorageQueueResourcePromise implements PromiseLike { + constructor(private _promise: Promise) {} + + then( + onfulfilled?: ((value: AzureQueueStorageQueueResource) => TResult1 | PromiseLike) | null, + onrejected?: ((reason: unknown) => TResult2 | PromiseLike) | null + ): PromiseLike { + return this._promise.then(onfulfilled, onrejected); + } + + /** Configures a resource to use a container registry */ + withContainerRegistry(registry: ResourceBuilderBase): AzureQueueStorageQueueResourcePromise { + return new AzureQueueStorageQueueResourcePromise(this._promise.then(obj => obj.withContainerRegistry(registry))); + } + + /** Sets the base image for a Dockerfile build */ + withDockerfileBaseImage(options?: WithDockerfileBaseImageOptions): AzureQueueStorageQueueResourcePromise { + return new AzureQueueStorageQueueResourcePromise(this._promise.then(obj => obj.withDockerfileBaseImage(options))); + } + + /** Adds a required command dependency */ + withRequiredCommand(command: string, options?: WithRequiredCommandOptions): AzureQueueStorageQueueResourcePromise { + return new AzureQueueStorageQueueResourcePromise(this._promise.then(obj => obj.withRequiredCommand(command, options))); + } + + /** Adds a connection property with a reference expression */ + withConnectionProperty(name: string, value: ReferenceExpression): AzureQueueStorageQueueResourcePromise { + return new AzureQueueStorageQueueResourcePromise(this._promise.then(obj => obj.withConnectionProperty(name, value))); + } + + /** Adds a connection property with a string value */ + withConnectionPropertyValue(name: string, value: string): AzureQueueStorageQueueResourcePromise { + return new AzureQueueStorageQueueResourcePromise(this._promise.then(obj => obj.withConnectionPropertyValue(name, value))); + } + + /** Customizes displayed URLs via callback */ + withUrlsCallback(callback: (obj: ResourceUrlsCallbackContext) => Promise): AzureQueueStorageQueueResourcePromise { + return new AzureQueueStorageQueueResourcePromise(this._promise.then(obj => obj.withUrlsCallback(callback))); + } + + /** Customizes displayed URLs via async callback */ + withUrlsCallbackAsync(callback: (arg: ResourceUrlsCallbackContext) => Promise): AzureQueueStorageQueueResourcePromise { + return new AzureQueueStorageQueueResourcePromise(this._promise.then(obj => obj.withUrlsCallbackAsync(callback))); + } + + /** Adds or modifies displayed URLs */ + withUrl(url: string, options?: WithUrlOptions): AzureQueueStorageQueueResourcePromise { + return new AzureQueueStorageQueueResourcePromise(this._promise.then(obj => obj.withUrl(url, options))); + } + + /** Adds a URL using a reference expression */ + withUrlExpression(url: ReferenceExpression, options?: WithUrlExpressionOptions): AzureQueueStorageQueueResourcePromise { + return new AzureQueueStorageQueueResourcePromise(this._promise.then(obj => obj.withUrlExpression(url, options))); + } + + /** Customizes the URL for a specific endpoint via callback */ + withUrlForEndpoint(endpointName: string, callback: (obj: ResourceUrlAnnotation) => Promise): AzureQueueStorageQueueResourcePromise { + return new AzureQueueStorageQueueResourcePromise(this._promise.then(obj => obj.withUrlForEndpoint(endpointName, callback))); + } + + /** Excludes the resource from the deployment manifest */ + excludeFromManifest(): AzureQueueStorageQueueResourcePromise { + return new AzureQueueStorageQueueResourcePromise(this._promise.then(obj => obj.excludeFromManifest())); + } + + /** Prevents resource from starting automatically */ + withExplicitStart(): AzureQueueStorageQueueResourcePromise { + return new AzureQueueStorageQueueResourcePromise(this._promise.then(obj => obj.withExplicitStart())); + } + + /** Adds a health check by key */ + withHealthCheck(key: string): AzureQueueStorageQueueResourcePromise { + return new AzureQueueStorageQueueResourcePromise(this._promise.then(obj => obj.withHealthCheck(key))); + } + + /** Adds a resource command */ + withCommand(name: string, displayName: string, executeCommand: (arg: ExecuteCommandContext) => Promise, options?: WithCommandOptions): AzureQueueStorageQueueResourcePromise { + return new AzureQueueStorageQueueResourcePromise(this._promise.then(obj => obj.withCommand(name, displayName, executeCommand, options))); + } + + /** Sets the parent relationship */ + withParentRelationship(parent: ResourceBuilderBase): AzureQueueStorageQueueResourcePromise { + return new AzureQueueStorageQueueResourcePromise(this._promise.then(obj => obj.withParentRelationship(parent))); + } + + /** Sets a child relationship */ + withChildRelationship(child: ResourceBuilderBase): AzureQueueStorageQueueResourcePromise { + return new AzureQueueStorageQueueResourcePromise(this._promise.then(obj => obj.withChildRelationship(child))); + } + + /** Sets the icon for the resource */ + withIconName(iconName: string, options?: WithIconNameOptions): AzureQueueStorageQueueResourcePromise { + return new AzureQueueStorageQueueResourcePromise(this._promise.then(obj => obj.withIconName(iconName, options))); + } + + /** Excludes the resource from MCP server exposure */ + excludeFromMcp(): AzureQueueStorageQueueResourcePromise { + return new AzureQueueStorageQueueResourcePromise(this._promise.then(obj => obj.excludeFromMcp())); + } + + /** Adds a pipeline step to the resource */ + withPipelineStepFactory(stepName: string, callback: (arg: PipelineStepContext) => Promise, options?: WithPipelineStepFactoryOptions): AzureQueueStorageQueueResourcePromise { + return new AzureQueueStorageQueueResourcePromise(this._promise.then(obj => obj.withPipelineStepFactory(stepName, callback, options))); + } + + /** Configures pipeline step dependencies via an async callback */ + withPipelineConfigurationAsync(callback: (arg: PipelineConfigurationContext) => Promise): AzureQueueStorageQueueResourcePromise { + return new AzureQueueStorageQueueResourcePromise(this._promise.then(obj => obj.withPipelineConfigurationAsync(callback))); + } + + /** Configures pipeline step dependencies via a callback */ + withPipelineConfiguration(callback: (obj: PipelineConfigurationContext) => Promise): AzureQueueStorageQueueResourcePromise { + return new AzureQueueStorageQueueResourcePromise(this._promise.then(obj => obj.withPipelineConfiguration(callback))); + } + + /** Gets the resource name */ + getResourceName(): Promise { + return this._promise.then(obj => obj.getResourceName()); + } + + /** Assigns Azure Storage roles to a resource */ + withStorageRoleAssignments(target: AzureStorageResource, roles: AzureStorageRole[]): AzureQueueStorageQueueResourcePromise { + return new AzureQueueStorageQueueResourcePromise(this._promise.then(obj => obj.withStorageRoleAssignments(target, roles))); + } + + /** Assigns Event Hubs roles to a resource */ + withEventHubsRoleAssignments(target: AzureEventHubsResource, roles: AzureEventHubsRole[]): AzureQueueStorageQueueResourcePromise { + return new AzureQueueStorageQueueResourcePromise(this._promise.then(obj => obj.withEventHubsRoleAssignments(target, roles))); + } + +} + +// ============================================================================ +// AzureQueueStorageResource +// ============================================================================ + +export class AzureQueueStorageResource extends ResourceBuilderBase { + constructor(handle: AzureQueueStorageResourceHandle, client: AspireClientRpc) { + super(handle, client); + } + + /** @internal */ + private async _withContainerRegistryInternal(registry: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, registry }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withContainerRegistry', + rpcArgs + ); + return new AzureQueueStorageResource(result, this._client); + } + + /** Configures a resource to use a container registry */ + withContainerRegistry(registry: ResourceBuilderBase): AzureQueueStorageResourcePromise { + return new AzureQueueStorageResourcePromise(this._withContainerRegistryInternal(registry)); + } + + /** @internal */ + private async _withDockerfileBaseImageInternal(buildImage?: string, runtimeImage?: string): Promise { + const rpcArgs: Record = { builder: this._handle }; + if (buildImage !== undefined) rpcArgs.buildImage = buildImage; + if (runtimeImage !== undefined) rpcArgs.runtimeImage = runtimeImage; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withDockerfileBaseImage', + rpcArgs + ); + return new AzureQueueStorageResource(result, this._client); + } + + /** Sets the base image for a Dockerfile build */ + withDockerfileBaseImage(options?: WithDockerfileBaseImageOptions): AzureQueueStorageResourcePromise { + const buildImage = options?.buildImage; + const runtimeImage = options?.runtimeImage; + return new AzureQueueStorageResourcePromise(this._withDockerfileBaseImageInternal(buildImage, runtimeImage)); + } + + /** @internal */ + private async _withRequiredCommandInternal(command: string, helpLink?: string): Promise { + const rpcArgs: Record = { builder: this._handle, command }; + if (helpLink !== undefined) rpcArgs.helpLink = helpLink; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withRequiredCommand', + rpcArgs + ); + return new AzureQueueStorageResource(result, this._client); + } + + /** Adds a required command dependency */ + withRequiredCommand(command: string, options?: WithRequiredCommandOptions): AzureQueueStorageResourcePromise { + const helpLink = options?.helpLink; + return new AzureQueueStorageResourcePromise(this._withRequiredCommandInternal(command, helpLink)); + } + + /** @internal */ + private async _withConnectionPropertyInternal(name: string, value: ReferenceExpression): Promise { + const rpcArgs: Record = { builder: this._handle, name, value }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withConnectionProperty', + rpcArgs + ); + return new AzureQueueStorageResource(result, this._client); + } + + /** Adds a connection property with a reference expression */ + withConnectionProperty(name: string, value: ReferenceExpression): AzureQueueStorageResourcePromise { + return new AzureQueueStorageResourcePromise(this._withConnectionPropertyInternal(name, value)); + } + + /** @internal */ + private async _withConnectionPropertyValueInternal(name: string, value: string): Promise { + const rpcArgs: Record = { builder: this._handle, name, value }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withConnectionPropertyValue', + rpcArgs + ); + return new AzureQueueStorageResource(result, this._client); + } + + /** Adds a connection property with a string value */ + withConnectionPropertyValue(name: string, value: string): AzureQueueStorageResourcePromise { + return new AzureQueueStorageResourcePromise(this._withConnectionPropertyValueInternal(name, value)); + } + + /** @internal */ + private async _withUrlsCallbackInternal(callback: (obj: ResourceUrlsCallbackContext) => Promise): Promise { + const callbackId = registerCallback(async (objData: unknown) => { + const objHandle = wrapIfHandle(objData) as ResourceUrlsCallbackContextHandle; + const obj = new ResourceUrlsCallbackContext(objHandle, this._client); + await callback(obj); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrlsCallback', + rpcArgs + ); + return new AzureQueueStorageResource(result, this._client); + } + + /** Customizes displayed URLs via callback */ + withUrlsCallback(callback: (obj: ResourceUrlsCallbackContext) => Promise): AzureQueueStorageResourcePromise { + return new AzureQueueStorageResourcePromise(this._withUrlsCallbackInternal(callback)); + } + + /** @internal */ + private async _withUrlsCallbackAsyncInternal(callback: (arg: ResourceUrlsCallbackContext) => Promise): Promise { + const callbackId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as ResourceUrlsCallbackContextHandle; + const arg = new ResourceUrlsCallbackContext(argHandle, this._client); + await callback(arg); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrlsCallbackAsync', + rpcArgs + ); + return new AzureQueueStorageResource(result, this._client); + } + + /** Customizes displayed URLs via async callback */ + withUrlsCallbackAsync(callback: (arg: ResourceUrlsCallbackContext) => Promise): AzureQueueStorageResourcePromise { + return new AzureQueueStorageResourcePromise(this._withUrlsCallbackAsyncInternal(callback)); + } + + /** @internal */ + private async _withUrlInternal(url: string, displayText?: string): Promise { + const rpcArgs: Record = { builder: this._handle, url }; + if (displayText !== undefined) rpcArgs.displayText = displayText; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrl', + rpcArgs + ); + return new AzureQueueStorageResource(result, this._client); + } + + /** Adds or modifies displayed URLs */ + withUrl(url: string, options?: WithUrlOptions): AzureQueueStorageResourcePromise { + const displayText = options?.displayText; + return new AzureQueueStorageResourcePromise(this._withUrlInternal(url, displayText)); + } + + /** @internal */ + private async _withUrlExpressionInternal(url: ReferenceExpression, displayText?: string): Promise { + const rpcArgs: Record = { builder: this._handle, url }; + if (displayText !== undefined) rpcArgs.displayText = displayText; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrlExpression', + rpcArgs + ); + return new AzureQueueStorageResource(result, this._client); + } + + /** Adds a URL using a reference expression */ + withUrlExpression(url: ReferenceExpression, options?: WithUrlExpressionOptions): AzureQueueStorageResourcePromise { + const displayText = options?.displayText; + return new AzureQueueStorageResourcePromise(this._withUrlExpressionInternal(url, displayText)); + } + + /** @internal */ + private async _withUrlForEndpointInternal(endpointName: string, callback: (obj: ResourceUrlAnnotation) => Promise): Promise { + const callbackId = registerCallback(async (objData: unknown) => { + const obj = wrapIfHandle(objData) as ResourceUrlAnnotation; + await callback(obj); + }); + const rpcArgs: Record = { builder: this._handle, endpointName, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrlForEndpoint', + rpcArgs + ); + return new AzureQueueStorageResource(result, this._client); + } + + /** Customizes the URL for a specific endpoint via callback */ + withUrlForEndpoint(endpointName: string, callback: (obj: ResourceUrlAnnotation) => Promise): AzureQueueStorageResourcePromise { + return new AzureQueueStorageResourcePromise(this._withUrlForEndpointInternal(endpointName, callback)); + } + + /** @internal */ + private async _excludeFromManifestInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/excludeFromManifest', + rpcArgs + ); + return new AzureQueueStorageResource(result, this._client); + } + + /** Excludes the resource from the deployment manifest */ + excludeFromManifest(): AzureQueueStorageResourcePromise { + return new AzureQueueStorageResourcePromise(this._excludeFromManifestInternal()); + } + + /** @internal */ + private async _withExplicitStartInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withExplicitStart', + rpcArgs + ); + return new AzureQueueStorageResource(result, this._client); + } + + /** Prevents resource from starting automatically */ + withExplicitStart(): AzureQueueStorageResourcePromise { + return new AzureQueueStorageResourcePromise(this._withExplicitStartInternal()); + } + + /** @internal */ + private async _withHealthCheckInternal(key: string): Promise { + const rpcArgs: Record = { builder: this._handle, key }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withHealthCheck', + rpcArgs + ); + return new AzureQueueStorageResource(result, this._client); + } + + /** Adds a health check by key */ + withHealthCheck(key: string): AzureQueueStorageResourcePromise { + return new AzureQueueStorageResourcePromise(this._withHealthCheckInternal(key)); + } + + /** @internal */ + private async _withCommandInternal(name: string, displayName: string, executeCommand: (arg: ExecuteCommandContext) => Promise, commandOptions?: CommandOptions): Promise { + const executeCommandId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as ExecuteCommandContextHandle; + const arg = new ExecuteCommandContext(argHandle, this._client); + return await executeCommand(arg); + }); + const rpcArgs: Record = { builder: this._handle, name, displayName, executeCommand: executeCommandId }; + if (commandOptions !== undefined) rpcArgs.commandOptions = commandOptions; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withCommand', + rpcArgs + ); + return new AzureQueueStorageResource(result, this._client); + } + + /** Adds a resource command */ + withCommand(name: string, displayName: string, executeCommand: (arg: ExecuteCommandContext) => Promise, options?: WithCommandOptions): AzureQueueStorageResourcePromise { + const commandOptions = options?.commandOptions; + return new AzureQueueStorageResourcePromise(this._withCommandInternal(name, displayName, executeCommand, commandOptions)); + } + + /** @internal */ + private async _withParentRelationshipInternal(parent: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, parent }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withParentRelationship', + rpcArgs + ); + return new AzureQueueStorageResource(result, this._client); + } + + /** Sets the parent relationship */ + withParentRelationship(parent: ResourceBuilderBase): AzureQueueStorageResourcePromise { + return new AzureQueueStorageResourcePromise(this._withParentRelationshipInternal(parent)); + } + + /** @internal */ + private async _withChildRelationshipInternal(child: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, child }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withChildRelationship', + rpcArgs + ); + return new AzureQueueStorageResource(result, this._client); + } + + /** Sets a child relationship */ + withChildRelationship(child: ResourceBuilderBase): AzureQueueStorageResourcePromise { + return new AzureQueueStorageResourcePromise(this._withChildRelationshipInternal(child)); + } + + /** @internal */ + private async _withIconNameInternal(iconName: string, iconVariant?: IconVariant): Promise { + const rpcArgs: Record = { builder: this._handle, iconName }; + if (iconVariant !== undefined) rpcArgs.iconVariant = iconVariant; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withIconName', + rpcArgs + ); + return new AzureQueueStorageResource(result, this._client); + } + + /** Sets the icon for the resource */ + withIconName(iconName: string, options?: WithIconNameOptions): AzureQueueStorageResourcePromise { + const iconVariant = options?.iconVariant; + return new AzureQueueStorageResourcePromise(this._withIconNameInternal(iconName, iconVariant)); + } + + /** @internal */ + private async _excludeFromMcpInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/excludeFromMcp', + rpcArgs + ); + return new AzureQueueStorageResource(result, this._client); + } + + /** Excludes the resource from MCP server exposure */ + excludeFromMcp(): AzureQueueStorageResourcePromise { + return new AzureQueueStorageResourcePromise(this._excludeFromMcpInternal()); + } + + /** @internal */ + private async _withPipelineStepFactoryInternal(stepName: string, callback: (arg: PipelineStepContext) => Promise, dependsOn?: string[], requiredBy?: string[], tags?: string[], description?: string): Promise { + const callbackId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as PipelineStepContextHandle; + const arg = new PipelineStepContext(argHandle, this._client); + await callback(arg); + }); + const rpcArgs: Record = { builder: this._handle, stepName, callback: callbackId }; + if (dependsOn !== undefined) rpcArgs.dependsOn = dependsOn; + if (requiredBy !== undefined) rpcArgs.requiredBy = requiredBy; + if (tags !== undefined) rpcArgs.tags = tags; + if (description !== undefined) rpcArgs.description = description; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withPipelineStepFactory', + rpcArgs + ); + return new AzureQueueStorageResource(result, this._client); + } + + /** Adds a pipeline step to the resource */ + withPipelineStepFactory(stepName: string, callback: (arg: PipelineStepContext) => Promise, options?: WithPipelineStepFactoryOptions): AzureQueueStorageResourcePromise { + const dependsOn = options?.dependsOn; + const requiredBy = options?.requiredBy; + const tags = options?.tags; + const description = options?.description; + return new AzureQueueStorageResourcePromise(this._withPipelineStepFactoryInternal(stepName, callback, dependsOn, requiredBy, tags, description)); + } + + /** @internal */ + private async _withPipelineConfigurationAsyncInternal(callback: (arg: PipelineConfigurationContext) => Promise): Promise { + const callbackId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as PipelineConfigurationContextHandle; + const arg = new PipelineConfigurationContext(argHandle, this._client); + await callback(arg); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withPipelineConfigurationAsync', + rpcArgs + ); + return new AzureQueueStorageResource(result, this._client); + } + + /** Configures pipeline step dependencies via an async callback */ + withPipelineConfigurationAsync(callback: (arg: PipelineConfigurationContext) => Promise): AzureQueueStorageResourcePromise { + return new AzureQueueStorageResourcePromise(this._withPipelineConfigurationAsyncInternal(callback)); + } + + /** @internal */ + private async _withPipelineConfigurationInternal(callback: (obj: PipelineConfigurationContext) => Promise): Promise { + const callbackId = registerCallback(async (objData: unknown) => { + const objHandle = wrapIfHandle(objData) as PipelineConfigurationContextHandle; + const obj = new PipelineConfigurationContext(objHandle, this._client); + await callback(obj); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withPipelineConfiguration', + rpcArgs + ); + return new AzureQueueStorageResource(result, this._client); + } + + /** Configures pipeline step dependencies via a callback */ + withPipelineConfiguration(callback: (obj: PipelineConfigurationContext) => Promise): AzureQueueStorageResourcePromise { + return new AzureQueueStorageResourcePromise(this._withPipelineConfigurationInternal(callback)); + } + + /** Gets the resource name */ + async getResourceName(): Promise { + const rpcArgs: Record = { resource: this._handle }; + return await this._client.invokeCapability( + 'Aspire.Hosting/getResourceName', + rpcArgs + ); + } + + /** @internal */ + private async _withStorageRoleAssignmentsInternal(target: AzureStorageResource, roles: AzureStorageRole[]): Promise { + const rpcArgs: Record = { builder: this._handle, target, roles }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure.Storage/withStorageRoleAssignments', + rpcArgs + ); + return new AzureQueueStorageResource(result, this._client); + } + + /** Assigns Azure Storage roles to a resource */ + withStorageRoleAssignments(target: AzureStorageResource, roles: AzureStorageRole[]): AzureQueueStorageResourcePromise { + return new AzureQueueStorageResourcePromise(this._withStorageRoleAssignmentsInternal(target, roles)); + } + + /** @internal */ + private async _withEventHubsRoleAssignmentsInternal(target: AzureEventHubsResource, roles: AzureEventHubsRole[]): Promise { + const rpcArgs: Record = { builder: this._handle, target, roles }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure.EventHubs/withEventHubsRoleAssignments', + rpcArgs + ); + return new AzureQueueStorageResource(result, this._client); + } + + /** Assigns Event Hubs roles to a resource */ + withEventHubsRoleAssignments(target: AzureEventHubsResource, roles: AzureEventHubsRole[]): AzureQueueStorageResourcePromise { + return new AzureQueueStorageResourcePromise(this._withEventHubsRoleAssignmentsInternal(target, roles)); + } + +} + +/** + * Thenable wrapper for AzureQueueStorageResource that enables fluent chaining. + * @example + * await builder.addSomething().withX().withY(); + */ +export class AzureQueueStorageResourcePromise implements PromiseLike { + constructor(private _promise: Promise) {} + + then( + onfulfilled?: ((value: AzureQueueStorageResource) => TResult1 | PromiseLike) | null, + onrejected?: ((reason: unknown) => TResult2 | PromiseLike) | null + ): PromiseLike { + return this._promise.then(onfulfilled, onrejected); + } + + /** Configures a resource to use a container registry */ + withContainerRegistry(registry: ResourceBuilderBase): AzureQueueStorageResourcePromise { + return new AzureQueueStorageResourcePromise(this._promise.then(obj => obj.withContainerRegistry(registry))); + } + + /** Sets the base image for a Dockerfile build */ + withDockerfileBaseImage(options?: WithDockerfileBaseImageOptions): AzureQueueStorageResourcePromise { + return new AzureQueueStorageResourcePromise(this._promise.then(obj => obj.withDockerfileBaseImage(options))); + } + + /** Adds a required command dependency */ + withRequiredCommand(command: string, options?: WithRequiredCommandOptions): AzureQueueStorageResourcePromise { + return new AzureQueueStorageResourcePromise(this._promise.then(obj => obj.withRequiredCommand(command, options))); + } + + /** Adds a connection property with a reference expression */ + withConnectionProperty(name: string, value: ReferenceExpression): AzureQueueStorageResourcePromise { + return new AzureQueueStorageResourcePromise(this._promise.then(obj => obj.withConnectionProperty(name, value))); + } + + /** Adds a connection property with a string value */ + withConnectionPropertyValue(name: string, value: string): AzureQueueStorageResourcePromise { + return new AzureQueueStorageResourcePromise(this._promise.then(obj => obj.withConnectionPropertyValue(name, value))); + } + + /** Customizes displayed URLs via callback */ + withUrlsCallback(callback: (obj: ResourceUrlsCallbackContext) => Promise): AzureQueueStorageResourcePromise { + return new AzureQueueStorageResourcePromise(this._promise.then(obj => obj.withUrlsCallback(callback))); + } + + /** Customizes displayed URLs via async callback */ + withUrlsCallbackAsync(callback: (arg: ResourceUrlsCallbackContext) => Promise): AzureQueueStorageResourcePromise { + return new AzureQueueStorageResourcePromise(this._promise.then(obj => obj.withUrlsCallbackAsync(callback))); + } + + /** Adds or modifies displayed URLs */ + withUrl(url: string, options?: WithUrlOptions): AzureQueueStorageResourcePromise { + return new AzureQueueStorageResourcePromise(this._promise.then(obj => obj.withUrl(url, options))); + } + + /** Adds a URL using a reference expression */ + withUrlExpression(url: ReferenceExpression, options?: WithUrlExpressionOptions): AzureQueueStorageResourcePromise { + return new AzureQueueStorageResourcePromise(this._promise.then(obj => obj.withUrlExpression(url, options))); + } + + /** Customizes the URL for a specific endpoint via callback */ + withUrlForEndpoint(endpointName: string, callback: (obj: ResourceUrlAnnotation) => Promise): AzureQueueStorageResourcePromise { + return new AzureQueueStorageResourcePromise(this._promise.then(obj => obj.withUrlForEndpoint(endpointName, callback))); + } + + /** Excludes the resource from the deployment manifest */ + excludeFromManifest(): AzureQueueStorageResourcePromise { + return new AzureQueueStorageResourcePromise(this._promise.then(obj => obj.excludeFromManifest())); + } + + /** Prevents resource from starting automatically */ + withExplicitStart(): AzureQueueStorageResourcePromise { + return new AzureQueueStorageResourcePromise(this._promise.then(obj => obj.withExplicitStart())); + } + + /** Adds a health check by key */ + withHealthCheck(key: string): AzureQueueStorageResourcePromise { + return new AzureQueueStorageResourcePromise(this._promise.then(obj => obj.withHealthCheck(key))); + } + + /** Adds a resource command */ + withCommand(name: string, displayName: string, executeCommand: (arg: ExecuteCommandContext) => Promise, options?: WithCommandOptions): AzureQueueStorageResourcePromise { + return new AzureQueueStorageResourcePromise(this._promise.then(obj => obj.withCommand(name, displayName, executeCommand, options))); + } + + /** Sets the parent relationship */ + withParentRelationship(parent: ResourceBuilderBase): AzureQueueStorageResourcePromise { + return new AzureQueueStorageResourcePromise(this._promise.then(obj => obj.withParentRelationship(parent))); + } + + /** Sets a child relationship */ + withChildRelationship(child: ResourceBuilderBase): AzureQueueStorageResourcePromise { + return new AzureQueueStorageResourcePromise(this._promise.then(obj => obj.withChildRelationship(child))); + } + + /** Sets the icon for the resource */ + withIconName(iconName: string, options?: WithIconNameOptions): AzureQueueStorageResourcePromise { + return new AzureQueueStorageResourcePromise(this._promise.then(obj => obj.withIconName(iconName, options))); + } + + /** Excludes the resource from MCP server exposure */ + excludeFromMcp(): AzureQueueStorageResourcePromise { + return new AzureQueueStorageResourcePromise(this._promise.then(obj => obj.excludeFromMcp())); + } + + /** Adds a pipeline step to the resource */ + withPipelineStepFactory(stepName: string, callback: (arg: PipelineStepContext) => Promise, options?: WithPipelineStepFactoryOptions): AzureQueueStorageResourcePromise { + return new AzureQueueStorageResourcePromise(this._promise.then(obj => obj.withPipelineStepFactory(stepName, callback, options))); + } + + /** Configures pipeline step dependencies via an async callback */ + withPipelineConfigurationAsync(callback: (arg: PipelineConfigurationContext) => Promise): AzureQueueStorageResourcePromise { + return new AzureQueueStorageResourcePromise(this._promise.then(obj => obj.withPipelineConfigurationAsync(callback))); + } + + /** Configures pipeline step dependencies via a callback */ + withPipelineConfiguration(callback: (obj: PipelineConfigurationContext) => Promise): AzureQueueStorageResourcePromise { + return new AzureQueueStorageResourcePromise(this._promise.then(obj => obj.withPipelineConfiguration(callback))); + } + + /** Gets the resource name */ + getResourceName(): Promise { + return this._promise.then(obj => obj.getResourceName()); + } + + /** Assigns Azure Storage roles to a resource */ + withStorageRoleAssignments(target: AzureStorageResource, roles: AzureStorageRole[]): AzureQueueStorageResourcePromise { + return new AzureQueueStorageResourcePromise(this._promise.then(obj => obj.withStorageRoleAssignments(target, roles))); + } + + /** Assigns Event Hubs roles to a resource */ + withEventHubsRoleAssignments(target: AzureEventHubsResource, roles: AzureEventHubsRole[]): AzureQueueStorageResourcePromise { + return new AzureQueueStorageResourcePromise(this._promise.then(obj => obj.withEventHubsRoleAssignments(target, roles))); + } + +} + +// ============================================================================ +// AzureStorageEmulatorResource +// ============================================================================ + +export class AzureStorageEmulatorResource extends ResourceBuilderBase { + constructor(handle: AzureStorageEmulatorResourceHandle, client: AspireClientRpc) { + super(handle, client); + } + + /** @internal */ + private async _withContainerRegistryInternal(registry: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, registry }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withContainerRegistry', + rpcArgs + ); + return new AzureStorageEmulatorResource(result, this._client); + } + + /** Configures a resource to use a container registry */ + withContainerRegistry(registry: ResourceBuilderBase): AzureStorageEmulatorResourcePromise { + return new AzureStorageEmulatorResourcePromise(this._withContainerRegistryInternal(registry)); + } + + /** @internal */ + private async _withBindMountInternal(source: string, target: string, isReadOnly?: boolean): Promise { + const rpcArgs: Record = { builder: this._handle, source, target }; + if (isReadOnly !== undefined) rpcArgs.isReadOnly = isReadOnly; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withBindMount', + rpcArgs + ); + return new AzureStorageEmulatorResource(result, this._client); + } + + /** Adds a bind mount */ + withBindMount(source: string, target: string, options?: WithBindMountOptions): AzureStorageEmulatorResourcePromise { + const isReadOnly = options?.isReadOnly; + return new AzureStorageEmulatorResourcePromise(this._withBindMountInternal(source, target, isReadOnly)); + } + + /** @internal */ + private async _withEntrypointInternal(entrypoint: string): Promise { + const rpcArgs: Record = { builder: this._handle, entrypoint }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withEntrypoint', + rpcArgs + ); + return new AzureStorageEmulatorResource(result, this._client); + } + + /** Sets the container entrypoint */ + withEntrypoint(entrypoint: string): AzureStorageEmulatorResourcePromise { + return new AzureStorageEmulatorResourcePromise(this._withEntrypointInternal(entrypoint)); + } + + /** @internal */ + private async _withImageTagInternal(tag: string): Promise { + const rpcArgs: Record = { builder: this._handle, tag }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withImageTag', + rpcArgs + ); + return new AzureStorageEmulatorResource(result, this._client); + } + + /** Sets the container image tag */ + withImageTag(tag: string): AzureStorageEmulatorResourcePromise { + return new AzureStorageEmulatorResourcePromise(this._withImageTagInternal(tag)); + } + + /** @internal */ + private async _withImageRegistryInternal(registry: string): Promise { + const rpcArgs: Record = { builder: this._handle, registry }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withImageRegistry', + rpcArgs + ); + return new AzureStorageEmulatorResource(result, this._client); + } + + /** Sets the container image registry */ + withImageRegistry(registry: string): AzureStorageEmulatorResourcePromise { + return new AzureStorageEmulatorResourcePromise(this._withImageRegistryInternal(registry)); + } + + /** @internal */ + private async _withImageInternal(image: string, tag?: string): Promise { + const rpcArgs: Record = { builder: this._handle, image }; + if (tag !== undefined) rpcArgs.tag = tag; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withImage', + rpcArgs + ); + return new AzureStorageEmulatorResource(result, this._client); + } + + /** Sets the container image */ + withImage(image: string, options?: WithImageOptions): AzureStorageEmulatorResourcePromise { + const tag = options?.tag; + return new AzureStorageEmulatorResourcePromise(this._withImageInternal(image, tag)); + } + + /** @internal */ + private async _withImageSHA256Internal(sha256: string): Promise { + const rpcArgs: Record = { builder: this._handle, sha256 }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withImageSHA256', + rpcArgs + ); + return new AzureStorageEmulatorResource(result, this._client); + } + + /** Sets the image SHA256 digest */ + withImageSHA256(sha256: string): AzureStorageEmulatorResourcePromise { + return new AzureStorageEmulatorResourcePromise(this._withImageSHA256Internal(sha256)); + } + + /** @internal */ + private async _withContainerRuntimeArgsInternal(args: string[]): Promise { + const rpcArgs: Record = { builder: this._handle, args }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withContainerRuntimeArgs', + rpcArgs + ); + return new AzureStorageEmulatorResource(result, this._client); + } + + /** Adds runtime arguments for the container */ + withContainerRuntimeArgs(args: string[]): AzureStorageEmulatorResourcePromise { + return new AzureStorageEmulatorResourcePromise(this._withContainerRuntimeArgsInternal(args)); + } + + /** @internal */ + private async _withLifetimeInternal(lifetime: ContainerLifetime): Promise { + const rpcArgs: Record = { builder: this._handle, lifetime }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withLifetime', + rpcArgs + ); + return new AzureStorageEmulatorResource(result, this._client); + } + + /** Sets the lifetime behavior of the container resource */ + withLifetime(lifetime: ContainerLifetime): AzureStorageEmulatorResourcePromise { + return new AzureStorageEmulatorResourcePromise(this._withLifetimeInternal(lifetime)); + } + + /** @internal */ + private async _withImagePullPolicyInternal(pullPolicy: ImagePullPolicy): Promise { + const rpcArgs: Record = { builder: this._handle, pullPolicy }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withImagePullPolicy', + rpcArgs + ); + return new AzureStorageEmulatorResource(result, this._client); + } + + /** Sets the container image pull policy */ + withImagePullPolicy(pullPolicy: ImagePullPolicy): AzureStorageEmulatorResourcePromise { + return new AzureStorageEmulatorResourcePromise(this._withImagePullPolicyInternal(pullPolicy)); + } + + /** @internal */ + private async _publishAsContainerInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/publishAsContainer', + rpcArgs + ); + return new AzureStorageEmulatorResource(result, this._client); + } + + /** Configures the resource to be published as a container */ + publishAsContainer(): AzureStorageEmulatorResourcePromise { + return new AzureStorageEmulatorResourcePromise(this._publishAsContainerInternal()); + } + + /** @internal */ + private async _withDockerfileInternal(contextPath: string, dockerfilePath?: string, stage?: string): Promise { + const rpcArgs: Record = { builder: this._handle, contextPath }; + if (dockerfilePath !== undefined) rpcArgs.dockerfilePath = dockerfilePath; + if (stage !== undefined) rpcArgs.stage = stage; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withDockerfile', + rpcArgs + ); + return new AzureStorageEmulatorResource(result, this._client); + } + + /** Configures the resource to use a Dockerfile */ + withDockerfile(contextPath: string, options?: WithDockerfileOptions): AzureStorageEmulatorResourcePromise { + const dockerfilePath = options?.dockerfilePath; + const stage = options?.stage; + return new AzureStorageEmulatorResourcePromise(this._withDockerfileInternal(contextPath, dockerfilePath, stage)); + } + + /** @internal */ + private async _withContainerNameInternal(name: string): Promise { + const rpcArgs: Record = { builder: this._handle, name }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withContainerName', + rpcArgs + ); + return new AzureStorageEmulatorResource(result, this._client); + } + + /** Sets the container name */ + withContainerName(name: string): AzureStorageEmulatorResourcePromise { + return new AzureStorageEmulatorResourcePromise(this._withContainerNameInternal(name)); + } + + /** @internal */ + private async _withBuildArgInternal(name: string, value: ParameterResource): Promise { + const rpcArgs: Record = { builder: this._handle, name, value }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withBuildArg', + rpcArgs + ); + return new AzureStorageEmulatorResource(result, this._client); + } + + /** Adds a build argument from a parameter resource */ + withBuildArg(name: string, value: ParameterResource): AzureStorageEmulatorResourcePromise { + return new AzureStorageEmulatorResourcePromise(this._withBuildArgInternal(name, value)); + } + + /** @internal */ + private async _withBuildSecretInternal(name: string, value: ParameterResource): Promise { + const rpcArgs: Record = { builder: this._handle, name, value }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withBuildSecret', + rpcArgs + ); + return new AzureStorageEmulatorResource(result, this._client); + } + + /** Adds a build secret from a parameter resource */ + withBuildSecret(name: string, value: ParameterResource): AzureStorageEmulatorResourcePromise { + return new AzureStorageEmulatorResourcePromise(this._withBuildSecretInternal(name, value)); + } + + /** @internal */ + private async _withEndpointProxySupportInternal(proxyEnabled: boolean): Promise { + const rpcArgs: Record = { builder: this._handle, proxyEnabled }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withEndpointProxySupport', + rpcArgs + ); + return new AzureStorageEmulatorResource(result, this._client); + } + + /** Configures endpoint proxy support */ + withEndpointProxySupport(proxyEnabled: boolean): AzureStorageEmulatorResourcePromise { + return new AzureStorageEmulatorResourcePromise(this._withEndpointProxySupportInternal(proxyEnabled)); + } + + /** @internal */ + private async _withDockerfileBaseImageInternal(buildImage?: string, runtimeImage?: string): Promise { + const rpcArgs: Record = { builder: this._handle }; + if (buildImage !== undefined) rpcArgs.buildImage = buildImage; + if (runtimeImage !== undefined) rpcArgs.runtimeImage = runtimeImage; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withDockerfileBaseImage', + rpcArgs + ); + return new AzureStorageEmulatorResource(result, this._client); + } + + /** Sets the base image for a Dockerfile build */ + withDockerfileBaseImage(options?: WithDockerfileBaseImageOptions): AzureStorageEmulatorResourcePromise { + const buildImage = options?.buildImage; + const runtimeImage = options?.runtimeImage; + return new AzureStorageEmulatorResourcePromise(this._withDockerfileBaseImageInternal(buildImage, runtimeImage)); + } + + /** @internal */ + private async _withContainerNetworkAliasInternal(alias: string): Promise { + const rpcArgs: Record = { builder: this._handle, alias }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withContainerNetworkAlias', + rpcArgs + ); + return new AzureStorageEmulatorResource(result, this._client); + } + + /** Adds a network alias for the container */ + withContainerNetworkAlias(alias: string): AzureStorageEmulatorResourcePromise { + return new AzureStorageEmulatorResourcePromise(this._withContainerNetworkAliasInternal(alias)); + } + + /** @internal */ + private async _withMcpServerInternal(path?: string, endpointName?: string): Promise { + const rpcArgs: Record = { builder: this._handle }; + if (path !== undefined) rpcArgs.path = path; + if (endpointName !== undefined) rpcArgs.endpointName = endpointName; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withMcpServer', + rpcArgs + ); + return new AzureStorageEmulatorResource(result, this._client); + } + + /** Configures an MCP server endpoint on the resource */ + withMcpServer(options?: WithMcpServerOptions): AzureStorageEmulatorResourcePromise { + const path = options?.path; + const endpointName = options?.endpointName; + return new AzureStorageEmulatorResourcePromise(this._withMcpServerInternal(path, endpointName)); + } + + /** @internal */ + private async _withOtlpExporterInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withOtlpExporter', + rpcArgs + ); + return new AzureStorageEmulatorResource(result, this._client); + } + + /** Configures OTLP telemetry export */ + withOtlpExporter(): AzureStorageEmulatorResourcePromise { + return new AzureStorageEmulatorResourcePromise(this._withOtlpExporterInternal()); + } + + /** @internal */ + private async _withOtlpExporterProtocolInternal(protocol: OtlpProtocol): Promise { + const rpcArgs: Record = { builder: this._handle, protocol }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withOtlpExporterProtocol', + rpcArgs + ); + return new AzureStorageEmulatorResource(result, this._client); + } + + /** Configures OTLP telemetry export with specific protocol */ + withOtlpExporterProtocol(protocol: OtlpProtocol): AzureStorageEmulatorResourcePromise { + return new AzureStorageEmulatorResourcePromise(this._withOtlpExporterProtocolInternal(protocol)); + } + + /** @internal */ + private async _publishAsConnectionStringInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/publishAsConnectionString', + rpcArgs + ); + return new AzureStorageEmulatorResource(result, this._client); + } + + /** Publishes the resource as a connection string */ + publishAsConnectionString(): AzureStorageEmulatorResourcePromise { + return new AzureStorageEmulatorResourcePromise(this._publishAsConnectionStringInternal()); + } + + /** @internal */ + private async _withRequiredCommandInternal(command: string, helpLink?: string): Promise { + const rpcArgs: Record = { builder: this._handle, command }; + if (helpLink !== undefined) rpcArgs.helpLink = helpLink; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withRequiredCommand', + rpcArgs + ); + return new AzureStorageEmulatorResource(result, this._client); + } + + /** Adds a required command dependency */ + withRequiredCommand(command: string, options?: WithRequiredCommandOptions): AzureStorageEmulatorResourcePromise { + const helpLink = options?.helpLink; + return new AzureStorageEmulatorResourcePromise(this._withRequiredCommandInternal(command, helpLink)); + } + + /** @internal */ + private async _withEnvironmentInternal(name: string, value: string): Promise { + const rpcArgs: Record = { builder: this._handle, name, value }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withEnvironment', + rpcArgs + ); + return new AzureStorageEmulatorResource(result, this._client); + } + + /** Sets an environment variable */ + withEnvironment(name: string, value: string): AzureStorageEmulatorResourcePromise { + return new AzureStorageEmulatorResourcePromise(this._withEnvironmentInternal(name, value)); + } + + /** @internal */ + private async _withEnvironmentExpressionInternal(name: string, value: ReferenceExpression): Promise { + const rpcArgs: Record = { builder: this._handle, name, value }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withEnvironmentExpression', + rpcArgs + ); + return new AzureStorageEmulatorResource(result, this._client); + } + + /** Adds an environment variable with a reference expression */ + withEnvironmentExpression(name: string, value: ReferenceExpression): AzureStorageEmulatorResourcePromise { + return new AzureStorageEmulatorResourcePromise(this._withEnvironmentExpressionInternal(name, value)); + } + + /** @internal */ + private async _withEnvironmentCallbackInternal(callback: (obj: EnvironmentCallbackContext) => Promise): Promise { + const callbackId = registerCallback(async (objData: unknown) => { + const objHandle = wrapIfHandle(objData) as EnvironmentCallbackContextHandle; + const obj = new EnvironmentCallbackContext(objHandle, this._client); + await callback(obj); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withEnvironmentCallback', + rpcArgs + ); + return new AzureStorageEmulatorResource(result, this._client); + } + + /** Sets environment variables via callback */ + withEnvironmentCallback(callback: (obj: EnvironmentCallbackContext) => Promise): AzureStorageEmulatorResourcePromise { + return new AzureStorageEmulatorResourcePromise(this._withEnvironmentCallbackInternal(callback)); + } + + /** @internal */ + private async _withEnvironmentCallbackAsyncInternal(callback: (arg: EnvironmentCallbackContext) => Promise): Promise { + const callbackId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as EnvironmentCallbackContextHandle; + const arg = new EnvironmentCallbackContext(argHandle, this._client); + await callback(arg); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withEnvironmentCallbackAsync', + rpcArgs + ); + return new AzureStorageEmulatorResource(result, this._client); + } + + /** Sets environment variables via async callback */ + withEnvironmentCallbackAsync(callback: (arg: EnvironmentCallbackContext) => Promise): AzureStorageEmulatorResourcePromise { + return new AzureStorageEmulatorResourcePromise(this._withEnvironmentCallbackAsyncInternal(callback)); + } + + /** @internal */ + private async _withEnvironmentEndpointInternal(name: string, endpointReference: EndpointReference): Promise { + const rpcArgs: Record = { builder: this._handle, name, endpointReference }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withEnvironmentEndpoint', + rpcArgs + ); + return new AzureStorageEmulatorResource(result, this._client); + } + + /** Sets an environment variable from an endpoint reference */ + withEnvironmentEndpoint(name: string, endpointReference: EndpointReference): AzureStorageEmulatorResourcePromise { + return new AzureStorageEmulatorResourcePromise(this._withEnvironmentEndpointInternal(name, endpointReference)); + } + + /** @internal */ + private async _withEnvironmentParameterInternal(name: string, parameter: ParameterResource): Promise { + const rpcArgs: Record = { builder: this._handle, name, parameter }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withEnvironmentParameter', + rpcArgs + ); + return new AzureStorageEmulatorResource(result, this._client); + } + + /** Sets an environment variable from a parameter resource */ + withEnvironmentParameter(name: string, parameter: ParameterResource): AzureStorageEmulatorResourcePromise { + return new AzureStorageEmulatorResourcePromise(this._withEnvironmentParameterInternal(name, parameter)); + } + + /** @internal */ + private async _withEnvironmentConnectionStringInternal(envVarName: string, resource: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, envVarName, resource }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withEnvironmentConnectionString', + rpcArgs + ); + return new AzureStorageEmulatorResource(result, this._client); + } + + /** Sets an environment variable from a connection string resource */ + withEnvironmentConnectionString(envVarName: string, resource: ResourceBuilderBase): AzureStorageEmulatorResourcePromise { + return new AzureStorageEmulatorResourcePromise(this._withEnvironmentConnectionStringInternal(envVarName, resource)); + } + + /** @internal */ + private async _withArgsInternal(args: string[]): Promise { + const rpcArgs: Record = { builder: this._handle, args }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withArgs', + rpcArgs + ); + return new AzureStorageEmulatorResource(result, this._client); + } + + /** Adds arguments */ + withArgs(args: string[]): AzureStorageEmulatorResourcePromise { + return new AzureStorageEmulatorResourcePromise(this._withArgsInternal(args)); + } + + /** @internal */ + private async _withArgsCallbackInternal(callback: (obj: CommandLineArgsCallbackContext) => Promise): Promise { + const callbackId = registerCallback(async (objData: unknown) => { + const objHandle = wrapIfHandle(objData) as CommandLineArgsCallbackContextHandle; + const obj = new CommandLineArgsCallbackContext(objHandle, this._client); + await callback(obj); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withArgsCallback', + rpcArgs + ); + return new AzureStorageEmulatorResource(result, this._client); + } + + /** Sets command-line arguments via callback */ + withArgsCallback(callback: (obj: CommandLineArgsCallbackContext) => Promise): AzureStorageEmulatorResourcePromise { + return new AzureStorageEmulatorResourcePromise(this._withArgsCallbackInternal(callback)); + } + + /** @internal */ + private async _withArgsCallbackAsyncInternal(callback: (arg: CommandLineArgsCallbackContext) => Promise): Promise { + const callbackId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as CommandLineArgsCallbackContextHandle; + const arg = new CommandLineArgsCallbackContext(argHandle, this._client); + await callback(arg); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withArgsCallbackAsync', + rpcArgs + ); + return new AzureStorageEmulatorResource(result, this._client); + } + + /** Sets command-line arguments via async callback */ + withArgsCallbackAsync(callback: (arg: CommandLineArgsCallbackContext) => Promise): AzureStorageEmulatorResourcePromise { + return new AzureStorageEmulatorResourcePromise(this._withArgsCallbackAsyncInternal(callback)); + } + + /** @internal */ + private async _withReferenceInternal(source: ResourceBuilderBase, connectionName?: string, optional?: boolean): Promise { + const rpcArgs: Record = { builder: this._handle, source }; + if (connectionName !== undefined) rpcArgs.connectionName = connectionName; + if (optional !== undefined) rpcArgs.optional = optional; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withReference', + rpcArgs + ); + return new AzureStorageEmulatorResource(result, this._client); + } + + /** Adds a reference to another resource */ + withReference(source: ResourceBuilderBase, options?: WithReferenceOptions): AzureStorageEmulatorResourcePromise { + const connectionName = options?.connectionName; + const optional = options?.optional; + return new AzureStorageEmulatorResourcePromise(this._withReferenceInternal(source, connectionName, optional)); + } + + /** @internal */ + private async _withServiceReferenceInternal(source: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, source }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withServiceReference', + rpcArgs + ); + return new AzureStorageEmulatorResource(result, this._client); + } + + /** Adds a service discovery reference to another resource */ + withServiceReference(source: ResourceBuilderBase): AzureStorageEmulatorResourcePromise { + return new AzureStorageEmulatorResourcePromise(this._withServiceReferenceInternal(source)); + } + + /** @internal */ + private async _withServiceReferenceNamedInternal(source: ResourceBuilderBase, name: string): Promise { + const rpcArgs: Record = { builder: this._handle, source, name }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withServiceReferenceNamed', + rpcArgs + ); + return new AzureStorageEmulatorResource(result, this._client); + } + + /** Adds a named service discovery reference */ + withServiceReferenceNamed(source: ResourceBuilderBase, name: string): AzureStorageEmulatorResourcePromise { + return new AzureStorageEmulatorResourcePromise(this._withServiceReferenceNamedInternal(source, name)); + } + + /** @internal */ + private async _withReferenceUriInternal(name: string, uri: string): Promise { + const rpcArgs: Record = { builder: this._handle, name, uri }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withReferenceUri', + rpcArgs + ); + return new AzureStorageEmulatorResource(result, this._client); + } + + /** Adds a reference to a URI */ + withReferenceUri(name: string, uri: string): AzureStorageEmulatorResourcePromise { + return new AzureStorageEmulatorResourcePromise(this._withReferenceUriInternal(name, uri)); + } + + /** @internal */ + private async _withReferenceExternalServiceInternal(externalService: ExternalServiceResource): Promise { + const rpcArgs: Record = { builder: this._handle, externalService }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withReferenceExternalService', + rpcArgs + ); + return new AzureStorageEmulatorResource(result, this._client); + } + + /** Adds a reference to an external service */ + withReferenceExternalService(externalService: ExternalServiceResource): AzureStorageEmulatorResourcePromise { + return new AzureStorageEmulatorResourcePromise(this._withReferenceExternalServiceInternal(externalService)); + } + + /** @internal */ + private async _withReferenceEndpointInternal(endpointReference: EndpointReference): Promise { + const rpcArgs: Record = { builder: this._handle, endpointReference }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withReferenceEndpoint', + rpcArgs + ); + return new AzureStorageEmulatorResource(result, this._client); + } + + /** Adds a reference to an endpoint */ + withReferenceEndpoint(endpointReference: EndpointReference): AzureStorageEmulatorResourcePromise { + return new AzureStorageEmulatorResourcePromise(this._withReferenceEndpointInternal(endpointReference)); + } + + /** @internal */ + private async _withEndpointInternal(port?: number, targetPort?: number, scheme?: string, name?: string, env?: string, isProxied?: boolean, isExternal?: boolean, protocol?: ProtocolType): Promise { + const rpcArgs: Record = { builder: this._handle }; + if (port !== undefined) rpcArgs.port = port; + if (targetPort !== undefined) rpcArgs.targetPort = targetPort; + if (scheme !== undefined) rpcArgs.scheme = scheme; + if (name !== undefined) rpcArgs.name = name; + if (env !== undefined) rpcArgs.env = env; + if (isProxied !== undefined) rpcArgs.isProxied = isProxied; + if (isExternal !== undefined) rpcArgs.isExternal = isExternal; + if (protocol !== undefined) rpcArgs.protocol = protocol; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withEndpoint', + rpcArgs + ); + return new AzureStorageEmulatorResource(result, this._client); + } + + /** Adds a network endpoint */ + withEndpoint(options?: WithEndpointOptions): AzureStorageEmulatorResourcePromise { + const port = options?.port; + const targetPort = options?.targetPort; + const scheme = options?.scheme; + const name = options?.name; + const env = options?.env; + const isProxied = options?.isProxied; + const isExternal = options?.isExternal; + const protocol = options?.protocol; + return new AzureStorageEmulatorResourcePromise(this._withEndpointInternal(port, targetPort, scheme, name, env, isProxied, isExternal, protocol)); + } + + /** @internal */ + private async _withHttpEndpointInternal(port?: number, targetPort?: number, name?: string, env?: string, isProxied?: boolean): Promise { + const rpcArgs: Record = { builder: this._handle }; + if (port !== undefined) rpcArgs.port = port; + if (targetPort !== undefined) rpcArgs.targetPort = targetPort; + if (name !== undefined) rpcArgs.name = name; + if (env !== undefined) rpcArgs.env = env; + if (isProxied !== undefined) rpcArgs.isProxied = isProxied; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withHttpEndpoint', + rpcArgs + ); + return new AzureStorageEmulatorResource(result, this._client); + } + + /** Adds an HTTP endpoint */ + withHttpEndpoint(options?: WithHttpEndpointOptions): AzureStorageEmulatorResourcePromise { + const port = options?.port; + const targetPort = options?.targetPort; + const name = options?.name; + const env = options?.env; + const isProxied = options?.isProxied; + return new AzureStorageEmulatorResourcePromise(this._withHttpEndpointInternal(port, targetPort, name, env, isProxied)); + } + + /** @internal */ + private async _withHttpsEndpointInternal(port?: number, targetPort?: number, name?: string, env?: string, isProxied?: boolean): Promise { + const rpcArgs: Record = { builder: this._handle }; + if (port !== undefined) rpcArgs.port = port; + if (targetPort !== undefined) rpcArgs.targetPort = targetPort; + if (name !== undefined) rpcArgs.name = name; + if (env !== undefined) rpcArgs.env = env; + if (isProxied !== undefined) rpcArgs.isProxied = isProxied; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withHttpsEndpoint', + rpcArgs + ); + return new AzureStorageEmulatorResource(result, this._client); + } + + /** Adds an HTTPS endpoint */ + withHttpsEndpoint(options?: WithHttpsEndpointOptions): AzureStorageEmulatorResourcePromise { + const port = options?.port; + const targetPort = options?.targetPort; + const name = options?.name; + const env = options?.env; + const isProxied = options?.isProxied; + return new AzureStorageEmulatorResourcePromise(this._withHttpsEndpointInternal(port, targetPort, name, env, isProxied)); + } + + /** @internal */ + private async _withExternalHttpEndpointsInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withExternalHttpEndpoints', + rpcArgs + ); + return new AzureStorageEmulatorResource(result, this._client); + } + + /** Makes HTTP endpoints externally accessible */ + withExternalHttpEndpoints(): AzureStorageEmulatorResourcePromise { + return new AzureStorageEmulatorResourcePromise(this._withExternalHttpEndpointsInternal()); + } + + /** Gets an endpoint reference */ + async getEndpoint(name: string): Promise { + const rpcArgs: Record = { builder: this._handle, name }; + return await this._client.invokeCapability( + 'Aspire.Hosting/getEndpoint', + rpcArgs + ); + } + + /** @internal */ + private async _asHttp2ServiceInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/asHttp2Service', + rpcArgs + ); + return new AzureStorageEmulatorResource(result, this._client); + } + + /** Configures resource for HTTP/2 */ + asHttp2Service(): AzureStorageEmulatorResourcePromise { + return new AzureStorageEmulatorResourcePromise(this._asHttp2ServiceInternal()); + } + + /** @internal */ + private async _withUrlsCallbackInternal(callback: (obj: ResourceUrlsCallbackContext) => Promise): Promise { + const callbackId = registerCallback(async (objData: unknown) => { + const objHandle = wrapIfHandle(objData) as ResourceUrlsCallbackContextHandle; + const obj = new ResourceUrlsCallbackContext(objHandle, this._client); + await callback(obj); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrlsCallback', + rpcArgs + ); + return new AzureStorageEmulatorResource(result, this._client); + } + + /** Customizes displayed URLs via callback */ + withUrlsCallback(callback: (obj: ResourceUrlsCallbackContext) => Promise): AzureStorageEmulatorResourcePromise { + return new AzureStorageEmulatorResourcePromise(this._withUrlsCallbackInternal(callback)); + } + + /** @internal */ + private async _withUrlsCallbackAsyncInternal(callback: (arg: ResourceUrlsCallbackContext) => Promise): Promise { + const callbackId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as ResourceUrlsCallbackContextHandle; + const arg = new ResourceUrlsCallbackContext(argHandle, this._client); + await callback(arg); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrlsCallbackAsync', + rpcArgs + ); + return new AzureStorageEmulatorResource(result, this._client); + } + + /** Customizes displayed URLs via async callback */ + withUrlsCallbackAsync(callback: (arg: ResourceUrlsCallbackContext) => Promise): AzureStorageEmulatorResourcePromise { + return new AzureStorageEmulatorResourcePromise(this._withUrlsCallbackAsyncInternal(callback)); + } + + /** @internal */ + private async _withUrlInternal(url: string, displayText?: string): Promise { + const rpcArgs: Record = { builder: this._handle, url }; + if (displayText !== undefined) rpcArgs.displayText = displayText; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrl', + rpcArgs + ); + return new AzureStorageEmulatorResource(result, this._client); + } + + /** Adds or modifies displayed URLs */ + withUrl(url: string, options?: WithUrlOptions): AzureStorageEmulatorResourcePromise { + const displayText = options?.displayText; + return new AzureStorageEmulatorResourcePromise(this._withUrlInternal(url, displayText)); + } + + /** @internal */ + private async _withUrlExpressionInternal(url: ReferenceExpression, displayText?: string): Promise { + const rpcArgs: Record = { builder: this._handle, url }; + if (displayText !== undefined) rpcArgs.displayText = displayText; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrlExpression', + rpcArgs + ); + return new AzureStorageEmulatorResource(result, this._client); + } + + /** Adds a URL using a reference expression */ + withUrlExpression(url: ReferenceExpression, options?: WithUrlExpressionOptions): AzureStorageEmulatorResourcePromise { + const displayText = options?.displayText; + return new AzureStorageEmulatorResourcePromise(this._withUrlExpressionInternal(url, displayText)); + } + + /** @internal */ + private async _withUrlForEndpointInternal(endpointName: string, callback: (obj: ResourceUrlAnnotation) => Promise): Promise { + const callbackId = registerCallback(async (objData: unknown) => { + const obj = wrapIfHandle(objData) as ResourceUrlAnnotation; + await callback(obj); + }); + const rpcArgs: Record = { builder: this._handle, endpointName, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrlForEndpoint', + rpcArgs + ); + return new AzureStorageEmulatorResource(result, this._client); + } + + /** Customizes the URL for a specific endpoint via callback */ + withUrlForEndpoint(endpointName: string, callback: (obj: ResourceUrlAnnotation) => Promise): AzureStorageEmulatorResourcePromise { + return new AzureStorageEmulatorResourcePromise(this._withUrlForEndpointInternal(endpointName, callback)); + } + + /** @internal */ + private async _withUrlForEndpointFactoryInternal(endpointName: string, callback: (arg: EndpointReference) => Promise): Promise { + const callbackId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as EndpointReferenceHandle; + const arg = new EndpointReference(argHandle, this._client); + return await callback(arg); + }); + const rpcArgs: Record = { builder: this._handle, endpointName, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrlForEndpointFactory', + rpcArgs + ); + return new AzureStorageEmulatorResource(result, this._client); + } + + /** Adds a URL for a specific endpoint via factory callback */ + withUrlForEndpointFactory(endpointName: string, callback: (arg: EndpointReference) => Promise): AzureStorageEmulatorResourcePromise { + return new AzureStorageEmulatorResourcePromise(this._withUrlForEndpointFactoryInternal(endpointName, callback)); + } + + /** @internal */ + private async _excludeFromManifestInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/excludeFromManifest', + rpcArgs + ); + return new AzureStorageEmulatorResource(result, this._client); + } + + /** Excludes the resource from the deployment manifest */ + excludeFromManifest(): AzureStorageEmulatorResourcePromise { + return new AzureStorageEmulatorResourcePromise(this._excludeFromManifestInternal()); + } + + /** @internal */ + private async _waitForInternal(dependency: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, dependency }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/waitFor', + rpcArgs + ); + return new AzureStorageEmulatorResource(result, this._client); + } + + /** Waits for another resource to be ready */ + waitFor(dependency: ResourceBuilderBase): AzureStorageEmulatorResourcePromise { + return new AzureStorageEmulatorResourcePromise(this._waitForInternal(dependency)); + } + + /** @internal */ + private async _waitForWithBehaviorInternal(dependency: ResourceBuilderBase, waitBehavior: WaitBehavior): Promise { + const rpcArgs: Record = { builder: this._handle, dependency, waitBehavior }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/waitForWithBehavior', + rpcArgs + ); + return new AzureStorageEmulatorResource(result, this._client); + } + + /** Waits for another resource with specific behavior */ + waitForWithBehavior(dependency: ResourceBuilderBase, waitBehavior: WaitBehavior): AzureStorageEmulatorResourcePromise { + return new AzureStorageEmulatorResourcePromise(this._waitForWithBehaviorInternal(dependency, waitBehavior)); + } + + /** @internal */ + private async _waitForStartInternal(dependency: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, dependency }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/waitForStart', + rpcArgs + ); + return new AzureStorageEmulatorResource(result, this._client); + } + + /** Waits for another resource to start */ + waitForStart(dependency: ResourceBuilderBase): AzureStorageEmulatorResourcePromise { + return new AzureStorageEmulatorResourcePromise(this._waitForStartInternal(dependency)); + } + + /** @internal */ + private async _waitForStartWithBehaviorInternal(dependency: ResourceBuilderBase, waitBehavior: WaitBehavior): Promise { + const rpcArgs: Record = { builder: this._handle, dependency, waitBehavior }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/waitForStartWithBehavior', + rpcArgs + ); + return new AzureStorageEmulatorResource(result, this._client); + } + + /** Waits for another resource to start with specific behavior */ + waitForStartWithBehavior(dependency: ResourceBuilderBase, waitBehavior: WaitBehavior): AzureStorageEmulatorResourcePromise { + return new AzureStorageEmulatorResourcePromise(this._waitForStartWithBehaviorInternal(dependency, waitBehavior)); + } + + /** @internal */ + private async _withExplicitStartInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withExplicitStart', + rpcArgs + ); + return new AzureStorageEmulatorResource(result, this._client); + } + + /** Prevents resource from starting automatically */ + withExplicitStart(): AzureStorageEmulatorResourcePromise { + return new AzureStorageEmulatorResourcePromise(this._withExplicitStartInternal()); + } + + /** @internal */ + private async _waitForCompletionInternal(dependency: ResourceBuilderBase, exitCode?: number): Promise { + const rpcArgs: Record = { builder: this._handle, dependency }; + if (exitCode !== undefined) rpcArgs.exitCode = exitCode; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/waitForCompletion', + rpcArgs + ); + return new AzureStorageEmulatorResource(result, this._client); + } + + /** Waits for resource completion */ + waitForCompletion(dependency: ResourceBuilderBase, options?: WaitForCompletionOptions): AzureStorageEmulatorResourcePromise { + const exitCode = options?.exitCode; + return new AzureStorageEmulatorResourcePromise(this._waitForCompletionInternal(dependency, exitCode)); + } + + /** @internal */ + private async _withHealthCheckInternal(key: string): Promise { + const rpcArgs: Record = { builder: this._handle, key }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withHealthCheck', + rpcArgs + ); + return new AzureStorageEmulatorResource(result, this._client); + } + + /** Adds a health check by key */ + withHealthCheck(key: string): AzureStorageEmulatorResourcePromise { + return new AzureStorageEmulatorResourcePromise(this._withHealthCheckInternal(key)); + } + + /** @internal */ + private async _withHttpHealthCheckInternal(path?: string, statusCode?: number, endpointName?: string): Promise { + const rpcArgs: Record = { builder: this._handle }; + if (path !== undefined) rpcArgs.path = path; + if (statusCode !== undefined) rpcArgs.statusCode = statusCode; + if (endpointName !== undefined) rpcArgs.endpointName = endpointName; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withHttpHealthCheck', + rpcArgs + ); + return new AzureStorageEmulatorResource(result, this._client); + } + + /** Adds an HTTP health check */ + withHttpHealthCheck(options?: WithHttpHealthCheckOptions): AzureStorageEmulatorResourcePromise { + const path = options?.path; + const statusCode = options?.statusCode; + const endpointName = options?.endpointName; + return new AzureStorageEmulatorResourcePromise(this._withHttpHealthCheckInternal(path, statusCode, endpointName)); + } + + /** @internal */ + private async _withCommandInternal(name: string, displayName: string, executeCommand: (arg: ExecuteCommandContext) => Promise, commandOptions?: CommandOptions): Promise { + const executeCommandId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as ExecuteCommandContextHandle; + const arg = new ExecuteCommandContext(argHandle, this._client); + return await executeCommand(arg); + }); + const rpcArgs: Record = { builder: this._handle, name, displayName, executeCommand: executeCommandId }; + if (commandOptions !== undefined) rpcArgs.commandOptions = commandOptions; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withCommand', + rpcArgs + ); + return new AzureStorageEmulatorResource(result, this._client); + } + + /** Adds a resource command */ + withCommand(name: string, displayName: string, executeCommand: (arg: ExecuteCommandContext) => Promise, options?: WithCommandOptions): AzureStorageEmulatorResourcePromise { + const commandOptions = options?.commandOptions; + return new AzureStorageEmulatorResourcePromise(this._withCommandInternal(name, displayName, executeCommand, commandOptions)); + } + + /** @internal */ + private async _withDeveloperCertificateTrustInternal(trust: boolean): Promise { + const rpcArgs: Record = { builder: this._handle, trust }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withDeveloperCertificateTrust', + rpcArgs + ); + return new AzureStorageEmulatorResource(result, this._client); + } + + /** Configures developer certificate trust */ + withDeveloperCertificateTrust(trust: boolean): AzureStorageEmulatorResourcePromise { + return new AzureStorageEmulatorResourcePromise(this._withDeveloperCertificateTrustInternal(trust)); + } + + /** @internal */ + private async _withCertificateTrustScopeInternal(scope: CertificateTrustScope): Promise { + const rpcArgs: Record = { builder: this._handle, scope }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withCertificateTrustScope', + rpcArgs + ); + return new AzureStorageEmulatorResource(result, this._client); + } + + /** Sets the certificate trust scope */ + withCertificateTrustScope(scope: CertificateTrustScope): AzureStorageEmulatorResourcePromise { + return new AzureStorageEmulatorResourcePromise(this._withCertificateTrustScopeInternal(scope)); + } + + /** @internal */ + private async _withHttpsDeveloperCertificateInternal(password?: ParameterResource): Promise { + const rpcArgs: Record = { builder: this._handle }; + if (password !== undefined) rpcArgs.password = password; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withHttpsDeveloperCertificate', + rpcArgs + ); + return new AzureStorageEmulatorResource(result, this._client); + } + + /** Configures HTTPS with a developer certificate */ + withHttpsDeveloperCertificate(options?: WithHttpsDeveloperCertificateOptions): AzureStorageEmulatorResourcePromise { + const password = options?.password; + return new AzureStorageEmulatorResourcePromise(this._withHttpsDeveloperCertificateInternal(password)); + } + + /** @internal */ + private async _withoutHttpsCertificateInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withoutHttpsCertificate', + rpcArgs + ); + return new AzureStorageEmulatorResource(result, this._client); + } + + /** Removes HTTPS certificate configuration */ + withoutHttpsCertificate(): AzureStorageEmulatorResourcePromise { + return new AzureStorageEmulatorResourcePromise(this._withoutHttpsCertificateInternal()); + } + + /** @internal */ + private async _withParentRelationshipInternal(parent: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, parent }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withParentRelationship', + rpcArgs + ); + return new AzureStorageEmulatorResource(result, this._client); + } + + /** Sets the parent relationship */ + withParentRelationship(parent: ResourceBuilderBase): AzureStorageEmulatorResourcePromise { + return new AzureStorageEmulatorResourcePromise(this._withParentRelationshipInternal(parent)); + } + + /** @internal */ + private async _withChildRelationshipInternal(child: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, child }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withChildRelationship', + rpcArgs + ); + return new AzureStorageEmulatorResource(result, this._client); + } + + /** Sets a child relationship */ + withChildRelationship(child: ResourceBuilderBase): AzureStorageEmulatorResourcePromise { + return new AzureStorageEmulatorResourcePromise(this._withChildRelationshipInternal(child)); + } + + /** @internal */ + private async _withIconNameInternal(iconName: string, iconVariant?: IconVariant): Promise { + const rpcArgs: Record = { builder: this._handle, iconName }; + if (iconVariant !== undefined) rpcArgs.iconVariant = iconVariant; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withIconName', + rpcArgs + ); + return new AzureStorageEmulatorResource(result, this._client); + } + + /** Sets the icon for the resource */ + withIconName(iconName: string, options?: WithIconNameOptions): AzureStorageEmulatorResourcePromise { + const iconVariant = options?.iconVariant; + return new AzureStorageEmulatorResourcePromise(this._withIconNameInternal(iconName, iconVariant)); + } + + /** @internal */ + private async _withHttpProbeInternal(probeType: ProbeType, path?: string, initialDelaySeconds?: number, periodSeconds?: number, timeoutSeconds?: number, failureThreshold?: number, successThreshold?: number, endpointName?: string): Promise { + const rpcArgs: Record = { builder: this._handle, probeType }; + if (path !== undefined) rpcArgs.path = path; + if (initialDelaySeconds !== undefined) rpcArgs.initialDelaySeconds = initialDelaySeconds; + if (periodSeconds !== undefined) rpcArgs.periodSeconds = periodSeconds; + if (timeoutSeconds !== undefined) rpcArgs.timeoutSeconds = timeoutSeconds; + if (failureThreshold !== undefined) rpcArgs.failureThreshold = failureThreshold; + if (successThreshold !== undefined) rpcArgs.successThreshold = successThreshold; + if (endpointName !== undefined) rpcArgs.endpointName = endpointName; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withHttpProbe', + rpcArgs + ); + return new AzureStorageEmulatorResource(result, this._client); + } + + /** Adds an HTTP health probe to the resource */ + withHttpProbe(probeType: ProbeType, options?: WithHttpProbeOptions): AzureStorageEmulatorResourcePromise { + const path = options?.path; + const initialDelaySeconds = options?.initialDelaySeconds; + const periodSeconds = options?.periodSeconds; + const timeoutSeconds = options?.timeoutSeconds; + const failureThreshold = options?.failureThreshold; + const successThreshold = options?.successThreshold; + const endpointName = options?.endpointName; + return new AzureStorageEmulatorResourcePromise(this._withHttpProbeInternal(probeType, path, initialDelaySeconds, periodSeconds, timeoutSeconds, failureThreshold, successThreshold, endpointName)); + } + + /** @internal */ + private async _excludeFromMcpInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/excludeFromMcp', + rpcArgs + ); + return new AzureStorageEmulatorResource(result, this._client); + } + + /** Excludes the resource from MCP server exposure */ + excludeFromMcp(): AzureStorageEmulatorResourcePromise { + return new AzureStorageEmulatorResourcePromise(this._excludeFromMcpInternal()); + } + + /** @internal */ + private async _withRemoteImageNameInternal(remoteImageName: string): Promise { + const rpcArgs: Record = { builder: this._handle, remoteImageName }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withRemoteImageName', + rpcArgs + ); + return new AzureStorageEmulatorResource(result, this._client); + } + + /** Sets the remote image name for publishing */ + withRemoteImageName(remoteImageName: string): AzureStorageEmulatorResourcePromise { + return new AzureStorageEmulatorResourcePromise(this._withRemoteImageNameInternal(remoteImageName)); + } + + /** @internal */ + private async _withRemoteImageTagInternal(remoteImageTag: string): Promise { + const rpcArgs: Record = { builder: this._handle, remoteImageTag }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withRemoteImageTag', + rpcArgs + ); + return new AzureStorageEmulatorResource(result, this._client); + } + + /** Sets the remote image tag for publishing */ + withRemoteImageTag(remoteImageTag: string): AzureStorageEmulatorResourcePromise { + return new AzureStorageEmulatorResourcePromise(this._withRemoteImageTagInternal(remoteImageTag)); + } + + /** @internal */ + private async _withPipelineStepFactoryInternal(stepName: string, callback: (arg: PipelineStepContext) => Promise, dependsOn?: string[], requiredBy?: string[], tags?: string[], description?: string): Promise { + const callbackId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as PipelineStepContextHandle; + const arg = new PipelineStepContext(argHandle, this._client); + await callback(arg); + }); + const rpcArgs: Record = { builder: this._handle, stepName, callback: callbackId }; + if (dependsOn !== undefined) rpcArgs.dependsOn = dependsOn; + if (requiredBy !== undefined) rpcArgs.requiredBy = requiredBy; + if (tags !== undefined) rpcArgs.tags = tags; + if (description !== undefined) rpcArgs.description = description; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withPipelineStepFactory', + rpcArgs + ); + return new AzureStorageEmulatorResource(result, this._client); + } + + /** Adds a pipeline step to the resource */ + withPipelineStepFactory(stepName: string, callback: (arg: PipelineStepContext) => Promise, options?: WithPipelineStepFactoryOptions): AzureStorageEmulatorResourcePromise { + const dependsOn = options?.dependsOn; + const requiredBy = options?.requiredBy; + const tags = options?.tags; + const description = options?.description; + return new AzureStorageEmulatorResourcePromise(this._withPipelineStepFactoryInternal(stepName, callback, dependsOn, requiredBy, tags, description)); + } + + /** @internal */ + private async _withPipelineConfigurationAsyncInternal(callback: (arg: PipelineConfigurationContext) => Promise): Promise { + const callbackId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as PipelineConfigurationContextHandle; + const arg = new PipelineConfigurationContext(argHandle, this._client); + await callback(arg); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withPipelineConfigurationAsync', + rpcArgs + ); + return new AzureStorageEmulatorResource(result, this._client); + } + + /** Configures pipeline step dependencies via an async callback */ + withPipelineConfigurationAsync(callback: (arg: PipelineConfigurationContext) => Promise): AzureStorageEmulatorResourcePromise { + return new AzureStorageEmulatorResourcePromise(this._withPipelineConfigurationAsyncInternal(callback)); + } + + /** @internal */ + private async _withPipelineConfigurationInternal(callback: (obj: PipelineConfigurationContext) => Promise): Promise { + const callbackId = registerCallback(async (objData: unknown) => { + const objHandle = wrapIfHandle(objData) as PipelineConfigurationContextHandle; + const obj = new PipelineConfigurationContext(objHandle, this._client); + await callback(obj); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withPipelineConfiguration', + rpcArgs + ); + return new AzureStorageEmulatorResource(result, this._client); + } + + /** Configures pipeline step dependencies via a callback */ + withPipelineConfiguration(callback: (obj: PipelineConfigurationContext) => Promise): AzureStorageEmulatorResourcePromise { + return new AzureStorageEmulatorResourcePromise(this._withPipelineConfigurationInternal(callback)); + } + + /** @internal */ + private async _withVolumeInternal(target: string, name?: string, isReadOnly?: boolean): Promise { + const rpcArgs: Record = { resource: this._handle, target }; + if (name !== undefined) rpcArgs.name = name; + if (isReadOnly !== undefined) rpcArgs.isReadOnly = isReadOnly; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withVolume', + rpcArgs + ); + return new AzureStorageEmulatorResource(result, this._client); + } + + /** Adds a volume */ + withVolume(target: string, options?: WithVolumeOptions): AzureStorageEmulatorResourcePromise { + const name = options?.name; + const isReadOnly = options?.isReadOnly; + return new AzureStorageEmulatorResourcePromise(this._withVolumeInternal(target, name, isReadOnly)); + } + + /** Gets the resource name */ + async getResourceName(): Promise { + const rpcArgs: Record = { resource: this._handle }; + return await this._client.invokeCapability( + 'Aspire.Hosting/getResourceName', + rpcArgs + ); + } + + /** @internal */ + private async _withDataBindMountInternal(path?: string, isReadOnly?: boolean): Promise { + const rpcArgs: Record = { builder: this._handle }; + if (path !== undefined) rpcArgs.path = path; + if (isReadOnly !== undefined) rpcArgs.isReadOnly = isReadOnly; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure.Storage/withDataBindMount', + rpcArgs + ); + return new AzureStorageEmulatorResource(result, this._client); + } + + /** Adds a bind mount for the data folder to an Azure Storage emulator resource */ + withDataBindMount(options?: WithDataBindMountOptions): AzureStorageEmulatorResourcePromise { + const path = options?.path; + const isReadOnly = options?.isReadOnly; + return new AzureStorageEmulatorResourcePromise(this._withDataBindMountInternal(path, isReadOnly)); + } + + /** @internal */ + private async _withDataVolumeInternal(name?: string, isReadOnly?: boolean): Promise { + const rpcArgs: Record = { builder: this._handle }; + if (name !== undefined) rpcArgs.name = name; + if (isReadOnly !== undefined) rpcArgs.isReadOnly = isReadOnly; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure.Storage/withDataVolume', + rpcArgs + ); + return new AzureStorageEmulatorResource(result, this._client); + } + + /** Adds a named volume for the data folder to an Azure Storage emulator resource */ + withDataVolume(options?: WithDataVolumeOptions): AzureStorageEmulatorResourcePromise { + const name = options?.name; + const isReadOnly = options?.isReadOnly; + return new AzureStorageEmulatorResourcePromise(this._withDataVolumeInternal(name, isReadOnly)); + } + + /** @internal */ + private async _withBlobPortInternal(port: number): Promise { + const rpcArgs: Record = { builder: this._handle, port }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure.Storage/withBlobPort', + rpcArgs + ); + return new AzureStorageEmulatorResource(result, this._client); + } + + /** Sets the host port for blob requests on the storage emulator */ + withBlobPort(port: number): AzureStorageEmulatorResourcePromise { + return new AzureStorageEmulatorResourcePromise(this._withBlobPortInternal(port)); + } + + /** @internal */ + private async _withQueuePortInternal(port: number): Promise { + const rpcArgs: Record = { builder: this._handle, port }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure.Storage/withQueuePort', + rpcArgs + ); + return new AzureStorageEmulatorResource(result, this._client); + } + + /** Sets the host port for queue requests on the storage emulator */ + withQueuePort(port: number): AzureStorageEmulatorResourcePromise { + return new AzureStorageEmulatorResourcePromise(this._withQueuePortInternal(port)); + } + + /** @internal */ + private async _withTablePortInternal(port: number): Promise { + const rpcArgs: Record = { builder: this._handle, port }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure.Storage/withTablePort', + rpcArgs + ); + return new AzureStorageEmulatorResource(result, this._client); + } + + /** Sets the host port for table requests on the storage emulator */ + withTablePort(port: number): AzureStorageEmulatorResourcePromise { + return new AzureStorageEmulatorResourcePromise(this._withTablePortInternal(port)); + } + + /** @internal */ + private async _withApiVersionCheckInternal(enable?: boolean): Promise { + const rpcArgs: Record = { builder: this._handle }; + if (enable !== undefined) rpcArgs.enable = enable; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure.Storage/withApiVersionCheck', + rpcArgs + ); + return new AzureStorageEmulatorResource(result, this._client); + } + + /** Configures whether the emulator checks API version validity */ + withApiVersionCheck(options?: WithApiVersionCheckOptions): AzureStorageEmulatorResourcePromise { + const enable = options?.enable; + return new AzureStorageEmulatorResourcePromise(this._withApiVersionCheckInternal(enable)); + } + + /** @internal */ + private async _withStorageRoleAssignmentsInternal(target: AzureStorageResource, roles: AzureStorageRole[]): Promise { + const rpcArgs: Record = { builder: this._handle, target, roles }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure.Storage/withStorageRoleAssignments', + rpcArgs + ); + return new AzureStorageEmulatorResource(result, this._client); + } + + /** Assigns Azure Storage roles to a resource */ + withStorageRoleAssignments(target: AzureStorageResource, roles: AzureStorageRole[]): AzureStorageEmulatorResourcePromise { + return new AzureStorageEmulatorResourcePromise(this._withStorageRoleAssignmentsInternal(target, roles)); + } + + /** @internal */ + private async _withEventHubsRoleAssignmentsInternal(target: AzureEventHubsResource, roles: AzureEventHubsRole[]): Promise { + const rpcArgs: Record = { builder: this._handle, target, roles }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure.EventHubs/withEventHubsRoleAssignments', + rpcArgs + ); + return new AzureStorageEmulatorResource(result, this._client); + } + + /** Assigns Event Hubs roles to a resource */ + withEventHubsRoleAssignments(target: AzureEventHubsResource, roles: AzureEventHubsRole[]): AzureStorageEmulatorResourcePromise { + return new AzureStorageEmulatorResourcePromise(this._withEventHubsRoleAssignmentsInternal(target, roles)); + } + + /** @internal */ + private async _withEnvironmentFromOutputInternal(name: string, bicepOutputReference: BicepOutputReference): Promise { + const rpcArgs: Record = { builder: this._handle, name, bicepOutputReference }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure/withEnvironmentFromOutput', + rpcArgs + ); + return new AzureStorageEmulatorResource(result, this._client); + } + + /** Sets an environment variable from a Bicep output reference */ + withEnvironmentFromOutput(name: string, bicepOutputReference: BicepOutputReference): AzureStorageEmulatorResourcePromise { + return new AzureStorageEmulatorResourcePromise(this._withEnvironmentFromOutputInternal(name, bicepOutputReference)); + } + + /** @internal */ + private async _withEnvironmentFromKeyVaultSecretInternal(name: string, secretReference: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, name, secretReference }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure/withEnvironmentFromKeyVaultSecret', + rpcArgs + ); + return new AzureStorageEmulatorResource(result, this._client); + } + + /** Sets an environment variable from an Azure Key Vault secret reference */ + withEnvironmentFromKeyVaultSecret(name: string, secretReference: ResourceBuilderBase): AzureStorageEmulatorResourcePromise { + return new AzureStorageEmulatorResourcePromise(this._withEnvironmentFromKeyVaultSecretInternal(name, secretReference)); + } + + /** @internal */ + private async _withAzureUserAssignedIdentityInternal(identityResourceBuilder: AzureUserAssignedIdentityResource): Promise { + const rpcArgs: Record = { builder: this._handle, identityResourceBuilder }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure/withUserAssignedIdentityAzureUserAssignedIdentity', + rpcArgs + ); + return new AzureStorageEmulatorResource(result, this._client); + } + + /** Associates an Azure user-assigned identity with a compute resource */ + withAzureUserAssignedIdentity(identityResourceBuilder: AzureUserAssignedIdentityResource): AzureStorageEmulatorResourcePromise { + return new AzureStorageEmulatorResourcePromise(this._withAzureUserAssignedIdentityInternal(identityResourceBuilder)); + } + +} + +/** + * Thenable wrapper for AzureStorageEmulatorResource that enables fluent chaining. + * @example + * await builder.addSomething().withX().withY(); + */ +export class AzureStorageEmulatorResourcePromise implements PromiseLike { + constructor(private _promise: Promise) {} + + then( + onfulfilled?: ((value: AzureStorageEmulatorResource) => TResult1 | PromiseLike) | null, + onrejected?: ((reason: unknown) => TResult2 | PromiseLike) | null + ): PromiseLike { + return this._promise.then(onfulfilled, onrejected); + } + + /** Configures a resource to use a container registry */ + withContainerRegistry(registry: ResourceBuilderBase): AzureStorageEmulatorResourcePromise { + return new AzureStorageEmulatorResourcePromise(this._promise.then(obj => obj.withContainerRegistry(registry))); + } + + /** Adds a bind mount */ + withBindMount(source: string, target: string, options?: WithBindMountOptions): AzureStorageEmulatorResourcePromise { + return new AzureStorageEmulatorResourcePromise(this._promise.then(obj => obj.withBindMount(source, target, options))); + } + + /** Sets the container entrypoint */ + withEntrypoint(entrypoint: string): AzureStorageEmulatorResourcePromise { + return new AzureStorageEmulatorResourcePromise(this._promise.then(obj => obj.withEntrypoint(entrypoint))); + } + + /** Sets the container image tag */ + withImageTag(tag: string): AzureStorageEmulatorResourcePromise { + return new AzureStorageEmulatorResourcePromise(this._promise.then(obj => obj.withImageTag(tag))); + } + + /** Sets the container image registry */ + withImageRegistry(registry: string): AzureStorageEmulatorResourcePromise { + return new AzureStorageEmulatorResourcePromise(this._promise.then(obj => obj.withImageRegistry(registry))); + } + + /** Sets the container image */ + withImage(image: string, options?: WithImageOptions): AzureStorageEmulatorResourcePromise { + return new AzureStorageEmulatorResourcePromise(this._promise.then(obj => obj.withImage(image, options))); + } + + /** Sets the image SHA256 digest */ + withImageSHA256(sha256: string): AzureStorageEmulatorResourcePromise { + return new AzureStorageEmulatorResourcePromise(this._promise.then(obj => obj.withImageSHA256(sha256))); + } + + /** Adds runtime arguments for the container */ + withContainerRuntimeArgs(args: string[]): AzureStorageEmulatorResourcePromise { + return new AzureStorageEmulatorResourcePromise(this._promise.then(obj => obj.withContainerRuntimeArgs(args))); + } + + /** Sets the lifetime behavior of the container resource */ + withLifetime(lifetime: ContainerLifetime): AzureStorageEmulatorResourcePromise { + return new AzureStorageEmulatorResourcePromise(this._promise.then(obj => obj.withLifetime(lifetime))); + } + + /** Sets the container image pull policy */ + withImagePullPolicy(pullPolicy: ImagePullPolicy): AzureStorageEmulatorResourcePromise { + return new AzureStorageEmulatorResourcePromise(this._promise.then(obj => obj.withImagePullPolicy(pullPolicy))); + } + + /** Configures the resource to be published as a container */ + publishAsContainer(): AzureStorageEmulatorResourcePromise { + return new AzureStorageEmulatorResourcePromise(this._promise.then(obj => obj.publishAsContainer())); + } + + /** Configures the resource to use a Dockerfile */ + withDockerfile(contextPath: string, options?: WithDockerfileOptions): AzureStorageEmulatorResourcePromise { + return new AzureStorageEmulatorResourcePromise(this._promise.then(obj => obj.withDockerfile(contextPath, options))); + } + + /** Sets the container name */ + withContainerName(name: string): AzureStorageEmulatorResourcePromise { + return new AzureStorageEmulatorResourcePromise(this._promise.then(obj => obj.withContainerName(name))); + } + + /** Adds a build argument from a parameter resource */ + withBuildArg(name: string, value: ParameterResource): AzureStorageEmulatorResourcePromise { + return new AzureStorageEmulatorResourcePromise(this._promise.then(obj => obj.withBuildArg(name, value))); + } + + /** Adds a build secret from a parameter resource */ + withBuildSecret(name: string, value: ParameterResource): AzureStorageEmulatorResourcePromise { + return new AzureStorageEmulatorResourcePromise(this._promise.then(obj => obj.withBuildSecret(name, value))); + } + + /** Configures endpoint proxy support */ + withEndpointProxySupport(proxyEnabled: boolean): AzureStorageEmulatorResourcePromise { + return new AzureStorageEmulatorResourcePromise(this._promise.then(obj => obj.withEndpointProxySupport(proxyEnabled))); + } + + /** Sets the base image for a Dockerfile build */ + withDockerfileBaseImage(options?: WithDockerfileBaseImageOptions): AzureStorageEmulatorResourcePromise { + return new AzureStorageEmulatorResourcePromise(this._promise.then(obj => obj.withDockerfileBaseImage(options))); + } + + /** Adds a network alias for the container */ + withContainerNetworkAlias(alias: string): AzureStorageEmulatorResourcePromise { + return new AzureStorageEmulatorResourcePromise(this._promise.then(obj => obj.withContainerNetworkAlias(alias))); + } + + /** Configures an MCP server endpoint on the resource */ + withMcpServer(options?: WithMcpServerOptions): AzureStorageEmulatorResourcePromise { + return new AzureStorageEmulatorResourcePromise(this._promise.then(obj => obj.withMcpServer(options))); + } + + /** Configures OTLP telemetry export */ + withOtlpExporter(): AzureStorageEmulatorResourcePromise { + return new AzureStorageEmulatorResourcePromise(this._promise.then(obj => obj.withOtlpExporter())); + } + + /** Configures OTLP telemetry export with specific protocol */ + withOtlpExporterProtocol(protocol: OtlpProtocol): AzureStorageEmulatorResourcePromise { + return new AzureStorageEmulatorResourcePromise(this._promise.then(obj => obj.withOtlpExporterProtocol(protocol))); + } + + /** Publishes the resource as a connection string */ + publishAsConnectionString(): AzureStorageEmulatorResourcePromise { + return new AzureStorageEmulatorResourcePromise(this._promise.then(obj => obj.publishAsConnectionString())); + } + + /** Adds a required command dependency */ + withRequiredCommand(command: string, options?: WithRequiredCommandOptions): AzureStorageEmulatorResourcePromise { + return new AzureStorageEmulatorResourcePromise(this._promise.then(obj => obj.withRequiredCommand(command, options))); + } + + /** Sets an environment variable */ + withEnvironment(name: string, value: string): AzureStorageEmulatorResourcePromise { + return new AzureStorageEmulatorResourcePromise(this._promise.then(obj => obj.withEnvironment(name, value))); + } + + /** Adds an environment variable with a reference expression */ + withEnvironmentExpression(name: string, value: ReferenceExpression): AzureStorageEmulatorResourcePromise { + return new AzureStorageEmulatorResourcePromise(this._promise.then(obj => obj.withEnvironmentExpression(name, value))); + } + + /** Sets environment variables via callback */ + withEnvironmentCallback(callback: (obj: EnvironmentCallbackContext) => Promise): AzureStorageEmulatorResourcePromise { + return new AzureStorageEmulatorResourcePromise(this._promise.then(obj => obj.withEnvironmentCallback(callback))); + } + + /** Sets environment variables via async callback */ + withEnvironmentCallbackAsync(callback: (arg: EnvironmentCallbackContext) => Promise): AzureStorageEmulatorResourcePromise { + return new AzureStorageEmulatorResourcePromise(this._promise.then(obj => obj.withEnvironmentCallbackAsync(callback))); + } + + /** Sets an environment variable from an endpoint reference */ + withEnvironmentEndpoint(name: string, endpointReference: EndpointReference): AzureStorageEmulatorResourcePromise { + return new AzureStorageEmulatorResourcePromise(this._promise.then(obj => obj.withEnvironmentEndpoint(name, endpointReference))); + } + + /** Sets an environment variable from a parameter resource */ + withEnvironmentParameter(name: string, parameter: ParameterResource): AzureStorageEmulatorResourcePromise { + return new AzureStorageEmulatorResourcePromise(this._promise.then(obj => obj.withEnvironmentParameter(name, parameter))); + } + + /** Sets an environment variable from a connection string resource */ + withEnvironmentConnectionString(envVarName: string, resource: ResourceBuilderBase): AzureStorageEmulatorResourcePromise { + return new AzureStorageEmulatorResourcePromise(this._promise.then(obj => obj.withEnvironmentConnectionString(envVarName, resource))); + } + + /** Adds arguments */ + withArgs(args: string[]): AzureStorageEmulatorResourcePromise { + return new AzureStorageEmulatorResourcePromise(this._promise.then(obj => obj.withArgs(args))); + } + + /** Sets command-line arguments via callback */ + withArgsCallback(callback: (obj: CommandLineArgsCallbackContext) => Promise): AzureStorageEmulatorResourcePromise { + return new AzureStorageEmulatorResourcePromise(this._promise.then(obj => obj.withArgsCallback(callback))); + } + + /** Sets command-line arguments via async callback */ + withArgsCallbackAsync(callback: (arg: CommandLineArgsCallbackContext) => Promise): AzureStorageEmulatorResourcePromise { + return new AzureStorageEmulatorResourcePromise(this._promise.then(obj => obj.withArgsCallbackAsync(callback))); + } + + /** Adds a reference to another resource */ + withReference(source: ResourceBuilderBase, options?: WithReferenceOptions): AzureStorageEmulatorResourcePromise { + return new AzureStorageEmulatorResourcePromise(this._promise.then(obj => obj.withReference(source, options))); + } + + /** Adds a service discovery reference to another resource */ + withServiceReference(source: ResourceBuilderBase): AzureStorageEmulatorResourcePromise { + return new AzureStorageEmulatorResourcePromise(this._promise.then(obj => obj.withServiceReference(source))); + } + + /** Adds a named service discovery reference */ + withServiceReferenceNamed(source: ResourceBuilderBase, name: string): AzureStorageEmulatorResourcePromise { + return new AzureStorageEmulatorResourcePromise(this._promise.then(obj => obj.withServiceReferenceNamed(source, name))); + } + + /** Adds a reference to a URI */ + withReferenceUri(name: string, uri: string): AzureStorageEmulatorResourcePromise { + return new AzureStorageEmulatorResourcePromise(this._promise.then(obj => obj.withReferenceUri(name, uri))); + } + + /** Adds a reference to an external service */ + withReferenceExternalService(externalService: ExternalServiceResource): AzureStorageEmulatorResourcePromise { + return new AzureStorageEmulatorResourcePromise(this._promise.then(obj => obj.withReferenceExternalService(externalService))); + } + + /** Adds a reference to an endpoint */ + withReferenceEndpoint(endpointReference: EndpointReference): AzureStorageEmulatorResourcePromise { + return new AzureStorageEmulatorResourcePromise(this._promise.then(obj => obj.withReferenceEndpoint(endpointReference))); + } + + /** Adds a network endpoint */ + withEndpoint(options?: WithEndpointOptions): AzureStorageEmulatorResourcePromise { + return new AzureStorageEmulatorResourcePromise(this._promise.then(obj => obj.withEndpoint(options))); + } + + /** Adds an HTTP endpoint */ + withHttpEndpoint(options?: WithHttpEndpointOptions): AzureStorageEmulatorResourcePromise { + return new AzureStorageEmulatorResourcePromise(this._promise.then(obj => obj.withHttpEndpoint(options))); + } + + /** Adds an HTTPS endpoint */ + withHttpsEndpoint(options?: WithHttpsEndpointOptions): AzureStorageEmulatorResourcePromise { + return new AzureStorageEmulatorResourcePromise(this._promise.then(obj => obj.withHttpsEndpoint(options))); + } + + /** Makes HTTP endpoints externally accessible */ + withExternalHttpEndpoints(): AzureStorageEmulatorResourcePromise { + return new AzureStorageEmulatorResourcePromise(this._promise.then(obj => obj.withExternalHttpEndpoints())); + } + + /** Gets an endpoint reference */ + getEndpoint(name: string): Promise { + return this._promise.then(obj => obj.getEndpoint(name)); + } + + /** Configures resource for HTTP/2 */ + asHttp2Service(): AzureStorageEmulatorResourcePromise { + return new AzureStorageEmulatorResourcePromise(this._promise.then(obj => obj.asHttp2Service())); + } + + /** Customizes displayed URLs via callback */ + withUrlsCallback(callback: (obj: ResourceUrlsCallbackContext) => Promise): AzureStorageEmulatorResourcePromise { + return new AzureStorageEmulatorResourcePromise(this._promise.then(obj => obj.withUrlsCallback(callback))); + } + + /** Customizes displayed URLs via async callback */ + withUrlsCallbackAsync(callback: (arg: ResourceUrlsCallbackContext) => Promise): AzureStorageEmulatorResourcePromise { + return new AzureStorageEmulatorResourcePromise(this._promise.then(obj => obj.withUrlsCallbackAsync(callback))); + } + + /** Adds or modifies displayed URLs */ + withUrl(url: string, options?: WithUrlOptions): AzureStorageEmulatorResourcePromise { + return new AzureStorageEmulatorResourcePromise(this._promise.then(obj => obj.withUrl(url, options))); + } + + /** Adds a URL using a reference expression */ + withUrlExpression(url: ReferenceExpression, options?: WithUrlExpressionOptions): AzureStorageEmulatorResourcePromise { + return new AzureStorageEmulatorResourcePromise(this._promise.then(obj => obj.withUrlExpression(url, options))); + } + + /** Customizes the URL for a specific endpoint via callback */ + withUrlForEndpoint(endpointName: string, callback: (obj: ResourceUrlAnnotation) => Promise): AzureStorageEmulatorResourcePromise { + return new AzureStorageEmulatorResourcePromise(this._promise.then(obj => obj.withUrlForEndpoint(endpointName, callback))); + } + + /** Adds a URL for a specific endpoint via factory callback */ + withUrlForEndpointFactory(endpointName: string, callback: (arg: EndpointReference) => Promise): AzureStorageEmulatorResourcePromise { + return new AzureStorageEmulatorResourcePromise(this._promise.then(obj => obj.withUrlForEndpointFactory(endpointName, callback))); + } + + /** Excludes the resource from the deployment manifest */ + excludeFromManifest(): AzureStorageEmulatorResourcePromise { + return new AzureStorageEmulatorResourcePromise(this._promise.then(obj => obj.excludeFromManifest())); + } + + /** Waits for another resource to be ready */ + waitFor(dependency: ResourceBuilderBase): AzureStorageEmulatorResourcePromise { + return new AzureStorageEmulatorResourcePromise(this._promise.then(obj => obj.waitFor(dependency))); + } + + /** Waits for another resource with specific behavior */ + waitForWithBehavior(dependency: ResourceBuilderBase, waitBehavior: WaitBehavior): AzureStorageEmulatorResourcePromise { + return new AzureStorageEmulatorResourcePromise(this._promise.then(obj => obj.waitForWithBehavior(dependency, waitBehavior))); + } + + /** Waits for another resource to start */ + waitForStart(dependency: ResourceBuilderBase): AzureStorageEmulatorResourcePromise { + return new AzureStorageEmulatorResourcePromise(this._promise.then(obj => obj.waitForStart(dependency))); + } + + /** Waits for another resource to start with specific behavior */ + waitForStartWithBehavior(dependency: ResourceBuilderBase, waitBehavior: WaitBehavior): AzureStorageEmulatorResourcePromise { + return new AzureStorageEmulatorResourcePromise(this._promise.then(obj => obj.waitForStartWithBehavior(dependency, waitBehavior))); + } + + /** Prevents resource from starting automatically */ + withExplicitStart(): AzureStorageEmulatorResourcePromise { + return new AzureStorageEmulatorResourcePromise(this._promise.then(obj => obj.withExplicitStart())); + } + + /** Waits for resource completion */ + waitForCompletion(dependency: ResourceBuilderBase, options?: WaitForCompletionOptions): AzureStorageEmulatorResourcePromise { + return new AzureStorageEmulatorResourcePromise(this._promise.then(obj => obj.waitForCompletion(dependency, options))); + } + + /** Adds a health check by key */ + withHealthCheck(key: string): AzureStorageEmulatorResourcePromise { + return new AzureStorageEmulatorResourcePromise(this._promise.then(obj => obj.withHealthCheck(key))); + } + + /** Adds an HTTP health check */ + withHttpHealthCheck(options?: WithHttpHealthCheckOptions): AzureStorageEmulatorResourcePromise { + return new AzureStorageEmulatorResourcePromise(this._promise.then(obj => obj.withHttpHealthCheck(options))); + } + + /** Adds a resource command */ + withCommand(name: string, displayName: string, executeCommand: (arg: ExecuteCommandContext) => Promise, options?: WithCommandOptions): AzureStorageEmulatorResourcePromise { + return new AzureStorageEmulatorResourcePromise(this._promise.then(obj => obj.withCommand(name, displayName, executeCommand, options))); + } + + /** Configures developer certificate trust */ + withDeveloperCertificateTrust(trust: boolean): AzureStorageEmulatorResourcePromise { + return new AzureStorageEmulatorResourcePromise(this._promise.then(obj => obj.withDeveloperCertificateTrust(trust))); + } + + /** Sets the certificate trust scope */ + withCertificateTrustScope(scope: CertificateTrustScope): AzureStorageEmulatorResourcePromise { + return new AzureStorageEmulatorResourcePromise(this._promise.then(obj => obj.withCertificateTrustScope(scope))); + } + + /** Configures HTTPS with a developer certificate */ + withHttpsDeveloperCertificate(options?: WithHttpsDeveloperCertificateOptions): AzureStorageEmulatorResourcePromise { + return new AzureStorageEmulatorResourcePromise(this._promise.then(obj => obj.withHttpsDeveloperCertificate(options))); + } + + /** Removes HTTPS certificate configuration */ + withoutHttpsCertificate(): AzureStorageEmulatorResourcePromise { + return new AzureStorageEmulatorResourcePromise(this._promise.then(obj => obj.withoutHttpsCertificate())); + } + + /** Sets the parent relationship */ + withParentRelationship(parent: ResourceBuilderBase): AzureStorageEmulatorResourcePromise { + return new AzureStorageEmulatorResourcePromise(this._promise.then(obj => obj.withParentRelationship(parent))); + } + + /** Sets a child relationship */ + withChildRelationship(child: ResourceBuilderBase): AzureStorageEmulatorResourcePromise { + return new AzureStorageEmulatorResourcePromise(this._promise.then(obj => obj.withChildRelationship(child))); + } + + /** Sets the icon for the resource */ + withIconName(iconName: string, options?: WithIconNameOptions): AzureStorageEmulatorResourcePromise { + return new AzureStorageEmulatorResourcePromise(this._promise.then(obj => obj.withIconName(iconName, options))); + } + + /** Adds an HTTP health probe to the resource */ + withHttpProbe(probeType: ProbeType, options?: WithHttpProbeOptions): AzureStorageEmulatorResourcePromise { + return new AzureStorageEmulatorResourcePromise(this._promise.then(obj => obj.withHttpProbe(probeType, options))); + } + + /** Excludes the resource from MCP server exposure */ + excludeFromMcp(): AzureStorageEmulatorResourcePromise { + return new AzureStorageEmulatorResourcePromise(this._promise.then(obj => obj.excludeFromMcp())); + } + + /** Sets the remote image name for publishing */ + withRemoteImageName(remoteImageName: string): AzureStorageEmulatorResourcePromise { + return new AzureStorageEmulatorResourcePromise(this._promise.then(obj => obj.withRemoteImageName(remoteImageName))); + } + + /** Sets the remote image tag for publishing */ + withRemoteImageTag(remoteImageTag: string): AzureStorageEmulatorResourcePromise { + return new AzureStorageEmulatorResourcePromise(this._promise.then(obj => obj.withRemoteImageTag(remoteImageTag))); + } + + /** Adds a pipeline step to the resource */ + withPipelineStepFactory(stepName: string, callback: (arg: PipelineStepContext) => Promise, options?: WithPipelineStepFactoryOptions): AzureStorageEmulatorResourcePromise { + return new AzureStorageEmulatorResourcePromise(this._promise.then(obj => obj.withPipelineStepFactory(stepName, callback, options))); + } + + /** Configures pipeline step dependencies via an async callback */ + withPipelineConfigurationAsync(callback: (arg: PipelineConfigurationContext) => Promise): AzureStorageEmulatorResourcePromise { + return new AzureStorageEmulatorResourcePromise(this._promise.then(obj => obj.withPipelineConfigurationAsync(callback))); + } + + /** Configures pipeline step dependencies via a callback */ + withPipelineConfiguration(callback: (obj: PipelineConfigurationContext) => Promise): AzureStorageEmulatorResourcePromise { + return new AzureStorageEmulatorResourcePromise(this._promise.then(obj => obj.withPipelineConfiguration(callback))); + } + + /** Adds a volume */ + withVolume(target: string, options?: WithVolumeOptions): AzureStorageEmulatorResourcePromise { + return new AzureStorageEmulatorResourcePromise(this._promise.then(obj => obj.withVolume(target, options))); + } + + /** Gets the resource name */ + getResourceName(): Promise { + return this._promise.then(obj => obj.getResourceName()); + } + + /** Adds a bind mount for the data folder to an Azure Storage emulator resource */ + withDataBindMount(options?: WithDataBindMountOptions): AzureStorageEmulatorResourcePromise { + return new AzureStorageEmulatorResourcePromise(this._promise.then(obj => obj.withDataBindMount(options))); + } + + /** Adds a named volume for the data folder to an Azure Storage emulator resource */ + withDataVolume(options?: WithDataVolumeOptions): AzureStorageEmulatorResourcePromise { + return new AzureStorageEmulatorResourcePromise(this._promise.then(obj => obj.withDataVolume(options))); + } + + /** Sets the host port for blob requests on the storage emulator */ + withBlobPort(port: number): AzureStorageEmulatorResourcePromise { + return new AzureStorageEmulatorResourcePromise(this._promise.then(obj => obj.withBlobPort(port))); + } + + /** Sets the host port for queue requests on the storage emulator */ + withQueuePort(port: number): AzureStorageEmulatorResourcePromise { + return new AzureStorageEmulatorResourcePromise(this._promise.then(obj => obj.withQueuePort(port))); + } + + /** Sets the host port for table requests on the storage emulator */ + withTablePort(port: number): AzureStorageEmulatorResourcePromise { + return new AzureStorageEmulatorResourcePromise(this._promise.then(obj => obj.withTablePort(port))); + } + + /** Configures whether the emulator checks API version validity */ + withApiVersionCheck(options?: WithApiVersionCheckOptions): AzureStorageEmulatorResourcePromise { + return new AzureStorageEmulatorResourcePromise(this._promise.then(obj => obj.withApiVersionCheck(options))); + } + + /** Assigns Azure Storage roles to a resource */ + withStorageRoleAssignments(target: AzureStorageResource, roles: AzureStorageRole[]): AzureStorageEmulatorResourcePromise { + return new AzureStorageEmulatorResourcePromise(this._promise.then(obj => obj.withStorageRoleAssignments(target, roles))); + } + + /** Assigns Event Hubs roles to a resource */ + withEventHubsRoleAssignments(target: AzureEventHubsResource, roles: AzureEventHubsRole[]): AzureStorageEmulatorResourcePromise { + return new AzureStorageEmulatorResourcePromise(this._promise.then(obj => obj.withEventHubsRoleAssignments(target, roles))); + } + + /** Sets an environment variable from a Bicep output reference */ + withEnvironmentFromOutput(name: string, bicepOutputReference: BicepOutputReference): AzureStorageEmulatorResourcePromise { + return new AzureStorageEmulatorResourcePromise(this._promise.then(obj => obj.withEnvironmentFromOutput(name, bicepOutputReference))); + } + + /** Sets an environment variable from an Azure Key Vault secret reference */ + withEnvironmentFromKeyVaultSecret(name: string, secretReference: ResourceBuilderBase): AzureStorageEmulatorResourcePromise { + return new AzureStorageEmulatorResourcePromise(this._promise.then(obj => obj.withEnvironmentFromKeyVaultSecret(name, secretReference))); + } + + /** Associates an Azure user-assigned identity with a compute resource */ + withAzureUserAssignedIdentity(identityResourceBuilder: AzureUserAssignedIdentityResource): AzureStorageEmulatorResourcePromise { + return new AzureStorageEmulatorResourcePromise(this._promise.then(obj => obj.withAzureUserAssignedIdentity(identityResourceBuilder))); + } + +} + +// ============================================================================ +// AzureStorageResource +// ============================================================================ + +export class AzureStorageResource extends ResourceBuilderBase { + constructor(handle: AzureStorageResourceHandle, client: AspireClientRpc) { + super(handle, client); + } + + /** @internal */ + private async _withContainerRegistryInternal(registry: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, registry }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withContainerRegistry', + rpcArgs + ); + return new AzureStorageResource(result, this._client); + } + + /** Configures a resource to use a container registry */ + withContainerRegistry(registry: ResourceBuilderBase): AzureStorageResourcePromise { + return new AzureStorageResourcePromise(this._withContainerRegistryInternal(registry)); + } + + /** @internal */ + private async _withDockerfileBaseImageInternal(buildImage?: string, runtimeImage?: string): Promise { + const rpcArgs: Record = { builder: this._handle }; + if (buildImage !== undefined) rpcArgs.buildImage = buildImage; + if (runtimeImage !== undefined) rpcArgs.runtimeImage = runtimeImage; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withDockerfileBaseImage', + rpcArgs + ); + return new AzureStorageResource(result, this._client); + } + + /** Sets the base image for a Dockerfile build */ + withDockerfileBaseImage(options?: WithDockerfileBaseImageOptions): AzureStorageResourcePromise { + const buildImage = options?.buildImage; + const runtimeImage = options?.runtimeImage; + return new AzureStorageResourcePromise(this._withDockerfileBaseImageInternal(buildImage, runtimeImage)); + } + + /** @internal */ + private async _withMcpServerInternal(path?: string, endpointName?: string): Promise { + const rpcArgs: Record = { builder: this._handle }; + if (path !== undefined) rpcArgs.path = path; + if (endpointName !== undefined) rpcArgs.endpointName = endpointName; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withMcpServer', + rpcArgs + ); + return new AzureStorageResource(result, this._client); + } + + /** Configures an MCP server endpoint on the resource */ + withMcpServer(options?: WithMcpServerOptions): AzureStorageResourcePromise { + const path = options?.path; + const endpointName = options?.endpointName; + return new AzureStorageResourcePromise(this._withMcpServerInternal(path, endpointName)); + } + + /** @internal */ + private async _withRequiredCommandInternal(command: string, helpLink?: string): Promise { + const rpcArgs: Record = { builder: this._handle, command }; + if (helpLink !== undefined) rpcArgs.helpLink = helpLink; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withRequiredCommand', + rpcArgs + ); + return new AzureStorageResource(result, this._client); + } + + /** Adds a required command dependency */ + withRequiredCommand(command: string, options?: WithRequiredCommandOptions): AzureStorageResourcePromise { + const helpLink = options?.helpLink; + return new AzureStorageResourcePromise(this._withRequiredCommandInternal(command, helpLink)); + } + + /** @internal */ + private async _withEndpointInternal(port?: number, targetPort?: number, scheme?: string, name?: string, env?: string, isProxied?: boolean, isExternal?: boolean, protocol?: ProtocolType): Promise { + const rpcArgs: Record = { builder: this._handle }; + if (port !== undefined) rpcArgs.port = port; + if (targetPort !== undefined) rpcArgs.targetPort = targetPort; + if (scheme !== undefined) rpcArgs.scheme = scheme; + if (name !== undefined) rpcArgs.name = name; + if (env !== undefined) rpcArgs.env = env; + if (isProxied !== undefined) rpcArgs.isProxied = isProxied; + if (isExternal !== undefined) rpcArgs.isExternal = isExternal; + if (protocol !== undefined) rpcArgs.protocol = protocol; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withEndpoint', + rpcArgs + ); + return new AzureStorageResource(result, this._client); + } + + /** Adds a network endpoint */ + withEndpoint(options?: WithEndpointOptions): AzureStorageResourcePromise { + const port = options?.port; + const targetPort = options?.targetPort; + const scheme = options?.scheme; + const name = options?.name; + const env = options?.env; + const isProxied = options?.isProxied; + const isExternal = options?.isExternal; + const protocol = options?.protocol; + return new AzureStorageResourcePromise(this._withEndpointInternal(port, targetPort, scheme, name, env, isProxied, isExternal, protocol)); + } + + /** @internal */ + private async _withHttpEndpointInternal(port?: number, targetPort?: number, name?: string, env?: string, isProxied?: boolean): Promise { + const rpcArgs: Record = { builder: this._handle }; + if (port !== undefined) rpcArgs.port = port; + if (targetPort !== undefined) rpcArgs.targetPort = targetPort; + if (name !== undefined) rpcArgs.name = name; + if (env !== undefined) rpcArgs.env = env; + if (isProxied !== undefined) rpcArgs.isProxied = isProxied; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withHttpEndpoint', + rpcArgs + ); + return new AzureStorageResource(result, this._client); + } + + /** Adds an HTTP endpoint */ + withHttpEndpoint(options?: WithHttpEndpointOptions): AzureStorageResourcePromise { + const port = options?.port; + const targetPort = options?.targetPort; + const name = options?.name; + const env = options?.env; + const isProxied = options?.isProxied; + return new AzureStorageResourcePromise(this._withHttpEndpointInternal(port, targetPort, name, env, isProxied)); + } + + /** @internal */ + private async _withHttpsEndpointInternal(port?: number, targetPort?: number, name?: string, env?: string, isProxied?: boolean): Promise { + const rpcArgs: Record = { builder: this._handle }; + if (port !== undefined) rpcArgs.port = port; + if (targetPort !== undefined) rpcArgs.targetPort = targetPort; + if (name !== undefined) rpcArgs.name = name; + if (env !== undefined) rpcArgs.env = env; + if (isProxied !== undefined) rpcArgs.isProxied = isProxied; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withHttpsEndpoint', + rpcArgs + ); + return new AzureStorageResource(result, this._client); + } + + /** Adds an HTTPS endpoint */ + withHttpsEndpoint(options?: WithHttpsEndpointOptions): AzureStorageResourcePromise { + const port = options?.port; + const targetPort = options?.targetPort; + const name = options?.name; + const env = options?.env; + const isProxied = options?.isProxied; + return new AzureStorageResourcePromise(this._withHttpsEndpointInternal(port, targetPort, name, env, isProxied)); + } + + /** @internal */ + private async _withExternalHttpEndpointsInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withExternalHttpEndpoints', + rpcArgs + ); + return new AzureStorageResource(result, this._client); + } + + /** Makes HTTP endpoints externally accessible */ + withExternalHttpEndpoints(): AzureStorageResourcePromise { + return new AzureStorageResourcePromise(this._withExternalHttpEndpointsInternal()); + } + + /** Gets an endpoint reference */ + async getEndpoint(name: string): Promise { + const rpcArgs: Record = { builder: this._handle, name }; + return await this._client.invokeCapability( + 'Aspire.Hosting/getEndpoint', + rpcArgs + ); + } + + /** @internal */ + private async _asHttp2ServiceInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/asHttp2Service', + rpcArgs + ); + return new AzureStorageResource(result, this._client); + } + + /** Configures resource for HTTP/2 */ + asHttp2Service(): AzureStorageResourcePromise { + return new AzureStorageResourcePromise(this._asHttp2ServiceInternal()); + } + + /** @internal */ + private async _withUrlsCallbackInternal(callback: (obj: ResourceUrlsCallbackContext) => Promise): Promise { + const callbackId = registerCallback(async (objData: unknown) => { + const objHandle = wrapIfHandle(objData) as ResourceUrlsCallbackContextHandle; + const obj = new ResourceUrlsCallbackContext(objHandle, this._client); + await callback(obj); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrlsCallback', + rpcArgs + ); + return new AzureStorageResource(result, this._client); + } + + /** Customizes displayed URLs via callback */ + withUrlsCallback(callback: (obj: ResourceUrlsCallbackContext) => Promise): AzureStorageResourcePromise { + return new AzureStorageResourcePromise(this._withUrlsCallbackInternal(callback)); + } + + /** @internal */ + private async _withUrlsCallbackAsyncInternal(callback: (arg: ResourceUrlsCallbackContext) => Promise): Promise { + const callbackId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as ResourceUrlsCallbackContextHandle; + const arg = new ResourceUrlsCallbackContext(argHandle, this._client); + await callback(arg); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrlsCallbackAsync', + rpcArgs + ); + return new AzureStorageResource(result, this._client); + } + + /** Customizes displayed URLs via async callback */ + withUrlsCallbackAsync(callback: (arg: ResourceUrlsCallbackContext) => Promise): AzureStorageResourcePromise { + return new AzureStorageResourcePromise(this._withUrlsCallbackAsyncInternal(callback)); + } + + /** @internal */ + private async _withUrlInternal(url: string, displayText?: string): Promise { + const rpcArgs: Record = { builder: this._handle, url }; + if (displayText !== undefined) rpcArgs.displayText = displayText; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrl', + rpcArgs + ); + return new AzureStorageResource(result, this._client); + } + + /** Adds or modifies displayed URLs */ + withUrl(url: string, options?: WithUrlOptions): AzureStorageResourcePromise { + const displayText = options?.displayText; + return new AzureStorageResourcePromise(this._withUrlInternal(url, displayText)); + } + + /** @internal */ + private async _withUrlExpressionInternal(url: ReferenceExpression, displayText?: string): Promise { + const rpcArgs: Record = { builder: this._handle, url }; + if (displayText !== undefined) rpcArgs.displayText = displayText; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrlExpression', + rpcArgs + ); + return new AzureStorageResource(result, this._client); + } + + /** Adds a URL using a reference expression */ + withUrlExpression(url: ReferenceExpression, options?: WithUrlExpressionOptions): AzureStorageResourcePromise { + const displayText = options?.displayText; + return new AzureStorageResourcePromise(this._withUrlExpressionInternal(url, displayText)); + } + + /** @internal */ + private async _withUrlForEndpointInternal(endpointName: string, callback: (obj: ResourceUrlAnnotation) => Promise): Promise { + const callbackId = registerCallback(async (objData: unknown) => { + const obj = wrapIfHandle(objData) as ResourceUrlAnnotation; + await callback(obj); + }); + const rpcArgs: Record = { builder: this._handle, endpointName, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrlForEndpoint', + rpcArgs + ); + return new AzureStorageResource(result, this._client); + } + + /** Customizes the URL for a specific endpoint via callback */ + withUrlForEndpoint(endpointName: string, callback: (obj: ResourceUrlAnnotation) => Promise): AzureStorageResourcePromise { + return new AzureStorageResourcePromise(this._withUrlForEndpointInternal(endpointName, callback)); + } + + /** @internal */ + private async _withUrlForEndpointFactoryInternal(endpointName: string, callback: (arg: EndpointReference) => Promise): Promise { + const callbackId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as EndpointReferenceHandle; + const arg = new EndpointReference(argHandle, this._client); + return await callback(arg); + }); + const rpcArgs: Record = { builder: this._handle, endpointName, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrlForEndpointFactory', + rpcArgs + ); + return new AzureStorageResource(result, this._client); + } + + /** Adds a URL for a specific endpoint via factory callback */ + withUrlForEndpointFactory(endpointName: string, callback: (arg: EndpointReference) => Promise): AzureStorageResourcePromise { + return new AzureStorageResourcePromise(this._withUrlForEndpointFactoryInternal(endpointName, callback)); + } + + /** @internal */ + private async _excludeFromManifestInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/excludeFromManifest', + rpcArgs + ); + return new AzureStorageResource(result, this._client); + } + + /** Excludes the resource from the deployment manifest */ + excludeFromManifest(): AzureStorageResourcePromise { + return new AzureStorageResourcePromise(this._excludeFromManifestInternal()); + } + + /** @internal */ + private async _withExplicitStartInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withExplicitStart', + rpcArgs + ); + return new AzureStorageResource(result, this._client); + } + + /** Prevents resource from starting automatically */ + withExplicitStart(): AzureStorageResourcePromise { + return new AzureStorageResourcePromise(this._withExplicitStartInternal()); + } + + /** @internal */ + private async _withHealthCheckInternal(key: string): Promise { + const rpcArgs: Record = { builder: this._handle, key }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withHealthCheck', + rpcArgs + ); + return new AzureStorageResource(result, this._client); + } + + /** Adds a health check by key */ + withHealthCheck(key: string): AzureStorageResourcePromise { + return new AzureStorageResourcePromise(this._withHealthCheckInternal(key)); + } + + /** @internal */ + private async _withHttpHealthCheckInternal(path?: string, statusCode?: number, endpointName?: string): Promise { + const rpcArgs: Record = { builder: this._handle }; + if (path !== undefined) rpcArgs.path = path; + if (statusCode !== undefined) rpcArgs.statusCode = statusCode; + if (endpointName !== undefined) rpcArgs.endpointName = endpointName; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withHttpHealthCheck', + rpcArgs + ); + return new AzureStorageResource(result, this._client); + } + + /** Adds an HTTP health check */ + withHttpHealthCheck(options?: WithHttpHealthCheckOptions): AzureStorageResourcePromise { + const path = options?.path; + const statusCode = options?.statusCode; + const endpointName = options?.endpointName; + return new AzureStorageResourcePromise(this._withHttpHealthCheckInternal(path, statusCode, endpointName)); + } + + /** @internal */ + private async _withCommandInternal(name: string, displayName: string, executeCommand: (arg: ExecuteCommandContext) => Promise, commandOptions?: CommandOptions): Promise { + const executeCommandId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as ExecuteCommandContextHandle; + const arg = new ExecuteCommandContext(argHandle, this._client); + return await executeCommand(arg); + }); + const rpcArgs: Record = { builder: this._handle, name, displayName, executeCommand: executeCommandId }; + if (commandOptions !== undefined) rpcArgs.commandOptions = commandOptions; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withCommand', + rpcArgs + ); + return new AzureStorageResource(result, this._client); + } + + /** Adds a resource command */ + withCommand(name: string, displayName: string, executeCommand: (arg: ExecuteCommandContext) => Promise, options?: WithCommandOptions): AzureStorageResourcePromise { + const commandOptions = options?.commandOptions; + return new AzureStorageResourcePromise(this._withCommandInternal(name, displayName, executeCommand, commandOptions)); + } + + /** @internal */ + private async _withParentRelationshipInternal(parent: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, parent }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withParentRelationship', + rpcArgs + ); + return new AzureStorageResource(result, this._client); + } + + /** Sets the parent relationship */ + withParentRelationship(parent: ResourceBuilderBase): AzureStorageResourcePromise { + return new AzureStorageResourcePromise(this._withParentRelationshipInternal(parent)); + } + + /** @internal */ + private async _withChildRelationshipInternal(child: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, child }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withChildRelationship', + rpcArgs + ); + return new AzureStorageResource(result, this._client); + } + + /** Sets a child relationship */ + withChildRelationship(child: ResourceBuilderBase): AzureStorageResourcePromise { + return new AzureStorageResourcePromise(this._withChildRelationshipInternal(child)); + } + + /** @internal */ + private async _withIconNameInternal(iconName: string, iconVariant?: IconVariant): Promise { + const rpcArgs: Record = { builder: this._handle, iconName }; + if (iconVariant !== undefined) rpcArgs.iconVariant = iconVariant; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withIconName', + rpcArgs + ); + return new AzureStorageResource(result, this._client); + } + + /** Sets the icon for the resource */ + withIconName(iconName: string, options?: WithIconNameOptions): AzureStorageResourcePromise { + const iconVariant = options?.iconVariant; + return new AzureStorageResourcePromise(this._withIconNameInternal(iconName, iconVariant)); + } + + /** @internal */ + private async _withHttpProbeInternal(probeType: ProbeType, path?: string, initialDelaySeconds?: number, periodSeconds?: number, timeoutSeconds?: number, failureThreshold?: number, successThreshold?: number, endpointName?: string): Promise { + const rpcArgs: Record = { builder: this._handle, probeType }; + if (path !== undefined) rpcArgs.path = path; + if (initialDelaySeconds !== undefined) rpcArgs.initialDelaySeconds = initialDelaySeconds; + if (periodSeconds !== undefined) rpcArgs.periodSeconds = periodSeconds; + if (timeoutSeconds !== undefined) rpcArgs.timeoutSeconds = timeoutSeconds; + if (failureThreshold !== undefined) rpcArgs.failureThreshold = failureThreshold; + if (successThreshold !== undefined) rpcArgs.successThreshold = successThreshold; + if (endpointName !== undefined) rpcArgs.endpointName = endpointName; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withHttpProbe', + rpcArgs + ); + return new AzureStorageResource(result, this._client); + } + + /** Adds an HTTP health probe to the resource */ + withHttpProbe(probeType: ProbeType, options?: WithHttpProbeOptions): AzureStorageResourcePromise { + const path = options?.path; + const initialDelaySeconds = options?.initialDelaySeconds; + const periodSeconds = options?.periodSeconds; + const timeoutSeconds = options?.timeoutSeconds; + const failureThreshold = options?.failureThreshold; + const successThreshold = options?.successThreshold; + const endpointName = options?.endpointName; + return new AzureStorageResourcePromise(this._withHttpProbeInternal(probeType, path, initialDelaySeconds, periodSeconds, timeoutSeconds, failureThreshold, successThreshold, endpointName)); + } + + /** @internal */ + private async _excludeFromMcpInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/excludeFromMcp', + rpcArgs + ); + return new AzureStorageResource(result, this._client); + } + + /** Excludes the resource from MCP server exposure */ + excludeFromMcp(): AzureStorageResourcePromise { + return new AzureStorageResourcePromise(this._excludeFromMcpInternal()); + } + + /** @internal */ + private async _withPipelineStepFactoryInternal(stepName: string, callback: (arg: PipelineStepContext) => Promise, dependsOn?: string[], requiredBy?: string[], tags?: string[], description?: string): Promise { + const callbackId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as PipelineStepContextHandle; + const arg = new PipelineStepContext(argHandle, this._client); + await callback(arg); + }); + const rpcArgs: Record = { builder: this._handle, stepName, callback: callbackId }; + if (dependsOn !== undefined) rpcArgs.dependsOn = dependsOn; + if (requiredBy !== undefined) rpcArgs.requiredBy = requiredBy; + if (tags !== undefined) rpcArgs.tags = tags; + if (description !== undefined) rpcArgs.description = description; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withPipelineStepFactory', + rpcArgs + ); + return new AzureStorageResource(result, this._client); + } + + /** Adds a pipeline step to the resource */ + withPipelineStepFactory(stepName: string, callback: (arg: PipelineStepContext) => Promise, options?: WithPipelineStepFactoryOptions): AzureStorageResourcePromise { + const dependsOn = options?.dependsOn; + const requiredBy = options?.requiredBy; + const tags = options?.tags; + const description = options?.description; + return new AzureStorageResourcePromise(this._withPipelineStepFactoryInternal(stepName, callback, dependsOn, requiredBy, tags, description)); + } + + /** @internal */ + private async _withPipelineConfigurationAsyncInternal(callback: (arg: PipelineConfigurationContext) => Promise): Promise { + const callbackId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as PipelineConfigurationContextHandle; + const arg = new PipelineConfigurationContext(argHandle, this._client); + await callback(arg); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withPipelineConfigurationAsync', + rpcArgs + ); + return new AzureStorageResource(result, this._client); + } + + /** Configures pipeline step dependencies via an async callback */ + withPipelineConfigurationAsync(callback: (arg: PipelineConfigurationContext) => Promise): AzureStorageResourcePromise { + return new AzureStorageResourcePromise(this._withPipelineConfigurationAsyncInternal(callback)); + } + + /** @internal */ + private async _withPipelineConfigurationInternal(callback: (obj: PipelineConfigurationContext) => Promise): Promise { + const callbackId = registerCallback(async (objData: unknown) => { + const objHandle = wrapIfHandle(objData) as PipelineConfigurationContextHandle; + const obj = new PipelineConfigurationContext(objHandle, this._client); + await callback(obj); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withPipelineConfiguration', + rpcArgs + ); + return new AzureStorageResource(result, this._client); + } + + /** Configures pipeline step dependencies via a callback */ + withPipelineConfiguration(callback: (obj: PipelineConfigurationContext) => Promise): AzureStorageResourcePromise { + return new AzureStorageResourcePromise(this._withPipelineConfigurationInternal(callback)); + } + + /** Gets the resource name */ + async getResourceName(): Promise { + const rpcArgs: Record = { resource: this._handle }; + return await this._client.invokeCapability( + 'Aspire.Hosting/getResourceName', + rpcArgs + ); + } + + /** @internal */ + private async _runAsEmulatorInternal(configureContainer?: (obj: AzureStorageEmulatorResource) => Promise): Promise { + const configureContainerId = configureContainer ? registerCallback(async (objData: unknown) => { + const objHandle = wrapIfHandle(objData) as AzureStorageEmulatorResourceHandle; + const obj = new AzureStorageEmulatorResource(objHandle, this._client); + await configureContainer(obj); + }) : undefined; + const rpcArgs: Record = { builder: this._handle }; + if (configureContainer !== undefined) rpcArgs.configureContainer = configureContainerId; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure.Storage/runAsEmulator', + rpcArgs + ); + return new AzureStorageResource(result, this._client); + } + + /** Configures the Azure Storage resource to be emulated using Azurite */ + runAsEmulator(options?: RunAsEmulator1Options): AzureStorageResourcePromise { + const configureContainer = options?.configureContainer; + return new AzureStorageResourcePromise(this._runAsEmulatorInternal(configureContainer)); + } + + /** @internal */ + private async _addBlobsInternal(name: string): Promise { + const rpcArgs: Record = { builder: this._handle, name }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure.Storage/addBlobs', + rpcArgs + ); + return new AzureBlobStorageResource(result, this._client); + } + + /** Adds an Azure Blob Storage resource */ + addBlobs(name: string): AzureBlobStorageResourcePromise { + return new AzureBlobStorageResourcePromise(this._addBlobsInternal(name)); + } + + /** @internal */ + private async _addDataLakeInternal(name: string): Promise { + const rpcArgs: Record = { builder: this._handle, name }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure.Storage/addDataLake', + rpcArgs + ); + return new AzureDataLakeStorageResource(result, this._client); + } + + /** Adds an Azure Data Lake Storage resource */ + addDataLake(name: string): AzureDataLakeStorageResourcePromise { + return new AzureDataLakeStorageResourcePromise(this._addDataLakeInternal(name)); + } + + /** @internal */ + private async _addBlobContainerInternal(name: string, blobContainerName?: string): Promise { + const rpcArgs: Record = { builder: this._handle, name }; + if (blobContainerName !== undefined) rpcArgs.blobContainerName = blobContainerName; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure.Storage/addBlobContainer', + rpcArgs + ); + return new AzureBlobStorageContainerResource(result, this._client); + } + + /** Adds an Azure Blob Storage container resource */ + addBlobContainer(name: string, options?: AddBlobContainerOptions): AzureBlobStorageContainerResourcePromise { + const blobContainerName = options?.blobContainerName; + return new AzureBlobStorageContainerResourcePromise(this._addBlobContainerInternal(name, blobContainerName)); + } + + /** @internal */ + private async _addDataLakeFileSystemInternal(name: string, dataLakeFileSystemName?: string): Promise { + const rpcArgs: Record = { builder: this._handle, name }; + if (dataLakeFileSystemName !== undefined) rpcArgs.dataLakeFileSystemName = dataLakeFileSystemName; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure.Storage/addDataLakeFileSystem', + rpcArgs + ); + return new AzureDataLakeStorageFileSystemResource(result, this._client); + } + + /** Adds an Azure Data Lake Storage file system resource */ + addDataLakeFileSystem(name: string, options?: AddDataLakeFileSystemOptions): AzureDataLakeStorageFileSystemResourcePromise { + const dataLakeFileSystemName = options?.dataLakeFileSystemName; + return new AzureDataLakeStorageFileSystemResourcePromise(this._addDataLakeFileSystemInternal(name, dataLakeFileSystemName)); + } + + /** @internal */ + private async _addTablesInternal(name: string): Promise { + const rpcArgs: Record = { builder: this._handle, name }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure.Storage/addTables', + rpcArgs + ); + return new AzureTableStorageResource(result, this._client); + } + + /** Adds an Azure Table Storage resource */ + addTables(name: string): AzureTableStorageResourcePromise { + return new AzureTableStorageResourcePromise(this._addTablesInternal(name)); + } + + /** @internal */ + private async _addQueuesInternal(name: string): Promise { + const rpcArgs: Record = { builder: this._handle, name }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure.Storage/addQueues', + rpcArgs + ); + return new AzureQueueStorageResource(result, this._client); + } + + /** Adds an Azure Queue Storage resource */ + addQueues(name: string): AzureQueueStorageResourcePromise { + return new AzureQueueStorageResourcePromise(this._addQueuesInternal(name)); + } + + /** @internal */ + private async _addQueueInternal(name: string, queueName?: string): Promise { + const rpcArgs: Record = { builder: this._handle, name }; + if (queueName !== undefined) rpcArgs.queueName = queueName; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure.Storage/addQueue', + rpcArgs + ); + return new AzureQueueStorageQueueResource(result, this._client); + } + + /** Adds an Azure Storage queue resource */ + addQueue(name: string, options?: AddQueueOptions): AzureQueueStorageQueueResourcePromise { + const queueName = options?.queueName; + return new AzureQueueStorageQueueResourcePromise(this._addQueueInternal(name, queueName)); + } + + /** @internal */ + private async _withStorageRoleAssignmentsInternal(target: AzureStorageResource, roles: AzureStorageRole[]): Promise { + const rpcArgs: Record = { builder: this._handle, target, roles }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure.Storage/withStorageRoleAssignments', + rpcArgs + ); + return new AzureStorageResource(result, this._client); + } + + /** Assigns Azure Storage roles to a resource */ + withStorageRoleAssignments(target: AzureStorageResource, roles: AzureStorageRole[]): AzureStorageResourcePromise { + return new AzureStorageResourcePromise(this._withStorageRoleAssignmentsInternal(target, roles)); + } + + /** @internal */ + private async _withEventHubsRoleAssignmentsInternal(target: AzureEventHubsResource, roles: AzureEventHubsRole[]): Promise { + const rpcArgs: Record = { builder: this._handle, target, roles }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure.EventHubs/withEventHubsRoleAssignments', + rpcArgs + ); + return new AzureStorageResource(result, this._client); + } + + /** Assigns Event Hubs roles to a resource */ + withEventHubsRoleAssignments(target: AzureEventHubsResource, roles: AzureEventHubsRole[]): AzureStorageResourcePromise { + return new AzureStorageResourcePromise(this._withEventHubsRoleAssignmentsInternal(target, roles)); + } + + /** Gets an output reference from an Azure Bicep template resource */ + async getOutput(name: string): Promise { + const rpcArgs: Record = { builder: this._handle, name }; + return await this._client.invokeCapability( + 'Aspire.Hosting.Azure/getOutput', + rpcArgs + ); + } + + /** @internal */ + private async _withParameterInternal(name: string): Promise { + const rpcArgs: Record = { builder: this._handle, name }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure/withParameter', + rpcArgs + ); + return new AzureStorageResource(result, this._client); + } + + /** Adds a Bicep parameter without a value */ + withParameter(name: string): AzureStorageResourcePromise { + return new AzureStorageResourcePromise(this._withParameterInternal(name)); + } + + /** @internal */ + private async _withParameterStringValueInternal(name: string, value: string): Promise { + const rpcArgs: Record = { builder: this._handle, name, value }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure/withParameterStringValue', + rpcArgs + ); + return new AzureStorageResource(result, this._client); + } + + /** Adds a Bicep parameter with a string value */ + withParameterStringValue(name: string, value: string): AzureStorageResourcePromise { + return new AzureStorageResourcePromise(this._withParameterStringValueInternal(name, value)); + } + + /** @internal */ + private async _withParameterStringValuesInternal(name: string, value: string[]): Promise { + const rpcArgs: Record = { builder: this._handle, name, value }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure/withParameterStringValues', + rpcArgs + ); + return new AzureStorageResource(result, this._client); + } + + /** Adds a Bicep parameter with a string list value */ + withParameterStringValues(name: string, value: string[]): AzureStorageResourcePromise { + return new AzureStorageResourcePromise(this._withParameterStringValuesInternal(name, value)); + } + + /** @internal */ + private async _withParameterFromParameterInternal(name: string, value: ParameterResource): Promise { + const rpcArgs: Record = { builder: this._handle, name, value }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure/withParameterFromParameter', + rpcArgs + ); + return new AzureStorageResource(result, this._client); + } + + /** Adds a Bicep parameter from a parameter resource builder */ + withParameterFromParameter(name: string, value: ParameterResource): AzureStorageResourcePromise { + return new AzureStorageResourcePromise(this._withParameterFromParameterInternal(name, value)); + } + + /** @internal */ + private async _withParameterFromConnectionStringInternal(name: string, value: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, name, value }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure/withParameterFromConnectionString', + rpcArgs + ); + return new AzureStorageResource(result, this._client); + } + + /** Adds a Bicep parameter from a connection string resource builder */ + withParameterFromConnectionString(name: string, value: ResourceBuilderBase): AzureStorageResourcePromise { + return new AzureStorageResourcePromise(this._withParameterFromConnectionStringInternal(name, value)); + } + + /** @internal */ + private async _withParameterFromOutputInternal(name: string, value: BicepOutputReference): Promise { + const rpcArgs: Record = { builder: this._handle, name, value }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure/withParameterFromOutput', + rpcArgs + ); + return new AzureStorageResource(result, this._client); + } + + /** Adds a Bicep parameter from another Bicep output reference */ + withParameterFromOutput(name: string, value: BicepOutputReference): AzureStorageResourcePromise { + return new AzureStorageResourcePromise(this._withParameterFromOutputInternal(name, value)); + } + + /** @internal */ + private async _withParameterFromReferenceExpressionInternal(name: string, value: ReferenceExpression): Promise { + const rpcArgs: Record = { builder: this._handle, name, value }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure/withParameterFromReferenceExpression', + rpcArgs + ); + return new AzureStorageResource(result, this._client); + } + + /** Adds a Bicep parameter from a reference expression */ + withParameterFromReferenceExpression(name: string, value: ReferenceExpression): AzureStorageResourcePromise { + return new AzureStorageResourcePromise(this._withParameterFromReferenceExpressionInternal(name, value)); + } + + /** @internal */ + private async _withParameterFromEndpointInternal(name: string, value: EndpointReference): Promise { + const rpcArgs: Record = { builder: this._handle, name, value }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure/withParameterFromEndpoint', + rpcArgs + ); + return new AzureStorageResource(result, this._client); + } + + /** Adds a Bicep parameter from an endpoint reference */ + withParameterFromEndpoint(name: string, value: EndpointReference): AzureStorageResourcePromise { + return new AzureStorageResourcePromise(this._withParameterFromEndpointInternal(name, value)); + } + + /** @internal */ + private async _configureInfrastructureInternal(configure: (obj: AzureResourceInfrastructure) => Promise): Promise { + const configureId = registerCallback(async (objData: unknown) => { + const objHandle = wrapIfHandle(objData) as AzureResourceInfrastructureHandle; + const obj = new AzureResourceInfrastructure(objHandle, this._client); + await configure(obj); + }); + const rpcArgs: Record = { builder: this._handle, configure: configureId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure/configureInfrastructure', + rpcArgs + ); + return new AzureStorageResource(result, this._client); + } + + /** Configures the Azure provisioning infrastructure callback */ + configureInfrastructure(configure: (obj: AzureResourceInfrastructure) => Promise): AzureStorageResourcePromise { + return new AzureStorageResourcePromise(this._configureInfrastructureInternal(configure)); + } + + /** @internal */ + private async _publishAsConnectionStringInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure/publishAsConnectionString', + rpcArgs + ); + return new AzureStorageResource(result, this._client); + } + + /** Publishes an Azure resource to the manifest as a connection string */ + publishAsConnectionString(): AzureStorageResourcePromise { + return new AzureStorageResourcePromise(this._publishAsConnectionStringInternal()); + } + + /** Gets the normalized Bicep identifier for an Azure resource */ + async getBicepIdentifier(): Promise { + const rpcArgs: Record = { resource: this._handle }; + return await this._client.invokeCapability( + 'Aspire.Hosting.Azure/getBicepIdentifier', + rpcArgs + ); + } + + /** @internal */ + private async _clearDefaultRoleAssignmentsInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure/clearDefaultRoleAssignments', + rpcArgs + ); + return new AzureStorageResource(result, this._client); + } + + /** Clears the default Azure role assignments from a resource */ + clearDefaultRoleAssignments(): AzureStorageResourcePromise { + return new AzureStorageResourcePromise(this._clearDefaultRoleAssignmentsInternal()); + } + + /** Determines whether a resource is marked as existing */ + async isExisting(): Promise { + const rpcArgs: Record = { resource: this._handle }; + return await this._client.invokeCapability( + 'Aspire.Hosting.Azure/isExisting', + rpcArgs + ); + } + + /** @internal */ + private async _runAsExistingFromParametersInternal(nameParameter: ParameterResource, resourceGroupParameter: ParameterResource): Promise { + const rpcArgs: Record = { builder: this._handle, nameParameter, resourceGroupParameter }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure/runAsExistingFromParameters', + rpcArgs + ); + return new AzureStorageResource(result, this._client); + } + + /** Marks an Azure resource as existing in run mode by using parameter resources */ + runAsExistingFromParameters(nameParameter: ParameterResource, resourceGroupParameter: ParameterResource): AzureStorageResourcePromise { + return new AzureStorageResourcePromise(this._runAsExistingFromParametersInternal(nameParameter, resourceGroupParameter)); + } + + /** @internal */ + private async _runAsExistingInternal(name: string, resourceGroup: string): Promise { + const rpcArgs: Record = { builder: this._handle, name, resourceGroup }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure/runAsExisting', + rpcArgs + ); + return new AzureStorageResource(result, this._client); + } + + /** Marks an Azure resource as existing in run mode */ + runAsExisting(name: string, resourceGroup: string): AzureStorageResourcePromise { + return new AzureStorageResourcePromise(this._runAsExistingInternal(name, resourceGroup)); + } + + /** @internal */ + private async _publishAsExistingFromParametersInternal(nameParameter: ParameterResource, resourceGroupParameter: ParameterResource): Promise { + const rpcArgs: Record = { builder: this._handle, nameParameter, resourceGroupParameter }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure/publishAsExistingFromParameters', + rpcArgs + ); + return new AzureStorageResource(result, this._client); + } + + /** Marks an Azure resource as existing in publish mode by using parameter resources */ + publishAsExistingFromParameters(nameParameter: ParameterResource, resourceGroupParameter: ParameterResource): AzureStorageResourcePromise { + return new AzureStorageResourcePromise(this._publishAsExistingFromParametersInternal(nameParameter, resourceGroupParameter)); + } + + /** @internal */ + private async _publishAsExistingInternal(name: string, resourceGroup: string): Promise { + const rpcArgs: Record = { builder: this._handle, name, resourceGroup }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure/publishAsExisting', + rpcArgs + ); + return new AzureStorageResource(result, this._client); + } + + /** Marks an Azure resource as existing in publish mode */ + publishAsExisting(name: string, resourceGroup: string): AzureStorageResourcePromise { + return new AzureStorageResourcePromise(this._publishAsExistingInternal(name, resourceGroup)); + } + + /** @internal */ + private async _asExistingInternal(nameParameter: ParameterResource, resourceGroupParameter: ParameterResource): Promise { + const rpcArgs: Record = { builder: this._handle, nameParameter, resourceGroupParameter }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure/asExistingFromParameters', + rpcArgs + ); + return new AzureStorageResource(result, this._client); + } + + /** Marks an Azure resource as existing in both run and publish modes by using parameter resources */ + asExisting(nameParameter: ParameterResource, resourceGroupParameter: ParameterResource): AzureStorageResourcePromise { + return new AzureStorageResourcePromise(this._asExistingInternal(nameParameter, resourceGroupParameter)); + } + +} + +/** + * Thenable wrapper for AzureStorageResource that enables fluent chaining. + * @example + * await builder.addSomething().withX().withY(); + */ +export class AzureStorageResourcePromise implements PromiseLike { + constructor(private _promise: Promise) {} + + then( + onfulfilled?: ((value: AzureStorageResource) => TResult1 | PromiseLike) | null, + onrejected?: ((reason: unknown) => TResult2 | PromiseLike) | null + ): PromiseLike { + return this._promise.then(onfulfilled, onrejected); + } + + /** Configures a resource to use a container registry */ + withContainerRegistry(registry: ResourceBuilderBase): AzureStorageResourcePromise { + return new AzureStorageResourcePromise(this._promise.then(obj => obj.withContainerRegistry(registry))); + } + + /** Sets the base image for a Dockerfile build */ + withDockerfileBaseImage(options?: WithDockerfileBaseImageOptions): AzureStorageResourcePromise { + return new AzureStorageResourcePromise(this._promise.then(obj => obj.withDockerfileBaseImage(options))); + } + + /** Configures an MCP server endpoint on the resource */ + withMcpServer(options?: WithMcpServerOptions): AzureStorageResourcePromise { + return new AzureStorageResourcePromise(this._promise.then(obj => obj.withMcpServer(options))); + } + + /** Adds a required command dependency */ + withRequiredCommand(command: string, options?: WithRequiredCommandOptions): AzureStorageResourcePromise { + return new AzureStorageResourcePromise(this._promise.then(obj => obj.withRequiredCommand(command, options))); + } + + /** Adds a network endpoint */ + withEndpoint(options?: WithEndpointOptions): AzureStorageResourcePromise { + return new AzureStorageResourcePromise(this._promise.then(obj => obj.withEndpoint(options))); + } + + /** Adds an HTTP endpoint */ + withHttpEndpoint(options?: WithHttpEndpointOptions): AzureStorageResourcePromise { + return new AzureStorageResourcePromise(this._promise.then(obj => obj.withHttpEndpoint(options))); + } + + /** Adds an HTTPS endpoint */ + withHttpsEndpoint(options?: WithHttpsEndpointOptions): AzureStorageResourcePromise { + return new AzureStorageResourcePromise(this._promise.then(obj => obj.withHttpsEndpoint(options))); + } + + /** Makes HTTP endpoints externally accessible */ + withExternalHttpEndpoints(): AzureStorageResourcePromise { + return new AzureStorageResourcePromise(this._promise.then(obj => obj.withExternalHttpEndpoints())); + } + + /** Gets an endpoint reference */ + getEndpoint(name: string): Promise { + return this._promise.then(obj => obj.getEndpoint(name)); + } + + /** Configures resource for HTTP/2 */ + asHttp2Service(): AzureStorageResourcePromise { + return new AzureStorageResourcePromise(this._promise.then(obj => obj.asHttp2Service())); + } + + /** Customizes displayed URLs via callback */ + withUrlsCallback(callback: (obj: ResourceUrlsCallbackContext) => Promise): AzureStorageResourcePromise { + return new AzureStorageResourcePromise(this._promise.then(obj => obj.withUrlsCallback(callback))); + } + + /** Customizes displayed URLs via async callback */ + withUrlsCallbackAsync(callback: (arg: ResourceUrlsCallbackContext) => Promise): AzureStorageResourcePromise { + return new AzureStorageResourcePromise(this._promise.then(obj => obj.withUrlsCallbackAsync(callback))); + } + + /** Adds or modifies displayed URLs */ + withUrl(url: string, options?: WithUrlOptions): AzureStorageResourcePromise { + return new AzureStorageResourcePromise(this._promise.then(obj => obj.withUrl(url, options))); + } + + /** Adds a URL using a reference expression */ + withUrlExpression(url: ReferenceExpression, options?: WithUrlExpressionOptions): AzureStorageResourcePromise { + return new AzureStorageResourcePromise(this._promise.then(obj => obj.withUrlExpression(url, options))); + } + + /** Customizes the URL for a specific endpoint via callback */ + withUrlForEndpoint(endpointName: string, callback: (obj: ResourceUrlAnnotation) => Promise): AzureStorageResourcePromise { + return new AzureStorageResourcePromise(this._promise.then(obj => obj.withUrlForEndpoint(endpointName, callback))); + } + + /** Adds a URL for a specific endpoint via factory callback */ + withUrlForEndpointFactory(endpointName: string, callback: (arg: EndpointReference) => Promise): AzureStorageResourcePromise { + return new AzureStorageResourcePromise(this._promise.then(obj => obj.withUrlForEndpointFactory(endpointName, callback))); + } + + /** Excludes the resource from the deployment manifest */ + excludeFromManifest(): AzureStorageResourcePromise { + return new AzureStorageResourcePromise(this._promise.then(obj => obj.excludeFromManifest())); + } + + /** Prevents resource from starting automatically */ + withExplicitStart(): AzureStorageResourcePromise { + return new AzureStorageResourcePromise(this._promise.then(obj => obj.withExplicitStart())); + } + + /** Adds a health check by key */ + withHealthCheck(key: string): AzureStorageResourcePromise { + return new AzureStorageResourcePromise(this._promise.then(obj => obj.withHealthCheck(key))); + } + + /** Adds an HTTP health check */ + withHttpHealthCheck(options?: WithHttpHealthCheckOptions): AzureStorageResourcePromise { + return new AzureStorageResourcePromise(this._promise.then(obj => obj.withHttpHealthCheck(options))); + } + + /** Adds a resource command */ + withCommand(name: string, displayName: string, executeCommand: (arg: ExecuteCommandContext) => Promise, options?: WithCommandOptions): AzureStorageResourcePromise { + return new AzureStorageResourcePromise(this._promise.then(obj => obj.withCommand(name, displayName, executeCommand, options))); + } + + /** Sets the parent relationship */ + withParentRelationship(parent: ResourceBuilderBase): AzureStorageResourcePromise { + return new AzureStorageResourcePromise(this._promise.then(obj => obj.withParentRelationship(parent))); + } + + /** Sets a child relationship */ + withChildRelationship(child: ResourceBuilderBase): AzureStorageResourcePromise { + return new AzureStorageResourcePromise(this._promise.then(obj => obj.withChildRelationship(child))); + } + + /** Sets the icon for the resource */ + withIconName(iconName: string, options?: WithIconNameOptions): AzureStorageResourcePromise { + return new AzureStorageResourcePromise(this._promise.then(obj => obj.withIconName(iconName, options))); + } + + /** Adds an HTTP health probe to the resource */ + withHttpProbe(probeType: ProbeType, options?: WithHttpProbeOptions): AzureStorageResourcePromise { + return new AzureStorageResourcePromise(this._promise.then(obj => obj.withHttpProbe(probeType, options))); + } + + /** Excludes the resource from MCP server exposure */ + excludeFromMcp(): AzureStorageResourcePromise { + return new AzureStorageResourcePromise(this._promise.then(obj => obj.excludeFromMcp())); + } + + /** Adds a pipeline step to the resource */ + withPipelineStepFactory(stepName: string, callback: (arg: PipelineStepContext) => Promise, options?: WithPipelineStepFactoryOptions): AzureStorageResourcePromise { + return new AzureStorageResourcePromise(this._promise.then(obj => obj.withPipelineStepFactory(stepName, callback, options))); + } + + /** Configures pipeline step dependencies via an async callback */ + withPipelineConfigurationAsync(callback: (arg: PipelineConfigurationContext) => Promise): AzureStorageResourcePromise { + return new AzureStorageResourcePromise(this._promise.then(obj => obj.withPipelineConfigurationAsync(callback))); + } + + /** Configures pipeline step dependencies via a callback */ + withPipelineConfiguration(callback: (obj: PipelineConfigurationContext) => Promise): AzureStorageResourcePromise { + return new AzureStorageResourcePromise(this._promise.then(obj => obj.withPipelineConfiguration(callback))); + } + + /** Gets the resource name */ + getResourceName(): Promise { + return this._promise.then(obj => obj.getResourceName()); + } + + /** Configures the Azure Storage resource to be emulated using Azurite */ + runAsEmulator(options?: RunAsEmulator1Options): AzureStorageResourcePromise { + return new AzureStorageResourcePromise(this._promise.then(obj => obj.runAsEmulator(options))); + } + + /** Adds an Azure Blob Storage resource */ + addBlobs(name: string): AzureBlobStorageResourcePromise { + return new AzureBlobStorageResourcePromise(this._promise.then(obj => obj.addBlobs(name))); + } + + /** Adds an Azure Data Lake Storage resource */ + addDataLake(name: string): AzureDataLakeStorageResourcePromise { + return new AzureDataLakeStorageResourcePromise(this._promise.then(obj => obj.addDataLake(name))); + } + + /** Adds an Azure Blob Storage container resource */ + addBlobContainer(name: string, options?: AddBlobContainerOptions): AzureBlobStorageContainerResourcePromise { + return new AzureBlobStorageContainerResourcePromise(this._promise.then(obj => obj.addBlobContainer(name, options))); + } + + /** Adds an Azure Data Lake Storage file system resource */ + addDataLakeFileSystem(name: string, options?: AddDataLakeFileSystemOptions): AzureDataLakeStorageFileSystemResourcePromise { + return new AzureDataLakeStorageFileSystemResourcePromise(this._promise.then(obj => obj.addDataLakeFileSystem(name, options))); + } + + /** Adds an Azure Table Storage resource */ + addTables(name: string): AzureTableStorageResourcePromise { + return new AzureTableStorageResourcePromise(this._promise.then(obj => obj.addTables(name))); + } + + /** Adds an Azure Queue Storage resource */ + addQueues(name: string): AzureQueueStorageResourcePromise { + return new AzureQueueStorageResourcePromise(this._promise.then(obj => obj.addQueues(name))); + } + + /** Adds an Azure Storage queue resource */ + addQueue(name: string, options?: AddQueueOptions): AzureQueueStorageQueueResourcePromise { + return new AzureQueueStorageQueueResourcePromise(this._promise.then(obj => obj.addQueue(name, options))); + } + + /** Assigns Azure Storage roles to a resource */ + withStorageRoleAssignments(target: AzureStorageResource, roles: AzureStorageRole[]): AzureStorageResourcePromise { + return new AzureStorageResourcePromise(this._promise.then(obj => obj.withStorageRoleAssignments(target, roles))); + } + + /** Assigns Event Hubs roles to a resource */ + withEventHubsRoleAssignments(target: AzureEventHubsResource, roles: AzureEventHubsRole[]): AzureStorageResourcePromise { + return new AzureStorageResourcePromise(this._promise.then(obj => obj.withEventHubsRoleAssignments(target, roles))); + } + + /** Gets an output reference from an Azure Bicep template resource */ + getOutput(name: string): Promise { + return this._promise.then(obj => obj.getOutput(name)); + } + + /** Adds a Bicep parameter without a value */ + withParameter(name: string): AzureStorageResourcePromise { + return new AzureStorageResourcePromise(this._promise.then(obj => obj.withParameter(name))); + } + + /** Adds a Bicep parameter with a string value */ + withParameterStringValue(name: string, value: string): AzureStorageResourcePromise { + return new AzureStorageResourcePromise(this._promise.then(obj => obj.withParameterStringValue(name, value))); + } + + /** Adds a Bicep parameter with a string list value */ + withParameterStringValues(name: string, value: string[]): AzureStorageResourcePromise { + return new AzureStorageResourcePromise(this._promise.then(obj => obj.withParameterStringValues(name, value))); + } + + /** Adds a Bicep parameter from a parameter resource builder */ + withParameterFromParameter(name: string, value: ParameterResource): AzureStorageResourcePromise { + return new AzureStorageResourcePromise(this._promise.then(obj => obj.withParameterFromParameter(name, value))); + } + + /** Adds a Bicep parameter from a connection string resource builder */ + withParameterFromConnectionString(name: string, value: ResourceBuilderBase): AzureStorageResourcePromise { + return new AzureStorageResourcePromise(this._promise.then(obj => obj.withParameterFromConnectionString(name, value))); + } + + /** Adds a Bicep parameter from another Bicep output reference */ + withParameterFromOutput(name: string, value: BicepOutputReference): AzureStorageResourcePromise { + return new AzureStorageResourcePromise(this._promise.then(obj => obj.withParameterFromOutput(name, value))); + } + + /** Adds a Bicep parameter from a reference expression */ + withParameterFromReferenceExpression(name: string, value: ReferenceExpression): AzureStorageResourcePromise { + return new AzureStorageResourcePromise(this._promise.then(obj => obj.withParameterFromReferenceExpression(name, value))); + } + + /** Adds a Bicep parameter from an endpoint reference */ + withParameterFromEndpoint(name: string, value: EndpointReference): AzureStorageResourcePromise { + return new AzureStorageResourcePromise(this._promise.then(obj => obj.withParameterFromEndpoint(name, value))); + } + + /** Configures the Azure provisioning infrastructure callback */ + configureInfrastructure(configure: (obj: AzureResourceInfrastructure) => Promise): AzureStorageResourcePromise { + return new AzureStorageResourcePromise(this._promise.then(obj => obj.configureInfrastructure(configure))); + } + + /** Publishes an Azure resource to the manifest as a connection string */ + publishAsConnectionString(): AzureStorageResourcePromise { + return new AzureStorageResourcePromise(this._promise.then(obj => obj.publishAsConnectionString())); + } + + /** Gets the normalized Bicep identifier for an Azure resource */ + getBicepIdentifier(): Promise { + return this._promise.then(obj => obj.getBicepIdentifier()); + } + + /** Clears the default Azure role assignments from a resource */ + clearDefaultRoleAssignments(): AzureStorageResourcePromise { + return new AzureStorageResourcePromise(this._promise.then(obj => obj.clearDefaultRoleAssignments())); + } + + /** Determines whether a resource is marked as existing */ + isExisting(): Promise { + return this._promise.then(obj => obj.isExisting()); + } + + /** Marks an Azure resource as existing in run mode by using parameter resources */ + runAsExistingFromParameters(nameParameter: ParameterResource, resourceGroupParameter: ParameterResource): AzureStorageResourcePromise { + return new AzureStorageResourcePromise(this._promise.then(obj => obj.runAsExistingFromParameters(nameParameter, resourceGroupParameter))); + } + + /** Marks an Azure resource as existing in run mode */ + runAsExisting(name: string, resourceGroup: string): AzureStorageResourcePromise { + return new AzureStorageResourcePromise(this._promise.then(obj => obj.runAsExisting(name, resourceGroup))); + } + + /** Marks an Azure resource as existing in publish mode by using parameter resources */ + publishAsExistingFromParameters(nameParameter: ParameterResource, resourceGroupParameter: ParameterResource): AzureStorageResourcePromise { + return new AzureStorageResourcePromise(this._promise.then(obj => obj.publishAsExistingFromParameters(nameParameter, resourceGroupParameter))); + } + + /** Marks an Azure resource as existing in publish mode */ + publishAsExisting(name: string, resourceGroup: string): AzureStorageResourcePromise { + return new AzureStorageResourcePromise(this._promise.then(obj => obj.publishAsExisting(name, resourceGroup))); + } + + /** Marks an Azure resource as existing in both run and publish modes by using parameter resources */ + asExisting(nameParameter: ParameterResource, resourceGroupParameter: ParameterResource): AzureStorageResourcePromise { + return new AzureStorageResourcePromise(this._promise.then(obj => obj.asExisting(nameParameter, resourceGroupParameter))); + } + +} + +// ============================================================================ +// AzureTableStorageResource +// ============================================================================ + +export class AzureTableStorageResource extends ResourceBuilderBase { + constructor(handle: AzureTableStorageResourceHandle, client: AspireClientRpc) { + super(handle, client); + } + + /** @internal */ + private async _withContainerRegistryInternal(registry: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, registry }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withContainerRegistry', + rpcArgs + ); + return new AzureTableStorageResource(result, this._client); + } + + /** Configures a resource to use a container registry */ + withContainerRegistry(registry: ResourceBuilderBase): AzureTableStorageResourcePromise { + return new AzureTableStorageResourcePromise(this._withContainerRegistryInternal(registry)); + } + + /** @internal */ + private async _withDockerfileBaseImageInternal(buildImage?: string, runtimeImage?: string): Promise { + const rpcArgs: Record = { builder: this._handle }; + if (buildImage !== undefined) rpcArgs.buildImage = buildImage; + if (runtimeImage !== undefined) rpcArgs.runtimeImage = runtimeImage; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withDockerfileBaseImage', + rpcArgs + ); + return new AzureTableStorageResource(result, this._client); + } + + /** Sets the base image for a Dockerfile build */ + withDockerfileBaseImage(options?: WithDockerfileBaseImageOptions): AzureTableStorageResourcePromise { + const buildImage = options?.buildImage; + const runtimeImage = options?.runtimeImage; + return new AzureTableStorageResourcePromise(this._withDockerfileBaseImageInternal(buildImage, runtimeImage)); + } + + /** @internal */ + private async _withRequiredCommandInternal(command: string, helpLink?: string): Promise { + const rpcArgs: Record = { builder: this._handle, command }; + if (helpLink !== undefined) rpcArgs.helpLink = helpLink; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withRequiredCommand', + rpcArgs + ); + return new AzureTableStorageResource(result, this._client); + } + + /** Adds a required command dependency */ + withRequiredCommand(command: string, options?: WithRequiredCommandOptions): AzureTableStorageResourcePromise { + const helpLink = options?.helpLink; + return new AzureTableStorageResourcePromise(this._withRequiredCommandInternal(command, helpLink)); + } + + /** @internal */ + private async _withConnectionPropertyInternal(name: string, value: ReferenceExpression): Promise { + const rpcArgs: Record = { builder: this._handle, name, value }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withConnectionProperty', + rpcArgs + ); + return new AzureTableStorageResource(result, this._client); + } + + /** Adds a connection property with a reference expression */ + withConnectionProperty(name: string, value: ReferenceExpression): AzureTableStorageResourcePromise { + return new AzureTableStorageResourcePromise(this._withConnectionPropertyInternal(name, value)); + } + + /** @internal */ + private async _withConnectionPropertyValueInternal(name: string, value: string): Promise { + const rpcArgs: Record = { builder: this._handle, name, value }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withConnectionPropertyValue', + rpcArgs + ); + return new AzureTableStorageResource(result, this._client); + } + + /** Adds a connection property with a string value */ + withConnectionPropertyValue(name: string, value: string): AzureTableStorageResourcePromise { + return new AzureTableStorageResourcePromise(this._withConnectionPropertyValueInternal(name, value)); + } + + /** @internal */ + private async _withUrlsCallbackInternal(callback: (obj: ResourceUrlsCallbackContext) => Promise): Promise { + const callbackId = registerCallback(async (objData: unknown) => { + const objHandle = wrapIfHandle(objData) as ResourceUrlsCallbackContextHandle; + const obj = new ResourceUrlsCallbackContext(objHandle, this._client); + await callback(obj); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrlsCallback', + rpcArgs + ); + return new AzureTableStorageResource(result, this._client); + } + + /** Customizes displayed URLs via callback */ + withUrlsCallback(callback: (obj: ResourceUrlsCallbackContext) => Promise): AzureTableStorageResourcePromise { + return new AzureTableStorageResourcePromise(this._withUrlsCallbackInternal(callback)); + } + + /** @internal */ + private async _withUrlsCallbackAsyncInternal(callback: (arg: ResourceUrlsCallbackContext) => Promise): Promise { + const callbackId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as ResourceUrlsCallbackContextHandle; + const arg = new ResourceUrlsCallbackContext(argHandle, this._client); + await callback(arg); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrlsCallbackAsync', + rpcArgs + ); + return new AzureTableStorageResource(result, this._client); + } + + /** Customizes displayed URLs via async callback */ + withUrlsCallbackAsync(callback: (arg: ResourceUrlsCallbackContext) => Promise): AzureTableStorageResourcePromise { + return new AzureTableStorageResourcePromise(this._withUrlsCallbackAsyncInternal(callback)); + } + + /** @internal */ + private async _withUrlInternal(url: string, displayText?: string): Promise { + const rpcArgs: Record = { builder: this._handle, url }; + if (displayText !== undefined) rpcArgs.displayText = displayText; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrl', + rpcArgs + ); + return new AzureTableStorageResource(result, this._client); + } + + /** Adds or modifies displayed URLs */ + withUrl(url: string, options?: WithUrlOptions): AzureTableStorageResourcePromise { + const displayText = options?.displayText; + return new AzureTableStorageResourcePromise(this._withUrlInternal(url, displayText)); + } + + /** @internal */ + private async _withUrlExpressionInternal(url: ReferenceExpression, displayText?: string): Promise { + const rpcArgs: Record = { builder: this._handle, url }; + if (displayText !== undefined) rpcArgs.displayText = displayText; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrlExpression', + rpcArgs + ); + return new AzureTableStorageResource(result, this._client); + } + + /** Adds a URL using a reference expression */ + withUrlExpression(url: ReferenceExpression, options?: WithUrlExpressionOptions): AzureTableStorageResourcePromise { + const displayText = options?.displayText; + return new AzureTableStorageResourcePromise(this._withUrlExpressionInternal(url, displayText)); + } + + /** @internal */ + private async _withUrlForEndpointInternal(endpointName: string, callback: (obj: ResourceUrlAnnotation) => Promise): Promise { + const callbackId = registerCallback(async (objData: unknown) => { + const obj = wrapIfHandle(objData) as ResourceUrlAnnotation; + await callback(obj); + }); + const rpcArgs: Record = { builder: this._handle, endpointName, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrlForEndpoint', + rpcArgs + ); + return new AzureTableStorageResource(result, this._client); + } + + /** Customizes the URL for a specific endpoint via callback */ + withUrlForEndpoint(endpointName: string, callback: (obj: ResourceUrlAnnotation) => Promise): AzureTableStorageResourcePromise { + return new AzureTableStorageResourcePromise(this._withUrlForEndpointInternal(endpointName, callback)); + } + + /** @internal */ + private async _excludeFromManifestInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/excludeFromManifest', + rpcArgs + ); + return new AzureTableStorageResource(result, this._client); + } + + /** Excludes the resource from the deployment manifest */ + excludeFromManifest(): AzureTableStorageResourcePromise { + return new AzureTableStorageResourcePromise(this._excludeFromManifestInternal()); + } + + /** @internal */ + private async _withExplicitStartInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withExplicitStart', + rpcArgs + ); + return new AzureTableStorageResource(result, this._client); + } + + /** Prevents resource from starting automatically */ + withExplicitStart(): AzureTableStorageResourcePromise { + return new AzureTableStorageResourcePromise(this._withExplicitStartInternal()); + } + + /** @internal */ + private async _withHealthCheckInternal(key: string): Promise { + const rpcArgs: Record = { builder: this._handle, key }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withHealthCheck', + rpcArgs + ); + return new AzureTableStorageResource(result, this._client); + } + + /** Adds a health check by key */ + withHealthCheck(key: string): AzureTableStorageResourcePromise { + return new AzureTableStorageResourcePromise(this._withHealthCheckInternal(key)); + } + + /** @internal */ + private async _withCommandInternal(name: string, displayName: string, executeCommand: (arg: ExecuteCommandContext) => Promise, commandOptions?: CommandOptions): Promise { + const executeCommandId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as ExecuteCommandContextHandle; + const arg = new ExecuteCommandContext(argHandle, this._client); + return await executeCommand(arg); + }); + const rpcArgs: Record = { builder: this._handle, name, displayName, executeCommand: executeCommandId }; + if (commandOptions !== undefined) rpcArgs.commandOptions = commandOptions; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withCommand', + rpcArgs + ); + return new AzureTableStorageResource(result, this._client); + } + + /** Adds a resource command */ + withCommand(name: string, displayName: string, executeCommand: (arg: ExecuteCommandContext) => Promise, options?: WithCommandOptions): AzureTableStorageResourcePromise { + const commandOptions = options?.commandOptions; + return new AzureTableStorageResourcePromise(this._withCommandInternal(name, displayName, executeCommand, commandOptions)); + } + + /** @internal */ + private async _withParentRelationshipInternal(parent: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, parent }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withParentRelationship', + rpcArgs + ); + return new AzureTableStorageResource(result, this._client); + } + + /** Sets the parent relationship */ + withParentRelationship(parent: ResourceBuilderBase): AzureTableStorageResourcePromise { + return new AzureTableStorageResourcePromise(this._withParentRelationshipInternal(parent)); + } + + /** @internal */ + private async _withChildRelationshipInternal(child: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, child }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withChildRelationship', + rpcArgs + ); + return new AzureTableStorageResource(result, this._client); + } + + /** Sets a child relationship */ + withChildRelationship(child: ResourceBuilderBase): AzureTableStorageResourcePromise { + return new AzureTableStorageResourcePromise(this._withChildRelationshipInternal(child)); + } + + /** @internal */ + private async _withIconNameInternal(iconName: string, iconVariant?: IconVariant): Promise { + const rpcArgs: Record = { builder: this._handle, iconName }; + if (iconVariant !== undefined) rpcArgs.iconVariant = iconVariant; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withIconName', + rpcArgs + ); + return new AzureTableStorageResource(result, this._client); + } + + /** Sets the icon for the resource */ + withIconName(iconName: string, options?: WithIconNameOptions): AzureTableStorageResourcePromise { + const iconVariant = options?.iconVariant; + return new AzureTableStorageResourcePromise(this._withIconNameInternal(iconName, iconVariant)); + } + + /** @internal */ + private async _excludeFromMcpInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/excludeFromMcp', + rpcArgs + ); + return new AzureTableStorageResource(result, this._client); + } + + /** Excludes the resource from MCP server exposure */ + excludeFromMcp(): AzureTableStorageResourcePromise { + return new AzureTableStorageResourcePromise(this._excludeFromMcpInternal()); + } + + /** @internal */ + private async _withPipelineStepFactoryInternal(stepName: string, callback: (arg: PipelineStepContext) => Promise, dependsOn?: string[], requiredBy?: string[], tags?: string[], description?: string): Promise { + const callbackId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as PipelineStepContextHandle; + const arg = new PipelineStepContext(argHandle, this._client); + await callback(arg); + }); + const rpcArgs: Record = { builder: this._handle, stepName, callback: callbackId }; + if (dependsOn !== undefined) rpcArgs.dependsOn = dependsOn; + if (requiredBy !== undefined) rpcArgs.requiredBy = requiredBy; + if (tags !== undefined) rpcArgs.tags = tags; + if (description !== undefined) rpcArgs.description = description; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withPipelineStepFactory', + rpcArgs + ); + return new AzureTableStorageResource(result, this._client); + } + + /** Adds a pipeline step to the resource */ + withPipelineStepFactory(stepName: string, callback: (arg: PipelineStepContext) => Promise, options?: WithPipelineStepFactoryOptions): AzureTableStorageResourcePromise { + const dependsOn = options?.dependsOn; + const requiredBy = options?.requiredBy; + const tags = options?.tags; + const description = options?.description; + return new AzureTableStorageResourcePromise(this._withPipelineStepFactoryInternal(stepName, callback, dependsOn, requiredBy, tags, description)); + } + + /** @internal */ + private async _withPipelineConfigurationAsyncInternal(callback: (arg: PipelineConfigurationContext) => Promise): Promise { + const callbackId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as PipelineConfigurationContextHandle; + const arg = new PipelineConfigurationContext(argHandle, this._client); + await callback(arg); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withPipelineConfigurationAsync', + rpcArgs + ); + return new AzureTableStorageResource(result, this._client); + } + + /** Configures pipeline step dependencies via an async callback */ + withPipelineConfigurationAsync(callback: (arg: PipelineConfigurationContext) => Promise): AzureTableStorageResourcePromise { + return new AzureTableStorageResourcePromise(this._withPipelineConfigurationAsyncInternal(callback)); + } + + /** @internal */ + private async _withPipelineConfigurationInternal(callback: (obj: PipelineConfigurationContext) => Promise): Promise { + const callbackId = registerCallback(async (objData: unknown) => { + const objHandle = wrapIfHandle(objData) as PipelineConfigurationContextHandle; + const obj = new PipelineConfigurationContext(objHandle, this._client); + await callback(obj); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withPipelineConfiguration', + rpcArgs + ); + return new AzureTableStorageResource(result, this._client); + } + + /** Configures pipeline step dependencies via a callback */ + withPipelineConfiguration(callback: (obj: PipelineConfigurationContext) => Promise): AzureTableStorageResourcePromise { + return new AzureTableStorageResourcePromise(this._withPipelineConfigurationInternal(callback)); + } + + /** Gets the resource name */ + async getResourceName(): Promise { + const rpcArgs: Record = { resource: this._handle }; + return await this._client.invokeCapability( + 'Aspire.Hosting/getResourceName', + rpcArgs + ); + } + + /** @internal */ + private async _withStorageRoleAssignmentsInternal(target: AzureStorageResource, roles: AzureStorageRole[]): Promise { + const rpcArgs: Record = { builder: this._handle, target, roles }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure.Storage/withStorageRoleAssignments', + rpcArgs + ); + return new AzureTableStorageResource(result, this._client); + } + + /** Assigns Azure Storage roles to a resource */ + withStorageRoleAssignments(target: AzureStorageResource, roles: AzureStorageRole[]): AzureTableStorageResourcePromise { + return new AzureTableStorageResourcePromise(this._withStorageRoleAssignmentsInternal(target, roles)); + } + + /** @internal */ + private async _withEventHubsRoleAssignmentsInternal(target: AzureEventHubsResource, roles: AzureEventHubsRole[]): Promise { + const rpcArgs: Record = { builder: this._handle, target, roles }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure.EventHubs/withEventHubsRoleAssignments', + rpcArgs + ); + return new AzureTableStorageResource(result, this._client); + } + + /** Assigns Event Hubs roles to a resource */ + withEventHubsRoleAssignments(target: AzureEventHubsResource, roles: AzureEventHubsRole[]): AzureTableStorageResourcePromise { + return new AzureTableStorageResourcePromise(this._withEventHubsRoleAssignmentsInternal(target, roles)); + } + +} + +/** + * Thenable wrapper for AzureTableStorageResource that enables fluent chaining. + * @example + * await builder.addSomething().withX().withY(); + */ +export class AzureTableStorageResourcePromise implements PromiseLike { + constructor(private _promise: Promise) {} + + then( + onfulfilled?: ((value: AzureTableStorageResource) => TResult1 | PromiseLike) | null, + onrejected?: ((reason: unknown) => TResult2 | PromiseLike) | null + ): PromiseLike { + return this._promise.then(onfulfilled, onrejected); + } + + /** Configures a resource to use a container registry */ + withContainerRegistry(registry: ResourceBuilderBase): AzureTableStorageResourcePromise { + return new AzureTableStorageResourcePromise(this._promise.then(obj => obj.withContainerRegistry(registry))); + } + + /** Sets the base image for a Dockerfile build */ + withDockerfileBaseImage(options?: WithDockerfileBaseImageOptions): AzureTableStorageResourcePromise { + return new AzureTableStorageResourcePromise(this._promise.then(obj => obj.withDockerfileBaseImage(options))); + } + + /** Adds a required command dependency */ + withRequiredCommand(command: string, options?: WithRequiredCommandOptions): AzureTableStorageResourcePromise { + return new AzureTableStorageResourcePromise(this._promise.then(obj => obj.withRequiredCommand(command, options))); + } + + /** Adds a connection property with a reference expression */ + withConnectionProperty(name: string, value: ReferenceExpression): AzureTableStorageResourcePromise { + return new AzureTableStorageResourcePromise(this._promise.then(obj => obj.withConnectionProperty(name, value))); + } + + /** Adds a connection property with a string value */ + withConnectionPropertyValue(name: string, value: string): AzureTableStorageResourcePromise { + return new AzureTableStorageResourcePromise(this._promise.then(obj => obj.withConnectionPropertyValue(name, value))); + } + + /** Customizes displayed URLs via callback */ + withUrlsCallback(callback: (obj: ResourceUrlsCallbackContext) => Promise): AzureTableStorageResourcePromise { + return new AzureTableStorageResourcePromise(this._promise.then(obj => obj.withUrlsCallback(callback))); + } + + /** Customizes displayed URLs via async callback */ + withUrlsCallbackAsync(callback: (arg: ResourceUrlsCallbackContext) => Promise): AzureTableStorageResourcePromise { + return new AzureTableStorageResourcePromise(this._promise.then(obj => obj.withUrlsCallbackAsync(callback))); + } + + /** Adds or modifies displayed URLs */ + withUrl(url: string, options?: WithUrlOptions): AzureTableStorageResourcePromise { + return new AzureTableStorageResourcePromise(this._promise.then(obj => obj.withUrl(url, options))); + } + + /** Adds a URL using a reference expression */ + withUrlExpression(url: ReferenceExpression, options?: WithUrlExpressionOptions): AzureTableStorageResourcePromise { + return new AzureTableStorageResourcePromise(this._promise.then(obj => obj.withUrlExpression(url, options))); + } + + /** Customizes the URL for a specific endpoint via callback */ + withUrlForEndpoint(endpointName: string, callback: (obj: ResourceUrlAnnotation) => Promise): AzureTableStorageResourcePromise { + return new AzureTableStorageResourcePromise(this._promise.then(obj => obj.withUrlForEndpoint(endpointName, callback))); + } + + /** Excludes the resource from the deployment manifest */ + excludeFromManifest(): AzureTableStorageResourcePromise { + return new AzureTableStorageResourcePromise(this._promise.then(obj => obj.excludeFromManifest())); + } + + /** Prevents resource from starting automatically */ + withExplicitStart(): AzureTableStorageResourcePromise { + return new AzureTableStorageResourcePromise(this._promise.then(obj => obj.withExplicitStart())); + } + + /** Adds a health check by key */ + withHealthCheck(key: string): AzureTableStorageResourcePromise { + return new AzureTableStorageResourcePromise(this._promise.then(obj => obj.withHealthCheck(key))); + } + + /** Adds a resource command */ + withCommand(name: string, displayName: string, executeCommand: (arg: ExecuteCommandContext) => Promise, options?: WithCommandOptions): AzureTableStorageResourcePromise { + return new AzureTableStorageResourcePromise(this._promise.then(obj => obj.withCommand(name, displayName, executeCommand, options))); + } + + /** Sets the parent relationship */ + withParentRelationship(parent: ResourceBuilderBase): AzureTableStorageResourcePromise { + return new AzureTableStorageResourcePromise(this._promise.then(obj => obj.withParentRelationship(parent))); + } + + /** Sets a child relationship */ + withChildRelationship(child: ResourceBuilderBase): AzureTableStorageResourcePromise { + return new AzureTableStorageResourcePromise(this._promise.then(obj => obj.withChildRelationship(child))); + } + + /** Sets the icon for the resource */ + withIconName(iconName: string, options?: WithIconNameOptions): AzureTableStorageResourcePromise { + return new AzureTableStorageResourcePromise(this._promise.then(obj => obj.withIconName(iconName, options))); + } + + /** Excludes the resource from MCP server exposure */ + excludeFromMcp(): AzureTableStorageResourcePromise { + return new AzureTableStorageResourcePromise(this._promise.then(obj => obj.excludeFromMcp())); + } + + /** Adds a pipeline step to the resource */ + withPipelineStepFactory(stepName: string, callback: (arg: PipelineStepContext) => Promise, options?: WithPipelineStepFactoryOptions): AzureTableStorageResourcePromise { + return new AzureTableStorageResourcePromise(this._promise.then(obj => obj.withPipelineStepFactory(stepName, callback, options))); + } + + /** Configures pipeline step dependencies via an async callback */ + withPipelineConfigurationAsync(callback: (arg: PipelineConfigurationContext) => Promise): AzureTableStorageResourcePromise { + return new AzureTableStorageResourcePromise(this._promise.then(obj => obj.withPipelineConfigurationAsync(callback))); + } + + /** Configures pipeline step dependencies via a callback */ + withPipelineConfiguration(callback: (obj: PipelineConfigurationContext) => Promise): AzureTableStorageResourcePromise { + return new AzureTableStorageResourcePromise(this._promise.then(obj => obj.withPipelineConfiguration(callback))); + } + + /** Gets the resource name */ + getResourceName(): Promise { + return this._promise.then(obj => obj.getResourceName()); + } + + /** Assigns Azure Storage roles to a resource */ + withStorageRoleAssignments(target: AzureStorageResource, roles: AzureStorageRole[]): AzureTableStorageResourcePromise { + return new AzureTableStorageResourcePromise(this._promise.then(obj => obj.withStorageRoleAssignments(target, roles))); + } + + /** Assigns Event Hubs roles to a resource */ + withEventHubsRoleAssignments(target: AzureEventHubsResource, roles: AzureEventHubsRole[]): AzureTableStorageResourcePromise { + return new AzureTableStorageResourcePromise(this._promise.then(obj => obj.withEventHubsRoleAssignments(target, roles))); + } + +} + +// ============================================================================ +// AzureUserAssignedIdentityResource +// ============================================================================ + +export class AzureUserAssignedIdentityResource extends ResourceBuilderBase { + constructor(handle: AzureUserAssignedIdentityResourceHandle, client: AspireClientRpc) { + super(handle, client); + } + + /** @internal */ + private async _withContainerRegistryInternal(registry: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, registry }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withContainerRegistry', + rpcArgs + ); + return new AzureUserAssignedIdentityResource(result, this._client); + } + + /** Configures a resource to use a container registry */ + withContainerRegistry(registry: ResourceBuilderBase): AzureUserAssignedIdentityResourcePromise { + return new AzureUserAssignedIdentityResourcePromise(this._withContainerRegistryInternal(registry)); + } + + /** @internal */ + private async _withDockerfileBaseImageInternal(buildImage?: string, runtimeImage?: string): Promise { + const rpcArgs: Record = { builder: this._handle }; + if (buildImage !== undefined) rpcArgs.buildImage = buildImage; + if (runtimeImage !== undefined) rpcArgs.runtimeImage = runtimeImage; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withDockerfileBaseImage', + rpcArgs + ); + return new AzureUserAssignedIdentityResource(result, this._client); + } + + /** Sets the base image for a Dockerfile build */ + withDockerfileBaseImage(options?: WithDockerfileBaseImageOptions): AzureUserAssignedIdentityResourcePromise { + const buildImage = options?.buildImage; + const runtimeImage = options?.runtimeImage; + return new AzureUserAssignedIdentityResourcePromise(this._withDockerfileBaseImageInternal(buildImage, runtimeImage)); + } + + /** @internal */ + private async _withRequiredCommandInternal(command: string, helpLink?: string): Promise { + const rpcArgs: Record = { builder: this._handle, command }; + if (helpLink !== undefined) rpcArgs.helpLink = helpLink; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withRequiredCommand', + rpcArgs + ); + return new AzureUserAssignedIdentityResource(result, this._client); + } + + /** Adds a required command dependency */ + withRequiredCommand(command: string, options?: WithRequiredCommandOptions): AzureUserAssignedIdentityResourcePromise { + const helpLink = options?.helpLink; + return new AzureUserAssignedIdentityResourcePromise(this._withRequiredCommandInternal(command, helpLink)); + } + + /** @internal */ + private async _withUrlsCallbackInternal(callback: (obj: ResourceUrlsCallbackContext) => Promise): Promise { + const callbackId = registerCallback(async (objData: unknown) => { + const objHandle = wrapIfHandle(objData) as ResourceUrlsCallbackContextHandle; + const obj = new ResourceUrlsCallbackContext(objHandle, this._client); + await callback(obj); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrlsCallback', + rpcArgs + ); + return new AzureUserAssignedIdentityResource(result, this._client); + } + + /** Customizes displayed URLs via callback */ + withUrlsCallback(callback: (obj: ResourceUrlsCallbackContext) => Promise): AzureUserAssignedIdentityResourcePromise { + return new AzureUserAssignedIdentityResourcePromise(this._withUrlsCallbackInternal(callback)); + } + + /** @internal */ + private async _withUrlsCallbackAsyncInternal(callback: (arg: ResourceUrlsCallbackContext) => Promise): Promise { + const callbackId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as ResourceUrlsCallbackContextHandle; + const arg = new ResourceUrlsCallbackContext(argHandle, this._client); + await callback(arg); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrlsCallbackAsync', + rpcArgs + ); + return new AzureUserAssignedIdentityResource(result, this._client); + } + + /** Customizes displayed URLs via async callback */ + withUrlsCallbackAsync(callback: (arg: ResourceUrlsCallbackContext) => Promise): AzureUserAssignedIdentityResourcePromise { + return new AzureUserAssignedIdentityResourcePromise(this._withUrlsCallbackAsyncInternal(callback)); + } + + /** @internal */ + private async _withUrlInternal(url: string, displayText?: string): Promise { + const rpcArgs: Record = { builder: this._handle, url }; + if (displayText !== undefined) rpcArgs.displayText = displayText; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrl', + rpcArgs + ); + return new AzureUserAssignedIdentityResource(result, this._client); + } + + /** Adds or modifies displayed URLs */ + withUrl(url: string, options?: WithUrlOptions): AzureUserAssignedIdentityResourcePromise { + const displayText = options?.displayText; + return new AzureUserAssignedIdentityResourcePromise(this._withUrlInternal(url, displayText)); + } + + /** @internal */ + private async _withUrlExpressionInternal(url: ReferenceExpression, displayText?: string): Promise { + const rpcArgs: Record = { builder: this._handle, url }; + if (displayText !== undefined) rpcArgs.displayText = displayText; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrlExpression', + rpcArgs + ); + return new AzureUserAssignedIdentityResource(result, this._client); + } + + /** Adds a URL using a reference expression */ + withUrlExpression(url: ReferenceExpression, options?: WithUrlExpressionOptions): AzureUserAssignedIdentityResourcePromise { + const displayText = options?.displayText; + return new AzureUserAssignedIdentityResourcePromise(this._withUrlExpressionInternal(url, displayText)); + } + + /** @internal */ + private async _withUrlForEndpointInternal(endpointName: string, callback: (obj: ResourceUrlAnnotation) => Promise): Promise { + const callbackId = registerCallback(async (objData: unknown) => { + const obj = wrapIfHandle(objData) as ResourceUrlAnnotation; + await callback(obj); + }); + const rpcArgs: Record = { builder: this._handle, endpointName, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrlForEndpoint', + rpcArgs + ); + return new AzureUserAssignedIdentityResource(result, this._client); + } + + /** Customizes the URL for a specific endpoint via callback */ + withUrlForEndpoint(endpointName: string, callback: (obj: ResourceUrlAnnotation) => Promise): AzureUserAssignedIdentityResourcePromise { + return new AzureUserAssignedIdentityResourcePromise(this._withUrlForEndpointInternal(endpointName, callback)); + } + + /** @internal */ + private async _excludeFromManifestInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/excludeFromManifest', + rpcArgs + ); + return new AzureUserAssignedIdentityResource(result, this._client); + } + + /** Excludes the resource from the deployment manifest */ + excludeFromManifest(): AzureUserAssignedIdentityResourcePromise { + return new AzureUserAssignedIdentityResourcePromise(this._excludeFromManifestInternal()); + } + + /** @internal */ + private async _withExplicitStartInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withExplicitStart', + rpcArgs + ); + return new AzureUserAssignedIdentityResource(result, this._client); + } + + /** Prevents resource from starting automatically */ + withExplicitStart(): AzureUserAssignedIdentityResourcePromise { + return new AzureUserAssignedIdentityResourcePromise(this._withExplicitStartInternal()); + } + + /** @internal */ + private async _withHealthCheckInternal(key: string): Promise { + const rpcArgs: Record = { builder: this._handle, key }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withHealthCheck', + rpcArgs + ); + return new AzureUserAssignedIdentityResource(result, this._client); + } + + /** Adds a health check by key */ + withHealthCheck(key: string): AzureUserAssignedIdentityResourcePromise { + return new AzureUserAssignedIdentityResourcePromise(this._withHealthCheckInternal(key)); + } + + /** @internal */ + private async _withCommandInternal(name: string, displayName: string, executeCommand: (arg: ExecuteCommandContext) => Promise, commandOptions?: CommandOptions): Promise { + const executeCommandId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as ExecuteCommandContextHandle; + const arg = new ExecuteCommandContext(argHandle, this._client); + return await executeCommand(arg); + }); + const rpcArgs: Record = { builder: this._handle, name, displayName, executeCommand: executeCommandId }; + if (commandOptions !== undefined) rpcArgs.commandOptions = commandOptions; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withCommand', + rpcArgs + ); + return new AzureUserAssignedIdentityResource(result, this._client); + } + + /** Adds a resource command */ + withCommand(name: string, displayName: string, executeCommand: (arg: ExecuteCommandContext) => Promise, options?: WithCommandOptions): AzureUserAssignedIdentityResourcePromise { + const commandOptions = options?.commandOptions; + return new AzureUserAssignedIdentityResourcePromise(this._withCommandInternal(name, displayName, executeCommand, commandOptions)); + } + + /** @internal */ + private async _withParentRelationshipInternal(parent: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, parent }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withParentRelationship', + rpcArgs + ); + return new AzureUserAssignedIdentityResource(result, this._client); + } + + /** Sets the parent relationship */ + withParentRelationship(parent: ResourceBuilderBase): AzureUserAssignedIdentityResourcePromise { + return new AzureUserAssignedIdentityResourcePromise(this._withParentRelationshipInternal(parent)); + } + + /** @internal */ + private async _withChildRelationshipInternal(child: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, child }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withChildRelationship', + rpcArgs + ); + return new AzureUserAssignedIdentityResource(result, this._client); + } + + /** Sets a child relationship */ + withChildRelationship(child: ResourceBuilderBase): AzureUserAssignedIdentityResourcePromise { + return new AzureUserAssignedIdentityResourcePromise(this._withChildRelationshipInternal(child)); + } + + /** @internal */ + private async _withIconNameInternal(iconName: string, iconVariant?: IconVariant): Promise { + const rpcArgs: Record = { builder: this._handle, iconName }; + if (iconVariant !== undefined) rpcArgs.iconVariant = iconVariant; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withIconName', + rpcArgs + ); + return new AzureUserAssignedIdentityResource(result, this._client); + } + + /** Sets the icon for the resource */ + withIconName(iconName: string, options?: WithIconNameOptions): AzureUserAssignedIdentityResourcePromise { + const iconVariant = options?.iconVariant; + return new AzureUserAssignedIdentityResourcePromise(this._withIconNameInternal(iconName, iconVariant)); + } + + /** @internal */ + private async _excludeFromMcpInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/excludeFromMcp', + rpcArgs + ); + return new AzureUserAssignedIdentityResource(result, this._client); + } + + /** Excludes the resource from MCP server exposure */ + excludeFromMcp(): AzureUserAssignedIdentityResourcePromise { + return new AzureUserAssignedIdentityResourcePromise(this._excludeFromMcpInternal()); + } + + /** @internal */ + private async _withPipelineStepFactoryInternal(stepName: string, callback: (arg: PipelineStepContext) => Promise, dependsOn?: string[], requiredBy?: string[], tags?: string[], description?: string): Promise { + const callbackId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as PipelineStepContextHandle; + const arg = new PipelineStepContext(argHandle, this._client); + await callback(arg); + }); + const rpcArgs: Record = { builder: this._handle, stepName, callback: callbackId }; + if (dependsOn !== undefined) rpcArgs.dependsOn = dependsOn; + if (requiredBy !== undefined) rpcArgs.requiredBy = requiredBy; + if (tags !== undefined) rpcArgs.tags = tags; + if (description !== undefined) rpcArgs.description = description; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withPipelineStepFactory', + rpcArgs + ); + return new AzureUserAssignedIdentityResource(result, this._client); + } + + /** Adds a pipeline step to the resource */ + withPipelineStepFactory(stepName: string, callback: (arg: PipelineStepContext) => Promise, options?: WithPipelineStepFactoryOptions): AzureUserAssignedIdentityResourcePromise { + const dependsOn = options?.dependsOn; + const requiredBy = options?.requiredBy; + const tags = options?.tags; + const description = options?.description; + return new AzureUserAssignedIdentityResourcePromise(this._withPipelineStepFactoryInternal(stepName, callback, dependsOn, requiredBy, tags, description)); + } + + /** @internal */ + private async _withPipelineConfigurationAsyncInternal(callback: (arg: PipelineConfigurationContext) => Promise): Promise { + const callbackId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as PipelineConfigurationContextHandle; + const arg = new PipelineConfigurationContext(argHandle, this._client); + await callback(arg); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withPipelineConfigurationAsync', + rpcArgs + ); + return new AzureUserAssignedIdentityResource(result, this._client); + } + + /** Configures pipeline step dependencies via an async callback */ + withPipelineConfigurationAsync(callback: (arg: PipelineConfigurationContext) => Promise): AzureUserAssignedIdentityResourcePromise { + return new AzureUserAssignedIdentityResourcePromise(this._withPipelineConfigurationAsyncInternal(callback)); + } + + /** @internal */ + private async _withPipelineConfigurationInternal(callback: (obj: PipelineConfigurationContext) => Promise): Promise { + const callbackId = registerCallback(async (objData: unknown) => { + const objHandle = wrapIfHandle(objData) as PipelineConfigurationContextHandle; + const obj = new PipelineConfigurationContext(objHandle, this._client); + await callback(obj); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withPipelineConfiguration', + rpcArgs + ); + return new AzureUserAssignedIdentityResource(result, this._client); + } + + /** Configures pipeline step dependencies via a callback */ + withPipelineConfiguration(callback: (obj: PipelineConfigurationContext) => Promise): AzureUserAssignedIdentityResourcePromise { + return new AzureUserAssignedIdentityResourcePromise(this._withPipelineConfigurationInternal(callback)); + } + + /** Gets the resource name */ + async getResourceName(): Promise { + const rpcArgs: Record = { resource: this._handle }; + return await this._client.invokeCapability( + 'Aspire.Hosting/getResourceName', + rpcArgs + ); + } + + /** @internal */ + private async _withStorageRoleAssignmentsInternal(target: AzureStorageResource, roles: AzureStorageRole[]): Promise { + const rpcArgs: Record = { builder: this._handle, target, roles }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure.Storage/withStorageRoleAssignments', + rpcArgs + ); + return new AzureUserAssignedIdentityResource(result, this._client); + } + + /** Assigns Azure Storage roles to a resource */ + withStorageRoleAssignments(target: AzureStorageResource, roles: AzureStorageRole[]): AzureUserAssignedIdentityResourcePromise { + return new AzureUserAssignedIdentityResourcePromise(this._withStorageRoleAssignmentsInternal(target, roles)); + } + + /** @internal */ + private async _withEventHubsRoleAssignmentsInternal(target: AzureEventHubsResource, roles: AzureEventHubsRole[]): Promise { + const rpcArgs: Record = { builder: this._handle, target, roles }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure.EventHubs/withEventHubsRoleAssignments', + rpcArgs + ); + return new AzureUserAssignedIdentityResource(result, this._client); + } + + /** Assigns Event Hubs roles to a resource */ + withEventHubsRoleAssignments(target: AzureEventHubsResource, roles: AzureEventHubsRole[]): AzureUserAssignedIdentityResourcePromise { + return new AzureUserAssignedIdentityResourcePromise(this._withEventHubsRoleAssignmentsInternal(target, roles)); + } + + /** Gets an output reference from an Azure Bicep template resource */ + async getOutput(name: string): Promise { + const rpcArgs: Record = { builder: this._handle, name }; + return await this._client.invokeCapability( + 'Aspire.Hosting.Azure/getOutput', + rpcArgs + ); + } + + /** @internal */ + private async _withParameterInternal(name: string): Promise { + const rpcArgs: Record = { builder: this._handle, name }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure/withParameter', + rpcArgs + ); + return new AzureUserAssignedIdentityResource(result, this._client); + } + + /** Adds a Bicep parameter without a value */ + withParameter(name: string): AzureUserAssignedIdentityResourcePromise { + return new AzureUserAssignedIdentityResourcePromise(this._withParameterInternal(name)); + } + + /** @internal */ + private async _withParameterStringValueInternal(name: string, value: string): Promise { + const rpcArgs: Record = { builder: this._handle, name, value }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure/withParameterStringValue', + rpcArgs + ); + return new AzureUserAssignedIdentityResource(result, this._client); + } + + /** Adds a Bicep parameter with a string value */ + withParameterStringValue(name: string, value: string): AzureUserAssignedIdentityResourcePromise { + return new AzureUserAssignedIdentityResourcePromise(this._withParameterStringValueInternal(name, value)); + } + + /** @internal */ + private async _withParameterStringValuesInternal(name: string, value: string[]): Promise { + const rpcArgs: Record = { builder: this._handle, name, value }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure/withParameterStringValues', + rpcArgs + ); + return new AzureUserAssignedIdentityResource(result, this._client); + } + + /** Adds a Bicep parameter with a string list value */ + withParameterStringValues(name: string, value: string[]): AzureUserAssignedIdentityResourcePromise { + return new AzureUserAssignedIdentityResourcePromise(this._withParameterStringValuesInternal(name, value)); + } + + /** @internal */ + private async _withParameterFromParameterInternal(name: string, value: ParameterResource): Promise { + const rpcArgs: Record = { builder: this._handle, name, value }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure/withParameterFromParameter', + rpcArgs + ); + return new AzureUserAssignedIdentityResource(result, this._client); + } + + /** Adds a Bicep parameter from a parameter resource builder */ + withParameterFromParameter(name: string, value: ParameterResource): AzureUserAssignedIdentityResourcePromise { + return new AzureUserAssignedIdentityResourcePromise(this._withParameterFromParameterInternal(name, value)); + } + + /** @internal */ + private async _withParameterFromConnectionStringInternal(name: string, value: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, name, value }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure/withParameterFromConnectionString', + rpcArgs + ); + return new AzureUserAssignedIdentityResource(result, this._client); + } + + /** Adds a Bicep parameter from a connection string resource builder */ + withParameterFromConnectionString(name: string, value: ResourceBuilderBase): AzureUserAssignedIdentityResourcePromise { + return new AzureUserAssignedIdentityResourcePromise(this._withParameterFromConnectionStringInternal(name, value)); + } + + /** @internal */ + private async _withParameterFromOutputInternal(name: string, value: BicepOutputReference): Promise { + const rpcArgs: Record = { builder: this._handle, name, value }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure/withParameterFromOutput', + rpcArgs + ); + return new AzureUserAssignedIdentityResource(result, this._client); + } + + /** Adds a Bicep parameter from another Bicep output reference */ + withParameterFromOutput(name: string, value: BicepOutputReference): AzureUserAssignedIdentityResourcePromise { + return new AzureUserAssignedIdentityResourcePromise(this._withParameterFromOutputInternal(name, value)); + } + + /** @internal */ + private async _withParameterFromReferenceExpressionInternal(name: string, value: ReferenceExpression): Promise { + const rpcArgs: Record = { builder: this._handle, name, value }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure/withParameterFromReferenceExpression', + rpcArgs + ); + return new AzureUserAssignedIdentityResource(result, this._client); + } + + /** Adds a Bicep parameter from a reference expression */ + withParameterFromReferenceExpression(name: string, value: ReferenceExpression): AzureUserAssignedIdentityResourcePromise { + return new AzureUserAssignedIdentityResourcePromise(this._withParameterFromReferenceExpressionInternal(name, value)); + } + + /** @internal */ + private async _withParameterFromEndpointInternal(name: string, value: EndpointReference): Promise { + const rpcArgs: Record = { builder: this._handle, name, value }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure/withParameterFromEndpoint', + rpcArgs + ); + return new AzureUserAssignedIdentityResource(result, this._client); + } + + /** Adds a Bicep parameter from an endpoint reference */ + withParameterFromEndpoint(name: string, value: EndpointReference): AzureUserAssignedIdentityResourcePromise { + return new AzureUserAssignedIdentityResourcePromise(this._withParameterFromEndpointInternal(name, value)); + } + + /** @internal */ + private async _configureInfrastructureInternal(configure: (obj: AzureResourceInfrastructure) => Promise): Promise { + const configureId = registerCallback(async (objData: unknown) => { + const objHandle = wrapIfHandle(objData) as AzureResourceInfrastructureHandle; + const obj = new AzureResourceInfrastructure(objHandle, this._client); + await configure(obj); + }); + const rpcArgs: Record = { builder: this._handle, configure: configureId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure/configureInfrastructure', + rpcArgs + ); + return new AzureUserAssignedIdentityResource(result, this._client); + } + + /** Configures the Azure provisioning infrastructure callback */ + configureInfrastructure(configure: (obj: AzureResourceInfrastructure) => Promise): AzureUserAssignedIdentityResourcePromise { + return new AzureUserAssignedIdentityResourcePromise(this._configureInfrastructureInternal(configure)); + } + + /** @internal */ + private async _publishAsConnectionStringInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure/publishAsConnectionString', + rpcArgs + ); + return new AzureUserAssignedIdentityResource(result, this._client); + } + + /** Publishes an Azure resource to the manifest as a connection string */ + publishAsConnectionString(): AzureUserAssignedIdentityResourcePromise { + return new AzureUserAssignedIdentityResourcePromise(this._publishAsConnectionStringInternal()); + } + + /** Gets the normalized Bicep identifier for an Azure resource */ + async getBicepIdentifier(): Promise { + const rpcArgs: Record = { resource: this._handle }; + return await this._client.invokeCapability( + 'Aspire.Hosting.Azure/getBicepIdentifier', + rpcArgs + ); + } + + /** @internal */ + private async _clearDefaultRoleAssignmentsInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure/clearDefaultRoleAssignments', + rpcArgs + ); + return new AzureUserAssignedIdentityResource(result, this._client); + } + + /** Clears the default Azure role assignments from a resource */ + clearDefaultRoleAssignments(): AzureUserAssignedIdentityResourcePromise { + return new AzureUserAssignedIdentityResourcePromise(this._clearDefaultRoleAssignmentsInternal()); + } + + /** Determines whether a resource is marked as existing */ + async isExisting(): Promise { + const rpcArgs: Record = { resource: this._handle }; + return await this._client.invokeCapability( + 'Aspire.Hosting.Azure/isExisting', + rpcArgs + ); + } + + /** @internal */ + private async _runAsExistingFromParametersInternal(nameParameter: ParameterResource, resourceGroupParameter: ParameterResource): Promise { + const rpcArgs: Record = { builder: this._handle, nameParameter, resourceGroupParameter }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure/runAsExistingFromParameters', + rpcArgs + ); + return new AzureUserAssignedIdentityResource(result, this._client); + } + + /** Marks an Azure resource as existing in run mode by using parameter resources */ + runAsExistingFromParameters(nameParameter: ParameterResource, resourceGroupParameter: ParameterResource): AzureUserAssignedIdentityResourcePromise { + return new AzureUserAssignedIdentityResourcePromise(this._runAsExistingFromParametersInternal(nameParameter, resourceGroupParameter)); + } + + /** @internal */ + private async _runAsExistingInternal(name: string, resourceGroup: string): Promise { + const rpcArgs: Record = { builder: this._handle, name, resourceGroup }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure/runAsExisting', + rpcArgs + ); + return new AzureUserAssignedIdentityResource(result, this._client); + } + + /** Marks an Azure resource as existing in run mode */ + runAsExisting(name: string, resourceGroup: string): AzureUserAssignedIdentityResourcePromise { + return new AzureUserAssignedIdentityResourcePromise(this._runAsExistingInternal(name, resourceGroup)); + } + + /** @internal */ + private async _publishAsExistingFromParametersInternal(nameParameter: ParameterResource, resourceGroupParameter: ParameterResource): Promise { + const rpcArgs: Record = { builder: this._handle, nameParameter, resourceGroupParameter }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure/publishAsExistingFromParameters', + rpcArgs + ); + return new AzureUserAssignedIdentityResource(result, this._client); + } + + /** Marks an Azure resource as existing in publish mode by using parameter resources */ + publishAsExistingFromParameters(nameParameter: ParameterResource, resourceGroupParameter: ParameterResource): AzureUserAssignedIdentityResourcePromise { + return new AzureUserAssignedIdentityResourcePromise(this._publishAsExistingFromParametersInternal(nameParameter, resourceGroupParameter)); + } + + /** @internal */ + private async _publishAsExistingInternal(name: string, resourceGroup: string): Promise { + const rpcArgs: Record = { builder: this._handle, name, resourceGroup }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure/publishAsExisting', + rpcArgs + ); + return new AzureUserAssignedIdentityResource(result, this._client); + } + + /** Marks an Azure resource as existing in publish mode */ + publishAsExisting(name: string, resourceGroup: string): AzureUserAssignedIdentityResourcePromise { + return new AzureUserAssignedIdentityResourcePromise(this._publishAsExistingInternal(name, resourceGroup)); + } + + /** @internal */ + private async _asExistingInternal(nameParameter: ParameterResource, resourceGroupParameter: ParameterResource): Promise { + const rpcArgs: Record = { builder: this._handle, nameParameter, resourceGroupParameter }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure/asExistingFromParameters', + rpcArgs + ); + return new AzureUserAssignedIdentityResource(result, this._client); + } + + /** Marks an Azure resource as existing in both run and publish modes by using parameter resources */ + asExisting(nameParameter: ParameterResource, resourceGroupParameter: ParameterResource): AzureUserAssignedIdentityResourcePromise { + return new AzureUserAssignedIdentityResourcePromise(this._asExistingInternal(nameParameter, resourceGroupParameter)); + } + +} + +/** + * Thenable wrapper for AzureUserAssignedIdentityResource that enables fluent chaining. + * @example + * await builder.addSomething().withX().withY(); + */ +export class AzureUserAssignedIdentityResourcePromise implements PromiseLike { + constructor(private _promise: Promise) {} + + then( + onfulfilled?: ((value: AzureUserAssignedIdentityResource) => TResult1 | PromiseLike) | null, + onrejected?: ((reason: unknown) => TResult2 | PromiseLike) | null + ): PromiseLike { + return this._promise.then(onfulfilled, onrejected); + } + + /** Configures a resource to use a container registry */ + withContainerRegistry(registry: ResourceBuilderBase): AzureUserAssignedIdentityResourcePromise { + return new AzureUserAssignedIdentityResourcePromise(this._promise.then(obj => obj.withContainerRegistry(registry))); + } + + /** Sets the base image for a Dockerfile build */ + withDockerfileBaseImage(options?: WithDockerfileBaseImageOptions): AzureUserAssignedIdentityResourcePromise { + return new AzureUserAssignedIdentityResourcePromise(this._promise.then(obj => obj.withDockerfileBaseImage(options))); + } + + /** Adds a required command dependency */ + withRequiredCommand(command: string, options?: WithRequiredCommandOptions): AzureUserAssignedIdentityResourcePromise { + return new AzureUserAssignedIdentityResourcePromise(this._promise.then(obj => obj.withRequiredCommand(command, options))); + } + + /** Customizes displayed URLs via callback */ + withUrlsCallback(callback: (obj: ResourceUrlsCallbackContext) => Promise): AzureUserAssignedIdentityResourcePromise { + return new AzureUserAssignedIdentityResourcePromise(this._promise.then(obj => obj.withUrlsCallback(callback))); + } + + /** Customizes displayed URLs via async callback */ + withUrlsCallbackAsync(callback: (arg: ResourceUrlsCallbackContext) => Promise): AzureUserAssignedIdentityResourcePromise { + return new AzureUserAssignedIdentityResourcePromise(this._promise.then(obj => obj.withUrlsCallbackAsync(callback))); + } + + /** Adds or modifies displayed URLs */ + withUrl(url: string, options?: WithUrlOptions): AzureUserAssignedIdentityResourcePromise { + return new AzureUserAssignedIdentityResourcePromise(this._promise.then(obj => obj.withUrl(url, options))); + } + + /** Adds a URL using a reference expression */ + withUrlExpression(url: ReferenceExpression, options?: WithUrlExpressionOptions): AzureUserAssignedIdentityResourcePromise { + return new AzureUserAssignedIdentityResourcePromise(this._promise.then(obj => obj.withUrlExpression(url, options))); + } + + /** Customizes the URL for a specific endpoint via callback */ + withUrlForEndpoint(endpointName: string, callback: (obj: ResourceUrlAnnotation) => Promise): AzureUserAssignedIdentityResourcePromise { + return new AzureUserAssignedIdentityResourcePromise(this._promise.then(obj => obj.withUrlForEndpoint(endpointName, callback))); + } + + /** Excludes the resource from the deployment manifest */ + excludeFromManifest(): AzureUserAssignedIdentityResourcePromise { + return new AzureUserAssignedIdentityResourcePromise(this._promise.then(obj => obj.excludeFromManifest())); + } + + /** Prevents resource from starting automatically */ + withExplicitStart(): AzureUserAssignedIdentityResourcePromise { + return new AzureUserAssignedIdentityResourcePromise(this._promise.then(obj => obj.withExplicitStart())); + } + + /** Adds a health check by key */ + withHealthCheck(key: string): AzureUserAssignedIdentityResourcePromise { + return new AzureUserAssignedIdentityResourcePromise(this._promise.then(obj => obj.withHealthCheck(key))); + } + + /** Adds a resource command */ + withCommand(name: string, displayName: string, executeCommand: (arg: ExecuteCommandContext) => Promise, options?: WithCommandOptions): AzureUserAssignedIdentityResourcePromise { + return new AzureUserAssignedIdentityResourcePromise(this._promise.then(obj => obj.withCommand(name, displayName, executeCommand, options))); + } + + /** Sets the parent relationship */ + withParentRelationship(parent: ResourceBuilderBase): AzureUserAssignedIdentityResourcePromise { + return new AzureUserAssignedIdentityResourcePromise(this._promise.then(obj => obj.withParentRelationship(parent))); + } + + /** Sets a child relationship */ + withChildRelationship(child: ResourceBuilderBase): AzureUserAssignedIdentityResourcePromise { + return new AzureUserAssignedIdentityResourcePromise(this._promise.then(obj => obj.withChildRelationship(child))); + } + + /** Sets the icon for the resource */ + withIconName(iconName: string, options?: WithIconNameOptions): AzureUserAssignedIdentityResourcePromise { + return new AzureUserAssignedIdentityResourcePromise(this._promise.then(obj => obj.withIconName(iconName, options))); + } + + /** Excludes the resource from MCP server exposure */ + excludeFromMcp(): AzureUserAssignedIdentityResourcePromise { + return new AzureUserAssignedIdentityResourcePromise(this._promise.then(obj => obj.excludeFromMcp())); + } + + /** Adds a pipeline step to the resource */ + withPipelineStepFactory(stepName: string, callback: (arg: PipelineStepContext) => Promise, options?: WithPipelineStepFactoryOptions): AzureUserAssignedIdentityResourcePromise { + return new AzureUserAssignedIdentityResourcePromise(this._promise.then(obj => obj.withPipelineStepFactory(stepName, callback, options))); + } + + /** Configures pipeline step dependencies via an async callback */ + withPipelineConfigurationAsync(callback: (arg: PipelineConfigurationContext) => Promise): AzureUserAssignedIdentityResourcePromise { + return new AzureUserAssignedIdentityResourcePromise(this._promise.then(obj => obj.withPipelineConfigurationAsync(callback))); + } + + /** Configures pipeline step dependencies via a callback */ + withPipelineConfiguration(callback: (obj: PipelineConfigurationContext) => Promise): AzureUserAssignedIdentityResourcePromise { + return new AzureUserAssignedIdentityResourcePromise(this._promise.then(obj => obj.withPipelineConfiguration(callback))); + } + + /** Gets the resource name */ + getResourceName(): Promise { + return this._promise.then(obj => obj.getResourceName()); + } + + /** Assigns Azure Storage roles to a resource */ + withStorageRoleAssignments(target: AzureStorageResource, roles: AzureStorageRole[]): AzureUserAssignedIdentityResourcePromise { + return new AzureUserAssignedIdentityResourcePromise(this._promise.then(obj => obj.withStorageRoleAssignments(target, roles))); + } + + /** Assigns Event Hubs roles to a resource */ + withEventHubsRoleAssignments(target: AzureEventHubsResource, roles: AzureEventHubsRole[]): AzureUserAssignedIdentityResourcePromise { + return new AzureUserAssignedIdentityResourcePromise(this._promise.then(obj => obj.withEventHubsRoleAssignments(target, roles))); + } + + /** Gets an output reference from an Azure Bicep template resource */ + getOutput(name: string): Promise { + return this._promise.then(obj => obj.getOutput(name)); + } + + /** Adds a Bicep parameter without a value */ + withParameter(name: string): AzureUserAssignedIdentityResourcePromise { + return new AzureUserAssignedIdentityResourcePromise(this._promise.then(obj => obj.withParameter(name))); + } + + /** Adds a Bicep parameter with a string value */ + withParameterStringValue(name: string, value: string): AzureUserAssignedIdentityResourcePromise { + return new AzureUserAssignedIdentityResourcePromise(this._promise.then(obj => obj.withParameterStringValue(name, value))); + } + + /** Adds a Bicep parameter with a string list value */ + withParameterStringValues(name: string, value: string[]): AzureUserAssignedIdentityResourcePromise { + return new AzureUserAssignedIdentityResourcePromise(this._promise.then(obj => obj.withParameterStringValues(name, value))); + } + + /** Adds a Bicep parameter from a parameter resource builder */ + withParameterFromParameter(name: string, value: ParameterResource): AzureUserAssignedIdentityResourcePromise { + return new AzureUserAssignedIdentityResourcePromise(this._promise.then(obj => obj.withParameterFromParameter(name, value))); + } + + /** Adds a Bicep parameter from a connection string resource builder */ + withParameterFromConnectionString(name: string, value: ResourceBuilderBase): AzureUserAssignedIdentityResourcePromise { + return new AzureUserAssignedIdentityResourcePromise(this._promise.then(obj => obj.withParameterFromConnectionString(name, value))); + } + + /** Adds a Bicep parameter from another Bicep output reference */ + withParameterFromOutput(name: string, value: BicepOutputReference): AzureUserAssignedIdentityResourcePromise { + return new AzureUserAssignedIdentityResourcePromise(this._promise.then(obj => obj.withParameterFromOutput(name, value))); + } + + /** Adds a Bicep parameter from a reference expression */ + withParameterFromReferenceExpression(name: string, value: ReferenceExpression): AzureUserAssignedIdentityResourcePromise { + return new AzureUserAssignedIdentityResourcePromise(this._promise.then(obj => obj.withParameterFromReferenceExpression(name, value))); + } + + /** Adds a Bicep parameter from an endpoint reference */ + withParameterFromEndpoint(name: string, value: EndpointReference): AzureUserAssignedIdentityResourcePromise { + return new AzureUserAssignedIdentityResourcePromise(this._promise.then(obj => obj.withParameterFromEndpoint(name, value))); + } + + /** Configures the Azure provisioning infrastructure callback */ + configureInfrastructure(configure: (obj: AzureResourceInfrastructure) => Promise): AzureUserAssignedIdentityResourcePromise { + return new AzureUserAssignedIdentityResourcePromise(this._promise.then(obj => obj.configureInfrastructure(configure))); + } + + /** Publishes an Azure resource to the manifest as a connection string */ + publishAsConnectionString(): AzureUserAssignedIdentityResourcePromise { + return new AzureUserAssignedIdentityResourcePromise(this._promise.then(obj => obj.publishAsConnectionString())); + } + + /** Gets the normalized Bicep identifier for an Azure resource */ + getBicepIdentifier(): Promise { + return this._promise.then(obj => obj.getBicepIdentifier()); + } + + /** Clears the default Azure role assignments from a resource */ + clearDefaultRoleAssignments(): AzureUserAssignedIdentityResourcePromise { + return new AzureUserAssignedIdentityResourcePromise(this._promise.then(obj => obj.clearDefaultRoleAssignments())); + } + + /** Determines whether a resource is marked as existing */ + isExisting(): Promise { + return this._promise.then(obj => obj.isExisting()); + } + + /** Marks an Azure resource as existing in run mode by using parameter resources */ + runAsExistingFromParameters(nameParameter: ParameterResource, resourceGroupParameter: ParameterResource): AzureUserAssignedIdentityResourcePromise { + return new AzureUserAssignedIdentityResourcePromise(this._promise.then(obj => obj.runAsExistingFromParameters(nameParameter, resourceGroupParameter))); + } + + /** Marks an Azure resource as existing in run mode */ + runAsExisting(name: string, resourceGroup: string): AzureUserAssignedIdentityResourcePromise { + return new AzureUserAssignedIdentityResourcePromise(this._promise.then(obj => obj.runAsExisting(name, resourceGroup))); + } + + /** Marks an Azure resource as existing in publish mode by using parameter resources */ + publishAsExistingFromParameters(nameParameter: ParameterResource, resourceGroupParameter: ParameterResource): AzureUserAssignedIdentityResourcePromise { + return new AzureUserAssignedIdentityResourcePromise(this._promise.then(obj => obj.publishAsExistingFromParameters(nameParameter, resourceGroupParameter))); + } + + /** Marks an Azure resource as existing in publish mode */ + publishAsExisting(name: string, resourceGroup: string): AzureUserAssignedIdentityResourcePromise { + return new AzureUserAssignedIdentityResourcePromise(this._promise.then(obj => obj.publishAsExisting(name, resourceGroup))); + } + + /** Marks an Azure resource as existing in both run and publish modes by using parameter resources */ + asExisting(nameParameter: ParameterResource, resourceGroupParameter: ParameterResource): AzureUserAssignedIdentityResourcePromise { + return new AzureUserAssignedIdentityResourcePromise(this._promise.then(obj => obj.asExisting(nameParameter, resourceGroupParameter))); + } + +} + +// ============================================================================ +// ConnectionStringResource +// ============================================================================ + +export class ConnectionStringResource extends ResourceBuilderBase { + constructor(handle: ConnectionStringResourceHandle, client: AspireClientRpc) { + super(handle, client); + } + + /** @internal */ + private async _withContainerRegistryInternal(registry: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, registry }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withContainerRegistry', + rpcArgs + ); + return new ConnectionStringResource(result, this._client); + } + + /** Configures a resource to use a container registry */ + withContainerRegistry(registry: ResourceBuilderBase): ConnectionStringResourcePromise { + return new ConnectionStringResourcePromise(this._withContainerRegistryInternal(registry)); + } + + /** @internal */ + private async _withDockerfileBaseImageInternal(buildImage?: string, runtimeImage?: string): Promise { + const rpcArgs: Record = { builder: this._handle }; + if (buildImage !== undefined) rpcArgs.buildImage = buildImage; + if (runtimeImage !== undefined) rpcArgs.runtimeImage = runtimeImage; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withDockerfileBaseImage', + rpcArgs + ); + return new ConnectionStringResource(result, this._client); + } + + /** Sets the base image for a Dockerfile build */ + withDockerfileBaseImage(options?: WithDockerfileBaseImageOptions): ConnectionStringResourcePromise { + const buildImage = options?.buildImage; + const runtimeImage = options?.runtimeImage; + return new ConnectionStringResourcePromise(this._withDockerfileBaseImageInternal(buildImage, runtimeImage)); + } + + /** @internal */ + private async _withRequiredCommandInternal(command: string, helpLink?: string): Promise { + const rpcArgs: Record = { builder: this._handle, command }; + if (helpLink !== undefined) rpcArgs.helpLink = helpLink; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withRequiredCommand', + rpcArgs + ); + return new ConnectionStringResource(result, this._client); + } + + /** Adds a required command dependency */ + withRequiredCommand(command: string, options?: WithRequiredCommandOptions): ConnectionStringResourcePromise { + const helpLink = options?.helpLink; + return new ConnectionStringResourcePromise(this._withRequiredCommandInternal(command, helpLink)); + } + + /** @internal */ + private async _withConnectionPropertyInternal(name: string, value: ReferenceExpression): Promise { + const rpcArgs: Record = { builder: this._handle, name, value }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withConnectionProperty', + rpcArgs + ); + return new ConnectionStringResource(result, this._client); + } + + /** Adds a connection property with a reference expression */ + withConnectionProperty(name: string, value: ReferenceExpression): ConnectionStringResourcePromise { + return new ConnectionStringResourcePromise(this._withConnectionPropertyInternal(name, value)); + } + + /** @internal */ + private async _withConnectionPropertyValueInternal(name: string, value: string): Promise { + const rpcArgs: Record = { builder: this._handle, name, value }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withConnectionPropertyValue', + rpcArgs + ); + return new ConnectionStringResource(result, this._client); + } + + /** Adds a connection property with a string value */ + withConnectionPropertyValue(name: string, value: string): ConnectionStringResourcePromise { + return new ConnectionStringResourcePromise(this._withConnectionPropertyValueInternal(name, value)); + } + + /** @internal */ + private async _withUrlsCallbackInternal(callback: (obj: ResourceUrlsCallbackContext) => Promise): Promise { + const callbackId = registerCallback(async (objData: unknown) => { + const objHandle = wrapIfHandle(objData) as ResourceUrlsCallbackContextHandle; + const obj = new ResourceUrlsCallbackContext(objHandle, this._client); + await callback(obj); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrlsCallback', + rpcArgs + ); + return new ConnectionStringResource(result, this._client); + } + + /** Customizes displayed URLs via callback */ + withUrlsCallback(callback: (obj: ResourceUrlsCallbackContext) => Promise): ConnectionStringResourcePromise { + return new ConnectionStringResourcePromise(this._withUrlsCallbackInternal(callback)); + } + + /** @internal */ + private async _withUrlsCallbackAsyncInternal(callback: (arg: ResourceUrlsCallbackContext) => Promise): Promise { + const callbackId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as ResourceUrlsCallbackContextHandle; + const arg = new ResourceUrlsCallbackContext(argHandle, this._client); + await callback(arg); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrlsCallbackAsync', + rpcArgs + ); + return new ConnectionStringResource(result, this._client); + } + + /** Customizes displayed URLs via async callback */ + withUrlsCallbackAsync(callback: (arg: ResourceUrlsCallbackContext) => Promise): ConnectionStringResourcePromise { + return new ConnectionStringResourcePromise(this._withUrlsCallbackAsyncInternal(callback)); + } + + /** @internal */ + private async _withUrlInternal(url: string, displayText?: string): Promise { + const rpcArgs: Record = { builder: this._handle, url }; + if (displayText !== undefined) rpcArgs.displayText = displayText; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrl', + rpcArgs + ); + return new ConnectionStringResource(result, this._client); + } + + /** Adds or modifies displayed URLs */ + withUrl(url: string, options?: WithUrlOptions): ConnectionStringResourcePromise { + const displayText = options?.displayText; + return new ConnectionStringResourcePromise(this._withUrlInternal(url, displayText)); + } + + /** @internal */ + private async _withUrlExpressionInternal(url: ReferenceExpression, displayText?: string): Promise { + const rpcArgs: Record = { builder: this._handle, url }; + if (displayText !== undefined) rpcArgs.displayText = displayText; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrlExpression', + rpcArgs + ); + return new ConnectionStringResource(result, this._client); + } + + /** Adds a URL using a reference expression */ + withUrlExpression(url: ReferenceExpression, options?: WithUrlExpressionOptions): ConnectionStringResourcePromise { + const displayText = options?.displayText; + return new ConnectionStringResourcePromise(this._withUrlExpressionInternal(url, displayText)); + } + + /** @internal */ + private async _withUrlForEndpointInternal(endpointName: string, callback: (obj: ResourceUrlAnnotation) => Promise): Promise { + const callbackId = registerCallback(async (objData: unknown) => { + const obj = wrapIfHandle(objData) as ResourceUrlAnnotation; + await callback(obj); + }); + const rpcArgs: Record = { builder: this._handle, endpointName, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrlForEndpoint', + rpcArgs + ); + return new ConnectionStringResource(result, this._client); + } + + /** Customizes the URL for a specific endpoint via callback */ + withUrlForEndpoint(endpointName: string, callback: (obj: ResourceUrlAnnotation) => Promise): ConnectionStringResourcePromise { + return new ConnectionStringResourcePromise(this._withUrlForEndpointInternal(endpointName, callback)); + } + + /** @internal */ + private async _excludeFromManifestInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/excludeFromManifest', + rpcArgs + ); + return new ConnectionStringResource(result, this._client); + } + + /** Excludes the resource from the deployment manifest */ + excludeFromManifest(): ConnectionStringResourcePromise { + return new ConnectionStringResourcePromise(this._excludeFromManifestInternal()); + } + + /** @internal */ + private async _waitForInternal(dependency: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, dependency }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/waitFor', + rpcArgs + ); + return new ConnectionStringResource(result, this._client); + } + + /** Waits for another resource to be ready */ + waitFor(dependency: ResourceBuilderBase): ConnectionStringResourcePromise { + return new ConnectionStringResourcePromise(this._waitForInternal(dependency)); + } + + /** @internal */ + private async _waitForWithBehaviorInternal(dependency: ResourceBuilderBase, waitBehavior: WaitBehavior): Promise { + const rpcArgs: Record = { builder: this._handle, dependency, waitBehavior }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/waitForWithBehavior', + rpcArgs + ); + return new ConnectionStringResource(result, this._client); + } + + /** Waits for another resource with specific behavior */ + waitForWithBehavior(dependency: ResourceBuilderBase, waitBehavior: WaitBehavior): ConnectionStringResourcePromise { + return new ConnectionStringResourcePromise(this._waitForWithBehaviorInternal(dependency, waitBehavior)); + } + + /** @internal */ + private async _waitForStartInternal(dependency: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, dependency }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/waitForStart', + rpcArgs + ); + return new ConnectionStringResource(result, this._client); + } + + /** Waits for another resource to start */ + waitForStart(dependency: ResourceBuilderBase): ConnectionStringResourcePromise { + return new ConnectionStringResourcePromise(this._waitForStartInternal(dependency)); + } + + /** @internal */ + private async _waitForStartWithBehaviorInternal(dependency: ResourceBuilderBase, waitBehavior: WaitBehavior): Promise { + const rpcArgs: Record = { builder: this._handle, dependency, waitBehavior }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/waitForStartWithBehavior', + rpcArgs + ); + return new ConnectionStringResource(result, this._client); + } + + /** Waits for another resource to start with specific behavior */ + waitForStartWithBehavior(dependency: ResourceBuilderBase, waitBehavior: WaitBehavior): ConnectionStringResourcePromise { + return new ConnectionStringResourcePromise(this._waitForStartWithBehaviorInternal(dependency, waitBehavior)); + } + + /** @internal */ + private async _withExplicitStartInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withExplicitStart', + rpcArgs + ); + return new ConnectionStringResource(result, this._client); + } + + /** Prevents resource from starting automatically */ + withExplicitStart(): ConnectionStringResourcePromise { + return new ConnectionStringResourcePromise(this._withExplicitStartInternal()); + } + + /** @internal */ + private async _waitForCompletionInternal(dependency: ResourceBuilderBase, exitCode?: number): Promise { + const rpcArgs: Record = { builder: this._handle, dependency }; + if (exitCode !== undefined) rpcArgs.exitCode = exitCode; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/waitForCompletion', + rpcArgs + ); + return new ConnectionStringResource(result, this._client); + } + + /** Waits for resource completion */ + waitForCompletion(dependency: ResourceBuilderBase, options?: WaitForCompletionOptions): ConnectionStringResourcePromise { + const exitCode = options?.exitCode; + return new ConnectionStringResourcePromise(this._waitForCompletionInternal(dependency, exitCode)); + } + + /** @internal */ + private async _withHealthCheckInternal(key: string): Promise { + const rpcArgs: Record = { builder: this._handle, key }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withHealthCheck', + rpcArgs + ); + return new ConnectionStringResource(result, this._client); + } + + /** Adds a health check by key */ + withHealthCheck(key: string): ConnectionStringResourcePromise { + return new ConnectionStringResourcePromise(this._withHealthCheckInternal(key)); + } + + /** @internal */ + private async _withCommandInternal(name: string, displayName: string, executeCommand: (arg: ExecuteCommandContext) => Promise, commandOptions?: CommandOptions): Promise { + const executeCommandId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as ExecuteCommandContextHandle; + const arg = new ExecuteCommandContext(argHandle, this._client); + return await executeCommand(arg); + }); + const rpcArgs: Record = { builder: this._handle, name, displayName, executeCommand: executeCommandId }; + if (commandOptions !== undefined) rpcArgs.commandOptions = commandOptions; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withCommand', + rpcArgs + ); + return new ConnectionStringResource(result, this._client); + } + + /** Adds a resource command */ + withCommand(name: string, displayName: string, executeCommand: (arg: ExecuteCommandContext) => Promise, options?: WithCommandOptions): ConnectionStringResourcePromise { + const commandOptions = options?.commandOptions; + return new ConnectionStringResourcePromise(this._withCommandInternal(name, displayName, executeCommand, commandOptions)); + } + + /** @internal */ + private async _withParentRelationshipInternal(parent: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, parent }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withParentRelationship', + rpcArgs + ); + return new ConnectionStringResource(result, this._client); + } + + /** Sets the parent relationship */ + withParentRelationship(parent: ResourceBuilderBase): ConnectionStringResourcePromise { + return new ConnectionStringResourcePromise(this._withParentRelationshipInternal(parent)); + } + + /** @internal */ + private async _withChildRelationshipInternal(child: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, child }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withChildRelationship', + rpcArgs + ); + return new ConnectionStringResource(result, this._client); + } + + /** Sets a child relationship */ + withChildRelationship(child: ResourceBuilderBase): ConnectionStringResourcePromise { + return new ConnectionStringResourcePromise(this._withChildRelationshipInternal(child)); + } + + /** @internal */ + private async _withIconNameInternal(iconName: string, iconVariant?: IconVariant): Promise { + const rpcArgs: Record = { builder: this._handle, iconName }; + if (iconVariant !== undefined) rpcArgs.iconVariant = iconVariant; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withIconName', + rpcArgs + ); + return new ConnectionStringResource(result, this._client); + } + + /** Sets the icon for the resource */ + withIconName(iconName: string, options?: WithIconNameOptions): ConnectionStringResourcePromise { + const iconVariant = options?.iconVariant; + return new ConnectionStringResourcePromise(this._withIconNameInternal(iconName, iconVariant)); + } + + /** @internal */ + private async _excludeFromMcpInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/excludeFromMcp', + rpcArgs + ); + return new ConnectionStringResource(result, this._client); + } + + /** Excludes the resource from MCP server exposure */ + excludeFromMcp(): ConnectionStringResourcePromise { + return new ConnectionStringResourcePromise(this._excludeFromMcpInternal()); + } + + /** @internal */ + private async _withPipelineStepFactoryInternal(stepName: string, callback: (arg: PipelineStepContext) => Promise, dependsOn?: string[], requiredBy?: string[], tags?: string[], description?: string): Promise { + const callbackId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as PipelineStepContextHandle; + const arg = new PipelineStepContext(argHandle, this._client); + await callback(arg); + }); + const rpcArgs: Record = { builder: this._handle, stepName, callback: callbackId }; + if (dependsOn !== undefined) rpcArgs.dependsOn = dependsOn; + if (requiredBy !== undefined) rpcArgs.requiredBy = requiredBy; + if (tags !== undefined) rpcArgs.tags = tags; + if (description !== undefined) rpcArgs.description = description; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withPipelineStepFactory', + rpcArgs + ); + return new ConnectionStringResource(result, this._client); + } + + /** Adds a pipeline step to the resource */ + withPipelineStepFactory(stepName: string, callback: (arg: PipelineStepContext) => Promise, options?: WithPipelineStepFactoryOptions): ConnectionStringResourcePromise { + const dependsOn = options?.dependsOn; + const requiredBy = options?.requiredBy; + const tags = options?.tags; + const description = options?.description; + return new ConnectionStringResourcePromise(this._withPipelineStepFactoryInternal(stepName, callback, dependsOn, requiredBy, tags, description)); + } + + /** @internal */ + private async _withPipelineConfigurationAsyncInternal(callback: (arg: PipelineConfigurationContext) => Promise): Promise { + const callbackId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as PipelineConfigurationContextHandle; + const arg = new PipelineConfigurationContext(argHandle, this._client); + await callback(arg); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withPipelineConfigurationAsync', + rpcArgs + ); + return new ConnectionStringResource(result, this._client); + } + + /** Configures pipeline step dependencies via an async callback */ + withPipelineConfigurationAsync(callback: (arg: PipelineConfigurationContext) => Promise): ConnectionStringResourcePromise { + return new ConnectionStringResourcePromise(this._withPipelineConfigurationAsyncInternal(callback)); + } + + /** @internal */ + private async _withPipelineConfigurationInternal(callback: (obj: PipelineConfigurationContext) => Promise): Promise { + const callbackId = registerCallback(async (objData: unknown) => { + const objHandle = wrapIfHandle(objData) as PipelineConfigurationContextHandle; + const obj = new PipelineConfigurationContext(objHandle, this._client); + await callback(obj); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withPipelineConfiguration', + rpcArgs + ); + return new ConnectionStringResource(result, this._client); + } + + /** Configures pipeline step dependencies via a callback */ + withPipelineConfiguration(callback: (obj: PipelineConfigurationContext) => Promise): ConnectionStringResourcePromise { + return new ConnectionStringResourcePromise(this._withPipelineConfigurationInternal(callback)); + } + + /** Gets the resource name */ + async getResourceName(): Promise { + const rpcArgs: Record = { resource: this._handle }; + return await this._client.invokeCapability( + 'Aspire.Hosting/getResourceName', + rpcArgs + ); + } + + /** @internal */ + private async _withStorageRoleAssignmentsInternal(target: AzureStorageResource, roles: AzureStorageRole[]): Promise { + const rpcArgs: Record = { builder: this._handle, target, roles }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure.Storage/withStorageRoleAssignments', + rpcArgs + ); + return new ConnectionStringResource(result, this._client); + } + + /** Assigns Azure Storage roles to a resource */ + withStorageRoleAssignments(target: AzureStorageResource, roles: AzureStorageRole[]): ConnectionStringResourcePromise { + return new ConnectionStringResourcePromise(this._withStorageRoleAssignmentsInternal(target, roles)); + } + + /** @internal */ + private async _withEventHubsRoleAssignmentsInternal(target: AzureEventHubsResource, roles: AzureEventHubsRole[]): Promise { + const rpcArgs: Record = { builder: this._handle, target, roles }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure.EventHubs/withEventHubsRoleAssignments', + rpcArgs + ); + return new ConnectionStringResource(result, this._client); + } + + /** Assigns Event Hubs roles to a resource */ + withEventHubsRoleAssignments(target: AzureEventHubsResource, roles: AzureEventHubsRole[]): ConnectionStringResourcePromise { + return new ConnectionStringResourcePromise(this._withEventHubsRoleAssignmentsInternal(target, roles)); + } + +} + +/** + * Thenable wrapper for ConnectionStringResource that enables fluent chaining. + * @example + * await builder.addSomething().withX().withY(); + */ +export class ConnectionStringResourcePromise implements PromiseLike { + constructor(private _promise: Promise) {} + + then( + onfulfilled?: ((value: ConnectionStringResource) => TResult1 | PromiseLike) | null, + onrejected?: ((reason: unknown) => TResult2 | PromiseLike) | null + ): PromiseLike { + return this._promise.then(onfulfilled, onrejected); + } + + /** Configures a resource to use a container registry */ + withContainerRegistry(registry: ResourceBuilderBase): ConnectionStringResourcePromise { + return new ConnectionStringResourcePromise(this._promise.then(obj => obj.withContainerRegistry(registry))); + } + + /** Sets the base image for a Dockerfile build */ + withDockerfileBaseImage(options?: WithDockerfileBaseImageOptions): ConnectionStringResourcePromise { + return new ConnectionStringResourcePromise(this._promise.then(obj => obj.withDockerfileBaseImage(options))); + } + + /** Adds a required command dependency */ + withRequiredCommand(command: string, options?: WithRequiredCommandOptions): ConnectionStringResourcePromise { + return new ConnectionStringResourcePromise(this._promise.then(obj => obj.withRequiredCommand(command, options))); + } + + /** Adds a connection property with a reference expression */ + withConnectionProperty(name: string, value: ReferenceExpression): ConnectionStringResourcePromise { + return new ConnectionStringResourcePromise(this._promise.then(obj => obj.withConnectionProperty(name, value))); + } + + /** Adds a connection property with a string value */ + withConnectionPropertyValue(name: string, value: string): ConnectionStringResourcePromise { + return new ConnectionStringResourcePromise(this._promise.then(obj => obj.withConnectionPropertyValue(name, value))); + } + + /** Customizes displayed URLs via callback */ + withUrlsCallback(callback: (obj: ResourceUrlsCallbackContext) => Promise): ConnectionStringResourcePromise { + return new ConnectionStringResourcePromise(this._promise.then(obj => obj.withUrlsCallback(callback))); + } + + /** Customizes displayed URLs via async callback */ + withUrlsCallbackAsync(callback: (arg: ResourceUrlsCallbackContext) => Promise): ConnectionStringResourcePromise { + return new ConnectionStringResourcePromise(this._promise.then(obj => obj.withUrlsCallbackAsync(callback))); + } + + /** Adds or modifies displayed URLs */ + withUrl(url: string, options?: WithUrlOptions): ConnectionStringResourcePromise { + return new ConnectionStringResourcePromise(this._promise.then(obj => obj.withUrl(url, options))); + } + + /** Adds a URL using a reference expression */ + withUrlExpression(url: ReferenceExpression, options?: WithUrlExpressionOptions): ConnectionStringResourcePromise { + return new ConnectionStringResourcePromise(this._promise.then(obj => obj.withUrlExpression(url, options))); + } + + /** Customizes the URL for a specific endpoint via callback */ + withUrlForEndpoint(endpointName: string, callback: (obj: ResourceUrlAnnotation) => Promise): ConnectionStringResourcePromise { + return new ConnectionStringResourcePromise(this._promise.then(obj => obj.withUrlForEndpoint(endpointName, callback))); + } + + /** Excludes the resource from the deployment manifest */ + excludeFromManifest(): ConnectionStringResourcePromise { + return new ConnectionStringResourcePromise(this._promise.then(obj => obj.excludeFromManifest())); + } + + /** Waits for another resource to be ready */ + waitFor(dependency: ResourceBuilderBase): ConnectionStringResourcePromise { + return new ConnectionStringResourcePromise(this._promise.then(obj => obj.waitFor(dependency))); + } + + /** Waits for another resource with specific behavior */ + waitForWithBehavior(dependency: ResourceBuilderBase, waitBehavior: WaitBehavior): ConnectionStringResourcePromise { + return new ConnectionStringResourcePromise(this._promise.then(obj => obj.waitForWithBehavior(dependency, waitBehavior))); + } + + /** Waits for another resource to start */ + waitForStart(dependency: ResourceBuilderBase): ConnectionStringResourcePromise { + return new ConnectionStringResourcePromise(this._promise.then(obj => obj.waitForStart(dependency))); + } + + /** Waits for another resource to start with specific behavior */ + waitForStartWithBehavior(dependency: ResourceBuilderBase, waitBehavior: WaitBehavior): ConnectionStringResourcePromise { + return new ConnectionStringResourcePromise(this._promise.then(obj => obj.waitForStartWithBehavior(dependency, waitBehavior))); + } + + /** Prevents resource from starting automatically */ + withExplicitStart(): ConnectionStringResourcePromise { + return new ConnectionStringResourcePromise(this._promise.then(obj => obj.withExplicitStart())); + } + + /** Waits for resource completion */ + waitForCompletion(dependency: ResourceBuilderBase, options?: WaitForCompletionOptions): ConnectionStringResourcePromise { + return new ConnectionStringResourcePromise(this._promise.then(obj => obj.waitForCompletion(dependency, options))); + } + + /** Adds a health check by key */ + withHealthCheck(key: string): ConnectionStringResourcePromise { + return new ConnectionStringResourcePromise(this._promise.then(obj => obj.withHealthCheck(key))); + } + + /** Adds a resource command */ + withCommand(name: string, displayName: string, executeCommand: (arg: ExecuteCommandContext) => Promise, options?: WithCommandOptions): ConnectionStringResourcePromise { + return new ConnectionStringResourcePromise(this._promise.then(obj => obj.withCommand(name, displayName, executeCommand, options))); + } + + /** Sets the parent relationship */ + withParentRelationship(parent: ResourceBuilderBase): ConnectionStringResourcePromise { + return new ConnectionStringResourcePromise(this._promise.then(obj => obj.withParentRelationship(parent))); + } + + /** Sets a child relationship */ + withChildRelationship(child: ResourceBuilderBase): ConnectionStringResourcePromise { + return new ConnectionStringResourcePromise(this._promise.then(obj => obj.withChildRelationship(child))); + } + + /** Sets the icon for the resource */ + withIconName(iconName: string, options?: WithIconNameOptions): ConnectionStringResourcePromise { + return new ConnectionStringResourcePromise(this._promise.then(obj => obj.withIconName(iconName, options))); + } + + /** Excludes the resource from MCP server exposure */ + excludeFromMcp(): ConnectionStringResourcePromise { + return new ConnectionStringResourcePromise(this._promise.then(obj => obj.excludeFromMcp())); + } + + /** Adds a pipeline step to the resource */ + withPipelineStepFactory(stepName: string, callback: (arg: PipelineStepContext) => Promise, options?: WithPipelineStepFactoryOptions): ConnectionStringResourcePromise { + return new ConnectionStringResourcePromise(this._promise.then(obj => obj.withPipelineStepFactory(stepName, callback, options))); + } + + /** Configures pipeline step dependencies via an async callback */ + withPipelineConfigurationAsync(callback: (arg: PipelineConfigurationContext) => Promise): ConnectionStringResourcePromise { + return new ConnectionStringResourcePromise(this._promise.then(obj => obj.withPipelineConfigurationAsync(callback))); + } + + /** Configures pipeline step dependencies via a callback */ + withPipelineConfiguration(callback: (obj: PipelineConfigurationContext) => Promise): ConnectionStringResourcePromise { + return new ConnectionStringResourcePromise(this._promise.then(obj => obj.withPipelineConfiguration(callback))); + } + + /** Gets the resource name */ + getResourceName(): Promise { + return this._promise.then(obj => obj.getResourceName()); + } + + /** Assigns Azure Storage roles to a resource */ + withStorageRoleAssignments(target: AzureStorageResource, roles: AzureStorageRole[]): ConnectionStringResourcePromise { + return new ConnectionStringResourcePromise(this._promise.then(obj => obj.withStorageRoleAssignments(target, roles))); + } + + /** Assigns Event Hubs roles to a resource */ + withEventHubsRoleAssignments(target: AzureEventHubsResource, roles: AzureEventHubsRole[]): ConnectionStringResourcePromise { + return new ConnectionStringResourcePromise(this._promise.then(obj => obj.withEventHubsRoleAssignments(target, roles))); + } + +} + +// ============================================================================ +// ContainerRegistryResource +// ============================================================================ + +export class ContainerRegistryResource extends ResourceBuilderBase { + constructor(handle: ContainerRegistryResourceHandle, client: AspireClientRpc) { + super(handle, client); + } + + /** @internal */ + private async _withContainerRegistryInternal(registry: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, registry }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withContainerRegistry', + rpcArgs + ); + return new ContainerRegistryResource(result, this._client); + } + + /** Configures a resource to use a container registry */ + withContainerRegistry(registry: ResourceBuilderBase): ContainerRegistryResourcePromise { + return new ContainerRegistryResourcePromise(this._withContainerRegistryInternal(registry)); + } + + /** @internal */ + private async _withDockerfileBaseImageInternal(buildImage?: string, runtimeImage?: string): Promise { + const rpcArgs: Record = { builder: this._handle }; + if (buildImage !== undefined) rpcArgs.buildImage = buildImage; + if (runtimeImage !== undefined) rpcArgs.runtimeImage = runtimeImage; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withDockerfileBaseImage', + rpcArgs + ); + return new ContainerRegistryResource(result, this._client); + } + + /** Sets the base image for a Dockerfile build */ + withDockerfileBaseImage(options?: WithDockerfileBaseImageOptions): ContainerRegistryResourcePromise { + const buildImage = options?.buildImage; + const runtimeImage = options?.runtimeImage; + return new ContainerRegistryResourcePromise(this._withDockerfileBaseImageInternal(buildImage, runtimeImage)); + } + + /** @internal */ + private async _withRequiredCommandInternal(command: string, helpLink?: string): Promise { + const rpcArgs: Record = { builder: this._handle, command }; + if (helpLink !== undefined) rpcArgs.helpLink = helpLink; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withRequiredCommand', + rpcArgs + ); + return new ContainerRegistryResource(result, this._client); + } + + /** Adds a required command dependency */ + withRequiredCommand(command: string, options?: WithRequiredCommandOptions): ContainerRegistryResourcePromise { + const helpLink = options?.helpLink; + return new ContainerRegistryResourcePromise(this._withRequiredCommandInternal(command, helpLink)); + } + + /** @internal */ + private async _withUrlsCallbackInternal(callback: (obj: ResourceUrlsCallbackContext) => Promise): Promise { + const callbackId = registerCallback(async (objData: unknown) => { + const objHandle = wrapIfHandle(objData) as ResourceUrlsCallbackContextHandle; + const obj = new ResourceUrlsCallbackContext(objHandle, this._client); + await callback(obj); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrlsCallback', + rpcArgs + ); + return new ContainerRegistryResource(result, this._client); + } + + /** Customizes displayed URLs via callback */ + withUrlsCallback(callback: (obj: ResourceUrlsCallbackContext) => Promise): ContainerRegistryResourcePromise { + return new ContainerRegistryResourcePromise(this._withUrlsCallbackInternal(callback)); + } + + /** @internal */ + private async _withUrlsCallbackAsyncInternal(callback: (arg: ResourceUrlsCallbackContext) => Promise): Promise { + const callbackId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as ResourceUrlsCallbackContextHandle; + const arg = new ResourceUrlsCallbackContext(argHandle, this._client); + await callback(arg); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrlsCallbackAsync', + rpcArgs + ); + return new ContainerRegistryResource(result, this._client); + } + + /** Customizes displayed URLs via async callback */ + withUrlsCallbackAsync(callback: (arg: ResourceUrlsCallbackContext) => Promise): ContainerRegistryResourcePromise { + return new ContainerRegistryResourcePromise(this._withUrlsCallbackAsyncInternal(callback)); + } + + /** @internal */ + private async _withUrlInternal(url: string, displayText?: string): Promise { + const rpcArgs: Record = { builder: this._handle, url }; + if (displayText !== undefined) rpcArgs.displayText = displayText; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrl', + rpcArgs + ); + return new ContainerRegistryResource(result, this._client); + } + + /** Adds or modifies displayed URLs */ + withUrl(url: string, options?: WithUrlOptions): ContainerRegistryResourcePromise { + const displayText = options?.displayText; + return new ContainerRegistryResourcePromise(this._withUrlInternal(url, displayText)); + } + + /** @internal */ + private async _withUrlExpressionInternal(url: ReferenceExpression, displayText?: string): Promise { + const rpcArgs: Record = { builder: this._handle, url }; + if (displayText !== undefined) rpcArgs.displayText = displayText; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrlExpression', + rpcArgs + ); + return new ContainerRegistryResource(result, this._client); + } + + /** Adds a URL using a reference expression */ + withUrlExpression(url: ReferenceExpression, options?: WithUrlExpressionOptions): ContainerRegistryResourcePromise { + const displayText = options?.displayText; + return new ContainerRegistryResourcePromise(this._withUrlExpressionInternal(url, displayText)); + } + + /** @internal */ + private async _withUrlForEndpointInternal(endpointName: string, callback: (obj: ResourceUrlAnnotation) => Promise): Promise { + const callbackId = registerCallback(async (objData: unknown) => { + const obj = wrapIfHandle(objData) as ResourceUrlAnnotation; + await callback(obj); + }); + const rpcArgs: Record = { builder: this._handle, endpointName, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrlForEndpoint', + rpcArgs + ); + return new ContainerRegistryResource(result, this._client); + } + + /** Customizes the URL for a specific endpoint via callback */ + withUrlForEndpoint(endpointName: string, callback: (obj: ResourceUrlAnnotation) => Promise): ContainerRegistryResourcePromise { + return new ContainerRegistryResourcePromise(this._withUrlForEndpointInternal(endpointName, callback)); + } + + /** @internal */ + private async _excludeFromManifestInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/excludeFromManifest', + rpcArgs + ); + return new ContainerRegistryResource(result, this._client); + } + + /** Excludes the resource from the deployment manifest */ + excludeFromManifest(): ContainerRegistryResourcePromise { + return new ContainerRegistryResourcePromise(this._excludeFromManifestInternal()); + } + + /** @internal */ + private async _withExplicitStartInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withExplicitStart', + rpcArgs + ); + return new ContainerRegistryResource(result, this._client); + } + + /** Prevents resource from starting automatically */ + withExplicitStart(): ContainerRegistryResourcePromise { + return new ContainerRegistryResourcePromise(this._withExplicitStartInternal()); + } + + /** @internal */ + private async _withHealthCheckInternal(key: string): Promise { + const rpcArgs: Record = { builder: this._handle, key }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withHealthCheck', + rpcArgs + ); + return new ContainerRegistryResource(result, this._client); + } + + /** Adds a health check by key */ + withHealthCheck(key: string): ContainerRegistryResourcePromise { + return new ContainerRegistryResourcePromise(this._withHealthCheckInternal(key)); + } + + /** @internal */ + private async _withCommandInternal(name: string, displayName: string, executeCommand: (arg: ExecuteCommandContext) => Promise, commandOptions?: CommandOptions): Promise { + const executeCommandId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as ExecuteCommandContextHandle; + const arg = new ExecuteCommandContext(argHandle, this._client); + return await executeCommand(arg); + }); + const rpcArgs: Record = { builder: this._handle, name, displayName, executeCommand: executeCommandId }; + if (commandOptions !== undefined) rpcArgs.commandOptions = commandOptions; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withCommand', + rpcArgs + ); + return new ContainerRegistryResource(result, this._client); + } + + /** Adds a resource command */ + withCommand(name: string, displayName: string, executeCommand: (arg: ExecuteCommandContext) => Promise, options?: WithCommandOptions): ContainerRegistryResourcePromise { + const commandOptions = options?.commandOptions; + return new ContainerRegistryResourcePromise(this._withCommandInternal(name, displayName, executeCommand, commandOptions)); + } + + /** @internal */ + private async _withParentRelationshipInternal(parent: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, parent }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withParentRelationship', + rpcArgs + ); + return new ContainerRegistryResource(result, this._client); + } + + /** Sets the parent relationship */ + withParentRelationship(parent: ResourceBuilderBase): ContainerRegistryResourcePromise { + return new ContainerRegistryResourcePromise(this._withParentRelationshipInternal(parent)); + } + + /** @internal */ + private async _withChildRelationshipInternal(child: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, child }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withChildRelationship', + rpcArgs + ); + return new ContainerRegistryResource(result, this._client); + } + + /** Sets a child relationship */ + withChildRelationship(child: ResourceBuilderBase): ContainerRegistryResourcePromise { + return new ContainerRegistryResourcePromise(this._withChildRelationshipInternal(child)); + } + + /** @internal */ + private async _withIconNameInternal(iconName: string, iconVariant?: IconVariant): Promise { + const rpcArgs: Record = { builder: this._handle, iconName }; + if (iconVariant !== undefined) rpcArgs.iconVariant = iconVariant; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withIconName', + rpcArgs + ); + return new ContainerRegistryResource(result, this._client); + } + + /** Sets the icon for the resource */ + withIconName(iconName: string, options?: WithIconNameOptions): ContainerRegistryResourcePromise { + const iconVariant = options?.iconVariant; + return new ContainerRegistryResourcePromise(this._withIconNameInternal(iconName, iconVariant)); + } + + /** @internal */ + private async _excludeFromMcpInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/excludeFromMcp', + rpcArgs + ); + return new ContainerRegistryResource(result, this._client); + } + + /** Excludes the resource from MCP server exposure */ + excludeFromMcp(): ContainerRegistryResourcePromise { + return new ContainerRegistryResourcePromise(this._excludeFromMcpInternal()); + } + + /** @internal */ + private async _withPipelineStepFactoryInternal(stepName: string, callback: (arg: PipelineStepContext) => Promise, dependsOn?: string[], requiredBy?: string[], tags?: string[], description?: string): Promise { + const callbackId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as PipelineStepContextHandle; + const arg = new PipelineStepContext(argHandle, this._client); + await callback(arg); + }); + const rpcArgs: Record = { builder: this._handle, stepName, callback: callbackId }; + if (dependsOn !== undefined) rpcArgs.dependsOn = dependsOn; + if (requiredBy !== undefined) rpcArgs.requiredBy = requiredBy; + if (tags !== undefined) rpcArgs.tags = tags; + if (description !== undefined) rpcArgs.description = description; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withPipelineStepFactory', + rpcArgs + ); + return new ContainerRegistryResource(result, this._client); + } + + /** Adds a pipeline step to the resource */ + withPipelineStepFactory(stepName: string, callback: (arg: PipelineStepContext) => Promise, options?: WithPipelineStepFactoryOptions): ContainerRegistryResourcePromise { + const dependsOn = options?.dependsOn; + const requiredBy = options?.requiredBy; + const tags = options?.tags; + const description = options?.description; + return new ContainerRegistryResourcePromise(this._withPipelineStepFactoryInternal(stepName, callback, dependsOn, requiredBy, tags, description)); + } + + /** @internal */ + private async _withPipelineConfigurationAsyncInternal(callback: (arg: PipelineConfigurationContext) => Promise): Promise { + const callbackId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as PipelineConfigurationContextHandle; + const arg = new PipelineConfigurationContext(argHandle, this._client); + await callback(arg); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withPipelineConfigurationAsync', + rpcArgs + ); + return new ContainerRegistryResource(result, this._client); + } + + /** Configures pipeline step dependencies via an async callback */ + withPipelineConfigurationAsync(callback: (arg: PipelineConfigurationContext) => Promise): ContainerRegistryResourcePromise { + return new ContainerRegistryResourcePromise(this._withPipelineConfigurationAsyncInternal(callback)); + } + + /** @internal */ + private async _withPipelineConfigurationInternal(callback: (obj: PipelineConfigurationContext) => Promise): Promise { + const callbackId = registerCallback(async (objData: unknown) => { + const objHandle = wrapIfHandle(objData) as PipelineConfigurationContextHandle; + const obj = new PipelineConfigurationContext(objHandle, this._client); + await callback(obj); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withPipelineConfiguration', + rpcArgs + ); + return new ContainerRegistryResource(result, this._client); + } + + /** Configures pipeline step dependencies via a callback */ + withPipelineConfiguration(callback: (obj: PipelineConfigurationContext) => Promise): ContainerRegistryResourcePromise { + return new ContainerRegistryResourcePromise(this._withPipelineConfigurationInternal(callback)); + } + + /** Gets the resource name */ + async getResourceName(): Promise { + const rpcArgs: Record = { resource: this._handle }; + return await this._client.invokeCapability( + 'Aspire.Hosting/getResourceName', + rpcArgs + ); + } + + /** @internal */ + private async _withStorageRoleAssignmentsInternal(target: AzureStorageResource, roles: AzureStorageRole[]): Promise { + const rpcArgs: Record = { builder: this._handle, target, roles }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure.Storage/withStorageRoleAssignments', + rpcArgs + ); + return new ContainerRegistryResource(result, this._client); + } + + /** Assigns Azure Storage roles to a resource */ + withStorageRoleAssignments(target: AzureStorageResource, roles: AzureStorageRole[]): ContainerRegistryResourcePromise { + return new ContainerRegistryResourcePromise(this._withStorageRoleAssignmentsInternal(target, roles)); + } + + /** @internal */ + private async _withEventHubsRoleAssignmentsInternal(target: AzureEventHubsResource, roles: AzureEventHubsRole[]): Promise { + const rpcArgs: Record = { builder: this._handle, target, roles }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure.EventHubs/withEventHubsRoleAssignments', + rpcArgs + ); + return new ContainerRegistryResource(result, this._client); + } + + /** Assigns Event Hubs roles to a resource */ + withEventHubsRoleAssignments(target: AzureEventHubsResource, roles: AzureEventHubsRole[]): ContainerRegistryResourcePromise { + return new ContainerRegistryResourcePromise(this._withEventHubsRoleAssignmentsInternal(target, roles)); + } + +} + +/** + * Thenable wrapper for ContainerRegistryResource that enables fluent chaining. + * @example + * await builder.addSomething().withX().withY(); + */ +export class ContainerRegistryResourcePromise implements PromiseLike { + constructor(private _promise: Promise) {} + + then( + onfulfilled?: ((value: ContainerRegistryResource) => TResult1 | PromiseLike) | null, + onrejected?: ((reason: unknown) => TResult2 | PromiseLike) | null + ): PromiseLike { + return this._promise.then(onfulfilled, onrejected); + } + + /** Configures a resource to use a container registry */ + withContainerRegistry(registry: ResourceBuilderBase): ContainerRegistryResourcePromise { + return new ContainerRegistryResourcePromise(this._promise.then(obj => obj.withContainerRegistry(registry))); + } + + /** Sets the base image for a Dockerfile build */ + withDockerfileBaseImage(options?: WithDockerfileBaseImageOptions): ContainerRegistryResourcePromise { + return new ContainerRegistryResourcePromise(this._promise.then(obj => obj.withDockerfileBaseImage(options))); + } + + /** Adds a required command dependency */ + withRequiredCommand(command: string, options?: WithRequiredCommandOptions): ContainerRegistryResourcePromise { + return new ContainerRegistryResourcePromise(this._promise.then(obj => obj.withRequiredCommand(command, options))); + } + + /** Customizes displayed URLs via callback */ + withUrlsCallback(callback: (obj: ResourceUrlsCallbackContext) => Promise): ContainerRegistryResourcePromise { + return new ContainerRegistryResourcePromise(this._promise.then(obj => obj.withUrlsCallback(callback))); + } + + /** Customizes displayed URLs via async callback */ + withUrlsCallbackAsync(callback: (arg: ResourceUrlsCallbackContext) => Promise): ContainerRegistryResourcePromise { + return new ContainerRegistryResourcePromise(this._promise.then(obj => obj.withUrlsCallbackAsync(callback))); + } + + /** Adds or modifies displayed URLs */ + withUrl(url: string, options?: WithUrlOptions): ContainerRegistryResourcePromise { + return new ContainerRegistryResourcePromise(this._promise.then(obj => obj.withUrl(url, options))); + } + + /** Adds a URL using a reference expression */ + withUrlExpression(url: ReferenceExpression, options?: WithUrlExpressionOptions): ContainerRegistryResourcePromise { + return new ContainerRegistryResourcePromise(this._promise.then(obj => obj.withUrlExpression(url, options))); + } + + /** Customizes the URL for a specific endpoint via callback */ + withUrlForEndpoint(endpointName: string, callback: (obj: ResourceUrlAnnotation) => Promise): ContainerRegistryResourcePromise { + return new ContainerRegistryResourcePromise(this._promise.then(obj => obj.withUrlForEndpoint(endpointName, callback))); + } + + /** Excludes the resource from the deployment manifest */ + excludeFromManifest(): ContainerRegistryResourcePromise { + return new ContainerRegistryResourcePromise(this._promise.then(obj => obj.excludeFromManifest())); + } + + /** Prevents resource from starting automatically */ + withExplicitStart(): ContainerRegistryResourcePromise { + return new ContainerRegistryResourcePromise(this._promise.then(obj => obj.withExplicitStart())); + } + + /** Adds a health check by key */ + withHealthCheck(key: string): ContainerRegistryResourcePromise { + return new ContainerRegistryResourcePromise(this._promise.then(obj => obj.withHealthCheck(key))); + } + + /** Adds a resource command */ + withCommand(name: string, displayName: string, executeCommand: (arg: ExecuteCommandContext) => Promise, options?: WithCommandOptions): ContainerRegistryResourcePromise { + return new ContainerRegistryResourcePromise(this._promise.then(obj => obj.withCommand(name, displayName, executeCommand, options))); + } + + /** Sets the parent relationship */ + withParentRelationship(parent: ResourceBuilderBase): ContainerRegistryResourcePromise { + return new ContainerRegistryResourcePromise(this._promise.then(obj => obj.withParentRelationship(parent))); + } + + /** Sets a child relationship */ + withChildRelationship(child: ResourceBuilderBase): ContainerRegistryResourcePromise { + return new ContainerRegistryResourcePromise(this._promise.then(obj => obj.withChildRelationship(child))); + } + + /** Sets the icon for the resource */ + withIconName(iconName: string, options?: WithIconNameOptions): ContainerRegistryResourcePromise { + return new ContainerRegistryResourcePromise(this._promise.then(obj => obj.withIconName(iconName, options))); + } + + /** Excludes the resource from MCP server exposure */ + excludeFromMcp(): ContainerRegistryResourcePromise { + return new ContainerRegistryResourcePromise(this._promise.then(obj => obj.excludeFromMcp())); + } + + /** Adds a pipeline step to the resource */ + withPipelineStepFactory(stepName: string, callback: (arg: PipelineStepContext) => Promise, options?: WithPipelineStepFactoryOptions): ContainerRegistryResourcePromise { + return new ContainerRegistryResourcePromise(this._promise.then(obj => obj.withPipelineStepFactory(stepName, callback, options))); + } + + /** Configures pipeline step dependencies via an async callback */ + withPipelineConfigurationAsync(callback: (arg: PipelineConfigurationContext) => Promise): ContainerRegistryResourcePromise { + return new ContainerRegistryResourcePromise(this._promise.then(obj => obj.withPipelineConfigurationAsync(callback))); + } + + /** Configures pipeline step dependencies via a callback */ + withPipelineConfiguration(callback: (obj: PipelineConfigurationContext) => Promise): ContainerRegistryResourcePromise { + return new ContainerRegistryResourcePromise(this._promise.then(obj => obj.withPipelineConfiguration(callback))); + } + + /** Gets the resource name */ + getResourceName(): Promise { + return this._promise.then(obj => obj.getResourceName()); + } + + /** Assigns Azure Storage roles to a resource */ + withStorageRoleAssignments(target: AzureStorageResource, roles: AzureStorageRole[]): ContainerRegistryResourcePromise { + return new ContainerRegistryResourcePromise(this._promise.then(obj => obj.withStorageRoleAssignments(target, roles))); + } + + /** Assigns Event Hubs roles to a resource */ + withEventHubsRoleAssignments(target: AzureEventHubsResource, roles: AzureEventHubsRole[]): ContainerRegistryResourcePromise { + return new ContainerRegistryResourcePromise(this._promise.then(obj => obj.withEventHubsRoleAssignments(target, roles))); + } + +} + +// ============================================================================ +// ContainerResource +// ============================================================================ + +export class ContainerResource extends ResourceBuilderBase { + constructor(handle: ContainerResourceHandle, client: AspireClientRpc) { + super(handle, client); + } + + /** @internal */ + private async _withContainerRegistryInternal(registry: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, registry }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withContainerRegistry', + rpcArgs + ); + return new ContainerResource(result, this._client); + } + + /** Configures a resource to use a container registry */ + withContainerRegistry(registry: ResourceBuilderBase): ContainerResourcePromise { + return new ContainerResourcePromise(this._withContainerRegistryInternal(registry)); + } + + /** @internal */ + private async _withDockerfileBaseImageInternal(buildImage?: string, runtimeImage?: string): Promise { + const rpcArgs: Record = { builder: this._handle }; + if (buildImage !== undefined) rpcArgs.buildImage = buildImage; + if (runtimeImage !== undefined) rpcArgs.runtimeImage = runtimeImage; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withDockerfileBaseImage', + rpcArgs + ); + return new ContainerResource(result, this._client); + } + + /** Sets the base image for a Dockerfile build */ + withDockerfileBaseImage(options?: WithDockerfileBaseImageOptions): ContainerResourcePromise { + const buildImage = options?.buildImage; + const runtimeImage = options?.runtimeImage; + return new ContainerResourcePromise(this._withDockerfileBaseImageInternal(buildImage, runtimeImage)); + } + + /** @internal */ + private async _withMcpServerInternal(path?: string, endpointName?: string): Promise { + const rpcArgs: Record = { builder: this._handle }; + if (path !== undefined) rpcArgs.path = path; + if (endpointName !== undefined) rpcArgs.endpointName = endpointName; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withMcpServer', + rpcArgs + ); + return new ContainerResource(result, this._client); + } + + /** Configures an MCP server endpoint on the resource */ + withMcpServer(options?: WithMcpServerOptions): ContainerResourcePromise { + const path = options?.path; + const endpointName = options?.endpointName; + return new ContainerResourcePromise(this._withMcpServerInternal(path, endpointName)); + } + + /** @internal */ + private async _withOtlpExporterInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withOtlpExporter', + rpcArgs + ); + return new ContainerResource(result, this._client); + } + + /** Configures OTLP telemetry export */ + withOtlpExporter(): ContainerResourcePromise { + return new ContainerResourcePromise(this._withOtlpExporterInternal()); + } + + /** @internal */ + private async _withOtlpExporterProtocolInternal(protocol: OtlpProtocol): Promise { + const rpcArgs: Record = { builder: this._handle, protocol }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withOtlpExporterProtocol', + rpcArgs + ); + return new ContainerResource(result, this._client); + } + + /** Configures OTLP telemetry export with specific protocol */ + withOtlpExporterProtocol(protocol: OtlpProtocol): ContainerResourcePromise { + return new ContainerResourcePromise(this._withOtlpExporterProtocolInternal(protocol)); + } + + /** @internal */ + private async _withRequiredCommandInternal(command: string, helpLink?: string): Promise { + const rpcArgs: Record = { builder: this._handle, command }; + if (helpLink !== undefined) rpcArgs.helpLink = helpLink; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withRequiredCommand', + rpcArgs + ); + return new ContainerResource(result, this._client); + } + + /** Adds a required command dependency */ + withRequiredCommand(command: string, options?: WithRequiredCommandOptions): ContainerResourcePromise { + const helpLink = options?.helpLink; + return new ContainerResourcePromise(this._withRequiredCommandInternal(command, helpLink)); + } + + /** @internal */ + private async _withEnvironmentInternal(name: string, value: string): Promise { + const rpcArgs: Record = { builder: this._handle, name, value }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withEnvironment', + rpcArgs + ); + return new ContainerResource(result, this._client); + } + + /** Sets an environment variable */ + withEnvironment(name: string, value: string): ContainerResourcePromise { + return new ContainerResourcePromise(this._withEnvironmentInternal(name, value)); + } + + /** @internal */ + private async _withEnvironmentExpressionInternal(name: string, value: ReferenceExpression): Promise { + const rpcArgs: Record = { builder: this._handle, name, value }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withEnvironmentExpression', + rpcArgs + ); + return new ContainerResource(result, this._client); + } + + /** Adds an environment variable with a reference expression */ + withEnvironmentExpression(name: string, value: ReferenceExpression): ContainerResourcePromise { + return new ContainerResourcePromise(this._withEnvironmentExpressionInternal(name, value)); + } + + /** @internal */ + private async _withEnvironmentCallbackInternal(callback: (obj: EnvironmentCallbackContext) => Promise): Promise { + const callbackId = registerCallback(async (objData: unknown) => { + const objHandle = wrapIfHandle(objData) as EnvironmentCallbackContextHandle; + const obj = new EnvironmentCallbackContext(objHandle, this._client); + await callback(obj); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withEnvironmentCallback', + rpcArgs + ); + return new ContainerResource(result, this._client); + } + + /** Sets environment variables via callback */ + withEnvironmentCallback(callback: (obj: EnvironmentCallbackContext) => Promise): ContainerResourcePromise { + return new ContainerResourcePromise(this._withEnvironmentCallbackInternal(callback)); + } + + /** @internal */ + private async _withEnvironmentCallbackAsyncInternal(callback: (arg: EnvironmentCallbackContext) => Promise): Promise { + const callbackId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as EnvironmentCallbackContextHandle; + const arg = new EnvironmentCallbackContext(argHandle, this._client); + await callback(arg); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withEnvironmentCallbackAsync', + rpcArgs + ); + return new ContainerResource(result, this._client); + } + + /** Sets environment variables via async callback */ + withEnvironmentCallbackAsync(callback: (arg: EnvironmentCallbackContext) => Promise): ContainerResourcePromise { + return new ContainerResourcePromise(this._withEnvironmentCallbackAsyncInternal(callback)); + } + + /** @internal */ + private async _withEnvironmentEndpointInternal(name: string, endpointReference: EndpointReference): Promise { + const rpcArgs: Record = { builder: this._handle, name, endpointReference }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withEnvironmentEndpoint', + rpcArgs + ); + return new ContainerResource(result, this._client); + } + + /** Sets an environment variable from an endpoint reference */ + withEnvironmentEndpoint(name: string, endpointReference: EndpointReference): ContainerResourcePromise { + return new ContainerResourcePromise(this._withEnvironmentEndpointInternal(name, endpointReference)); + } + + /** @internal */ + private async _withEnvironmentParameterInternal(name: string, parameter: ParameterResource): Promise { + const rpcArgs: Record = { builder: this._handle, name, parameter }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withEnvironmentParameter', + rpcArgs + ); + return new ContainerResource(result, this._client); + } + + /** Sets an environment variable from a parameter resource */ + withEnvironmentParameter(name: string, parameter: ParameterResource): ContainerResourcePromise { + return new ContainerResourcePromise(this._withEnvironmentParameterInternal(name, parameter)); + } + + /** @internal */ + private async _withEnvironmentConnectionStringInternal(envVarName: string, resource: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, envVarName, resource }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withEnvironmentConnectionString', + rpcArgs + ); + return new ContainerResource(result, this._client); + } + + /** Sets an environment variable from a connection string resource */ + withEnvironmentConnectionString(envVarName: string, resource: ResourceBuilderBase): ContainerResourcePromise { + return new ContainerResourcePromise(this._withEnvironmentConnectionStringInternal(envVarName, resource)); + } + + /** @internal */ + private async _withArgsInternal(args: string[]): Promise { + const rpcArgs: Record = { builder: this._handle, args }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withArgs', + rpcArgs + ); + return new ContainerResource(result, this._client); + } + + /** Adds arguments */ + withArgs(args: string[]): ContainerResourcePromise { + return new ContainerResourcePromise(this._withArgsInternal(args)); + } + + /** @internal */ + private async _withArgsCallbackInternal(callback: (obj: CommandLineArgsCallbackContext) => Promise): Promise { + const callbackId = registerCallback(async (objData: unknown) => { + const objHandle = wrapIfHandle(objData) as CommandLineArgsCallbackContextHandle; + const obj = new CommandLineArgsCallbackContext(objHandle, this._client); + await callback(obj); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withArgsCallback', + rpcArgs + ); + return new ContainerResource(result, this._client); + } + + /** Sets command-line arguments via callback */ + withArgsCallback(callback: (obj: CommandLineArgsCallbackContext) => Promise): ContainerResourcePromise { + return new ContainerResourcePromise(this._withArgsCallbackInternal(callback)); + } + + /** @internal */ + private async _withArgsCallbackAsyncInternal(callback: (arg: CommandLineArgsCallbackContext) => Promise): Promise { + const callbackId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as CommandLineArgsCallbackContextHandle; + const arg = new CommandLineArgsCallbackContext(argHandle, this._client); + await callback(arg); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withArgsCallbackAsync', + rpcArgs + ); + return new ContainerResource(result, this._client); + } + + /** Sets command-line arguments via async callback */ + withArgsCallbackAsync(callback: (arg: CommandLineArgsCallbackContext) => Promise): ContainerResourcePromise { + return new ContainerResourcePromise(this._withArgsCallbackAsyncInternal(callback)); + } + + /** @internal */ + private async _withReferenceInternal(source: ResourceBuilderBase, connectionName?: string, optional?: boolean): Promise { + const rpcArgs: Record = { builder: this._handle, source }; + if (connectionName !== undefined) rpcArgs.connectionName = connectionName; + if (optional !== undefined) rpcArgs.optional = optional; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withReference', + rpcArgs + ); + return new ContainerResource(result, this._client); + } + + /** Adds a reference to another resource */ + withReference(source: ResourceBuilderBase, options?: WithReferenceOptions): ContainerResourcePromise { + const connectionName = options?.connectionName; + const optional = options?.optional; + return new ContainerResourcePromise(this._withReferenceInternal(source, connectionName, optional)); + } + + /** @internal */ + private async _withServiceReferenceInternal(source: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, source }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withServiceReference', + rpcArgs + ); + return new ContainerResource(result, this._client); + } + + /** Adds a service discovery reference to another resource */ + withServiceReference(source: ResourceBuilderBase): ContainerResourcePromise { + return new ContainerResourcePromise(this._withServiceReferenceInternal(source)); + } + + /** @internal */ + private async _withServiceReferenceNamedInternal(source: ResourceBuilderBase, name: string): Promise { + const rpcArgs: Record = { builder: this._handle, source, name }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withServiceReferenceNamed', + rpcArgs + ); + return new ContainerResource(result, this._client); + } + + /** Adds a named service discovery reference */ + withServiceReferenceNamed(source: ResourceBuilderBase, name: string): ContainerResourcePromise { + return new ContainerResourcePromise(this._withServiceReferenceNamedInternal(source, name)); + } + + /** @internal */ + private async _withReferenceUriInternal(name: string, uri: string): Promise { + const rpcArgs: Record = { builder: this._handle, name, uri }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withReferenceUri', + rpcArgs + ); + return new ContainerResource(result, this._client); + } + + /** Adds a reference to a URI */ + withReferenceUri(name: string, uri: string): ContainerResourcePromise { + return new ContainerResourcePromise(this._withReferenceUriInternal(name, uri)); + } + + /** @internal */ + private async _withReferenceExternalServiceInternal(externalService: ExternalServiceResource): Promise { + const rpcArgs: Record = { builder: this._handle, externalService }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withReferenceExternalService', + rpcArgs + ); + return new ContainerResource(result, this._client); + } + + /** Adds a reference to an external service */ + withReferenceExternalService(externalService: ExternalServiceResource): ContainerResourcePromise { + return new ContainerResourcePromise(this._withReferenceExternalServiceInternal(externalService)); + } + + /** @internal */ + private async _withReferenceEndpointInternal(endpointReference: EndpointReference): Promise { + const rpcArgs: Record = { builder: this._handle, endpointReference }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withReferenceEndpoint', + rpcArgs + ); + return new ContainerResource(result, this._client); + } + + /** Adds a reference to an endpoint */ + withReferenceEndpoint(endpointReference: EndpointReference): ContainerResourcePromise { + return new ContainerResourcePromise(this._withReferenceEndpointInternal(endpointReference)); + } + + /** @internal */ + private async _withEndpointInternal(port?: number, targetPort?: number, scheme?: string, name?: string, env?: string, isProxied?: boolean, isExternal?: boolean, protocol?: ProtocolType): Promise { + const rpcArgs: Record = { builder: this._handle }; + if (port !== undefined) rpcArgs.port = port; + if (targetPort !== undefined) rpcArgs.targetPort = targetPort; + if (scheme !== undefined) rpcArgs.scheme = scheme; + if (name !== undefined) rpcArgs.name = name; + if (env !== undefined) rpcArgs.env = env; + if (isProxied !== undefined) rpcArgs.isProxied = isProxied; + if (isExternal !== undefined) rpcArgs.isExternal = isExternal; + if (protocol !== undefined) rpcArgs.protocol = protocol; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withEndpoint', + rpcArgs + ); + return new ContainerResource(result, this._client); + } + + /** Adds a network endpoint */ + withEndpoint(options?: WithEndpointOptions): ContainerResourcePromise { + const port = options?.port; + const targetPort = options?.targetPort; + const scheme = options?.scheme; + const name = options?.name; + const env = options?.env; + const isProxied = options?.isProxied; + const isExternal = options?.isExternal; + const protocol = options?.protocol; + return new ContainerResourcePromise(this._withEndpointInternal(port, targetPort, scheme, name, env, isProxied, isExternal, protocol)); + } + + /** @internal */ + private async _withHttpEndpointInternal(port?: number, targetPort?: number, name?: string, env?: string, isProxied?: boolean): Promise { + const rpcArgs: Record = { builder: this._handle }; + if (port !== undefined) rpcArgs.port = port; + if (targetPort !== undefined) rpcArgs.targetPort = targetPort; + if (name !== undefined) rpcArgs.name = name; + if (env !== undefined) rpcArgs.env = env; + if (isProxied !== undefined) rpcArgs.isProxied = isProxied; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withHttpEndpoint', + rpcArgs + ); + return new ContainerResource(result, this._client); + } + + /** Adds an HTTP endpoint */ + withHttpEndpoint(options?: WithHttpEndpointOptions): ContainerResourcePromise { + const port = options?.port; + const targetPort = options?.targetPort; + const name = options?.name; + const env = options?.env; + const isProxied = options?.isProxied; + return new ContainerResourcePromise(this._withHttpEndpointInternal(port, targetPort, name, env, isProxied)); + } + + /** @internal */ + private async _withHttpsEndpointInternal(port?: number, targetPort?: number, name?: string, env?: string, isProxied?: boolean): Promise { + const rpcArgs: Record = { builder: this._handle }; + if (port !== undefined) rpcArgs.port = port; + if (targetPort !== undefined) rpcArgs.targetPort = targetPort; + if (name !== undefined) rpcArgs.name = name; + if (env !== undefined) rpcArgs.env = env; + if (isProxied !== undefined) rpcArgs.isProxied = isProxied; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withHttpsEndpoint', + rpcArgs + ); + return new ContainerResource(result, this._client); + } + + /** Adds an HTTPS endpoint */ + withHttpsEndpoint(options?: WithHttpsEndpointOptions): ContainerResourcePromise { + const port = options?.port; + const targetPort = options?.targetPort; + const name = options?.name; + const env = options?.env; + const isProxied = options?.isProxied; + return new ContainerResourcePromise(this._withHttpsEndpointInternal(port, targetPort, name, env, isProxied)); + } + + /** @internal */ + private async _withExternalHttpEndpointsInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withExternalHttpEndpoints', + rpcArgs + ); + return new ContainerResource(result, this._client); + } + + /** Makes HTTP endpoints externally accessible */ + withExternalHttpEndpoints(): ContainerResourcePromise { + return new ContainerResourcePromise(this._withExternalHttpEndpointsInternal()); + } + + /** Gets an endpoint reference */ + async getEndpoint(name: string): Promise { + const rpcArgs: Record = { builder: this._handle, name }; + return await this._client.invokeCapability( + 'Aspire.Hosting/getEndpoint', + rpcArgs + ); + } + + /** @internal */ + private async _asHttp2ServiceInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/asHttp2Service', + rpcArgs + ); + return new ContainerResource(result, this._client); + } + + /** Configures resource for HTTP/2 */ + asHttp2Service(): ContainerResourcePromise { + return new ContainerResourcePromise(this._asHttp2ServiceInternal()); + } + + /** @internal */ + private async _withUrlsCallbackInternal(callback: (obj: ResourceUrlsCallbackContext) => Promise): Promise { + const callbackId = registerCallback(async (objData: unknown) => { + const objHandle = wrapIfHandle(objData) as ResourceUrlsCallbackContextHandle; + const obj = new ResourceUrlsCallbackContext(objHandle, this._client); + await callback(obj); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrlsCallback', + rpcArgs + ); + return new ContainerResource(result, this._client); + } + + /** Customizes displayed URLs via callback */ + withUrlsCallback(callback: (obj: ResourceUrlsCallbackContext) => Promise): ContainerResourcePromise { + return new ContainerResourcePromise(this._withUrlsCallbackInternal(callback)); + } + + /** @internal */ + private async _withUrlsCallbackAsyncInternal(callback: (arg: ResourceUrlsCallbackContext) => Promise): Promise { + const callbackId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as ResourceUrlsCallbackContextHandle; + const arg = new ResourceUrlsCallbackContext(argHandle, this._client); + await callback(arg); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrlsCallbackAsync', + rpcArgs + ); + return new ContainerResource(result, this._client); + } + + /** Customizes displayed URLs via async callback */ + withUrlsCallbackAsync(callback: (arg: ResourceUrlsCallbackContext) => Promise): ContainerResourcePromise { + return new ContainerResourcePromise(this._withUrlsCallbackAsyncInternal(callback)); + } + + /** @internal */ + private async _withUrlInternal(url: string, displayText?: string): Promise { + const rpcArgs: Record = { builder: this._handle, url }; + if (displayText !== undefined) rpcArgs.displayText = displayText; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrl', + rpcArgs + ); + return new ContainerResource(result, this._client); + } + + /** Adds or modifies displayed URLs */ + withUrl(url: string, options?: WithUrlOptions): ContainerResourcePromise { + const displayText = options?.displayText; + return new ContainerResourcePromise(this._withUrlInternal(url, displayText)); + } + + /** @internal */ + private async _withUrlExpressionInternal(url: ReferenceExpression, displayText?: string): Promise { + const rpcArgs: Record = { builder: this._handle, url }; + if (displayText !== undefined) rpcArgs.displayText = displayText; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrlExpression', + rpcArgs + ); + return new ContainerResource(result, this._client); + } + + /** Adds a URL using a reference expression */ + withUrlExpression(url: ReferenceExpression, options?: WithUrlExpressionOptions): ContainerResourcePromise { + const displayText = options?.displayText; + return new ContainerResourcePromise(this._withUrlExpressionInternal(url, displayText)); + } + + /** @internal */ + private async _withUrlForEndpointInternal(endpointName: string, callback: (obj: ResourceUrlAnnotation) => Promise): Promise { + const callbackId = registerCallback(async (objData: unknown) => { + const obj = wrapIfHandle(objData) as ResourceUrlAnnotation; + await callback(obj); + }); + const rpcArgs: Record = { builder: this._handle, endpointName, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrlForEndpoint', + rpcArgs + ); + return new ContainerResource(result, this._client); + } + + /** Customizes the URL for a specific endpoint via callback */ + withUrlForEndpoint(endpointName: string, callback: (obj: ResourceUrlAnnotation) => Promise): ContainerResourcePromise { + return new ContainerResourcePromise(this._withUrlForEndpointInternal(endpointName, callback)); + } + + /** @internal */ + private async _withUrlForEndpointFactoryInternal(endpointName: string, callback: (arg: EndpointReference) => Promise): Promise { + const callbackId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as EndpointReferenceHandle; + const arg = new EndpointReference(argHandle, this._client); + return await callback(arg); + }); + const rpcArgs: Record = { builder: this._handle, endpointName, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrlForEndpointFactory', + rpcArgs + ); + return new ContainerResource(result, this._client); + } + + /** Adds a URL for a specific endpoint via factory callback */ + withUrlForEndpointFactory(endpointName: string, callback: (arg: EndpointReference) => Promise): ContainerResourcePromise { + return new ContainerResourcePromise(this._withUrlForEndpointFactoryInternal(endpointName, callback)); + } + + /** @internal */ + private async _excludeFromManifestInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/excludeFromManifest', + rpcArgs + ); + return new ContainerResource(result, this._client); + } + + /** Excludes the resource from the deployment manifest */ + excludeFromManifest(): ContainerResourcePromise { + return new ContainerResourcePromise(this._excludeFromManifestInternal()); + } + + /** @internal */ + private async _waitForInternal(dependency: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, dependency }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/waitFor', + rpcArgs + ); + return new ContainerResource(result, this._client); + } + + /** Waits for another resource to be ready */ + waitFor(dependency: ResourceBuilderBase): ContainerResourcePromise { + return new ContainerResourcePromise(this._waitForInternal(dependency)); + } + + /** @internal */ + private async _waitForWithBehaviorInternal(dependency: ResourceBuilderBase, waitBehavior: WaitBehavior): Promise { + const rpcArgs: Record = { builder: this._handle, dependency, waitBehavior }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/waitForWithBehavior', + rpcArgs + ); + return new ContainerResource(result, this._client); + } + + /** Waits for another resource with specific behavior */ + waitForWithBehavior(dependency: ResourceBuilderBase, waitBehavior: WaitBehavior): ContainerResourcePromise { + return new ContainerResourcePromise(this._waitForWithBehaviorInternal(dependency, waitBehavior)); + } + + /** @internal */ + private async _waitForStartInternal(dependency: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, dependency }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/waitForStart', + rpcArgs + ); + return new ContainerResource(result, this._client); + } + + /** Waits for another resource to start */ + waitForStart(dependency: ResourceBuilderBase): ContainerResourcePromise { + return new ContainerResourcePromise(this._waitForStartInternal(dependency)); + } + + /** @internal */ + private async _waitForStartWithBehaviorInternal(dependency: ResourceBuilderBase, waitBehavior: WaitBehavior): Promise { + const rpcArgs: Record = { builder: this._handle, dependency, waitBehavior }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/waitForStartWithBehavior', + rpcArgs + ); + return new ContainerResource(result, this._client); + } + + /** Waits for another resource to start with specific behavior */ + waitForStartWithBehavior(dependency: ResourceBuilderBase, waitBehavior: WaitBehavior): ContainerResourcePromise { + return new ContainerResourcePromise(this._waitForStartWithBehaviorInternal(dependency, waitBehavior)); + } + + /** @internal */ + private async _withExplicitStartInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withExplicitStart', + rpcArgs + ); + return new ContainerResource(result, this._client); + } + + /** Prevents resource from starting automatically */ + withExplicitStart(): ContainerResourcePromise { + return new ContainerResourcePromise(this._withExplicitStartInternal()); + } + + /** @internal */ + private async _waitForCompletionInternal(dependency: ResourceBuilderBase, exitCode?: number): Promise { + const rpcArgs: Record = { builder: this._handle, dependency }; + if (exitCode !== undefined) rpcArgs.exitCode = exitCode; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/waitForCompletion', + rpcArgs + ); + return new ContainerResource(result, this._client); + } + + /** Waits for resource completion */ + waitForCompletion(dependency: ResourceBuilderBase, options?: WaitForCompletionOptions): ContainerResourcePromise { + const exitCode = options?.exitCode; + return new ContainerResourcePromise(this._waitForCompletionInternal(dependency, exitCode)); + } + + /** @internal */ + private async _withHealthCheckInternal(key: string): Promise { + const rpcArgs: Record = { builder: this._handle, key }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withHealthCheck', + rpcArgs + ); + return new ContainerResource(result, this._client); + } + + /** Adds a health check by key */ + withHealthCheck(key: string): ContainerResourcePromise { + return new ContainerResourcePromise(this._withHealthCheckInternal(key)); + } + + /** @internal */ + private async _withHttpHealthCheckInternal(path?: string, statusCode?: number, endpointName?: string): Promise { + const rpcArgs: Record = { builder: this._handle }; + if (path !== undefined) rpcArgs.path = path; + if (statusCode !== undefined) rpcArgs.statusCode = statusCode; + if (endpointName !== undefined) rpcArgs.endpointName = endpointName; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withHttpHealthCheck', + rpcArgs + ); + return new ContainerResource(result, this._client); + } + + /** Adds an HTTP health check */ + withHttpHealthCheck(options?: WithHttpHealthCheckOptions): ContainerResourcePromise { + const path = options?.path; + const statusCode = options?.statusCode; + const endpointName = options?.endpointName; + return new ContainerResourcePromise(this._withHttpHealthCheckInternal(path, statusCode, endpointName)); + } + + /** @internal */ + private async _withCommandInternal(name: string, displayName: string, executeCommand: (arg: ExecuteCommandContext) => Promise, commandOptions?: CommandOptions): Promise { + const executeCommandId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as ExecuteCommandContextHandle; + const arg = new ExecuteCommandContext(argHandle, this._client); + return await executeCommand(arg); + }); + const rpcArgs: Record = { builder: this._handle, name, displayName, executeCommand: executeCommandId }; + if (commandOptions !== undefined) rpcArgs.commandOptions = commandOptions; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withCommand', + rpcArgs + ); + return new ContainerResource(result, this._client); + } + + /** Adds a resource command */ + withCommand(name: string, displayName: string, executeCommand: (arg: ExecuteCommandContext) => Promise, options?: WithCommandOptions): ContainerResourcePromise { + const commandOptions = options?.commandOptions; + return new ContainerResourcePromise(this._withCommandInternal(name, displayName, executeCommand, commandOptions)); + } + + /** @internal */ + private async _withDeveloperCertificateTrustInternal(trust: boolean): Promise { + const rpcArgs: Record = { builder: this._handle, trust }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withDeveloperCertificateTrust', + rpcArgs + ); + return new ContainerResource(result, this._client); + } + + /** Configures developer certificate trust */ + withDeveloperCertificateTrust(trust: boolean): ContainerResourcePromise { + return new ContainerResourcePromise(this._withDeveloperCertificateTrustInternal(trust)); + } + + /** @internal */ + private async _withCertificateTrustScopeInternal(scope: CertificateTrustScope): Promise { + const rpcArgs: Record = { builder: this._handle, scope }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withCertificateTrustScope', + rpcArgs + ); + return new ContainerResource(result, this._client); + } + + /** Sets the certificate trust scope */ + withCertificateTrustScope(scope: CertificateTrustScope): ContainerResourcePromise { + return new ContainerResourcePromise(this._withCertificateTrustScopeInternal(scope)); + } + + /** @internal */ + private async _withHttpsDeveloperCertificateInternal(password?: ParameterResource): Promise { + const rpcArgs: Record = { builder: this._handle }; + if (password !== undefined) rpcArgs.password = password; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withHttpsDeveloperCertificate', + rpcArgs + ); + return new ContainerResource(result, this._client); + } + + /** Configures HTTPS with a developer certificate */ + withHttpsDeveloperCertificate(options?: WithHttpsDeveloperCertificateOptions): ContainerResourcePromise { + const password = options?.password; + return new ContainerResourcePromise(this._withHttpsDeveloperCertificateInternal(password)); + } + + /** @internal */ + private async _withoutHttpsCertificateInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withoutHttpsCertificate', + rpcArgs + ); + return new ContainerResource(result, this._client); + } + + /** Removes HTTPS certificate configuration */ + withoutHttpsCertificate(): ContainerResourcePromise { + return new ContainerResourcePromise(this._withoutHttpsCertificateInternal()); + } + + /** @internal */ + private async _withParentRelationshipInternal(parent: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, parent }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withParentRelationship', + rpcArgs + ); + return new ContainerResource(result, this._client); + } + + /** Sets the parent relationship */ + withParentRelationship(parent: ResourceBuilderBase): ContainerResourcePromise { + return new ContainerResourcePromise(this._withParentRelationshipInternal(parent)); + } + + /** @internal */ + private async _withChildRelationshipInternal(child: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, child }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withChildRelationship', + rpcArgs + ); + return new ContainerResource(result, this._client); + } + + /** Sets a child relationship */ + withChildRelationship(child: ResourceBuilderBase): ContainerResourcePromise { + return new ContainerResourcePromise(this._withChildRelationshipInternal(child)); + } + + /** @internal */ + private async _withIconNameInternal(iconName: string, iconVariant?: IconVariant): Promise { + const rpcArgs: Record = { builder: this._handle, iconName }; + if (iconVariant !== undefined) rpcArgs.iconVariant = iconVariant; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withIconName', + rpcArgs + ); + return new ContainerResource(result, this._client); + } + + /** Sets the icon for the resource */ + withIconName(iconName: string, options?: WithIconNameOptions): ContainerResourcePromise { + const iconVariant = options?.iconVariant; + return new ContainerResourcePromise(this._withIconNameInternal(iconName, iconVariant)); + } + + /** @internal */ + private async _withHttpProbeInternal(probeType: ProbeType, path?: string, initialDelaySeconds?: number, periodSeconds?: number, timeoutSeconds?: number, failureThreshold?: number, successThreshold?: number, endpointName?: string): Promise { + const rpcArgs: Record = { builder: this._handle, probeType }; + if (path !== undefined) rpcArgs.path = path; + if (initialDelaySeconds !== undefined) rpcArgs.initialDelaySeconds = initialDelaySeconds; + if (periodSeconds !== undefined) rpcArgs.periodSeconds = periodSeconds; + if (timeoutSeconds !== undefined) rpcArgs.timeoutSeconds = timeoutSeconds; + if (failureThreshold !== undefined) rpcArgs.failureThreshold = failureThreshold; + if (successThreshold !== undefined) rpcArgs.successThreshold = successThreshold; + if (endpointName !== undefined) rpcArgs.endpointName = endpointName; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withHttpProbe', + rpcArgs + ); + return new ContainerResource(result, this._client); + } + + /** Adds an HTTP health probe to the resource */ + withHttpProbe(probeType: ProbeType, options?: WithHttpProbeOptions): ContainerResourcePromise { + const path = options?.path; + const initialDelaySeconds = options?.initialDelaySeconds; + const periodSeconds = options?.periodSeconds; + const timeoutSeconds = options?.timeoutSeconds; + const failureThreshold = options?.failureThreshold; + const successThreshold = options?.successThreshold; + const endpointName = options?.endpointName; + return new ContainerResourcePromise(this._withHttpProbeInternal(probeType, path, initialDelaySeconds, periodSeconds, timeoutSeconds, failureThreshold, successThreshold, endpointName)); + } + + /** @internal */ + private async _excludeFromMcpInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/excludeFromMcp', + rpcArgs + ); + return new ContainerResource(result, this._client); + } + + /** Excludes the resource from MCP server exposure */ + excludeFromMcp(): ContainerResourcePromise { + return new ContainerResourcePromise(this._excludeFromMcpInternal()); + } + + /** @internal */ + private async _withRemoteImageNameInternal(remoteImageName: string): Promise { + const rpcArgs: Record = { builder: this._handle, remoteImageName }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withRemoteImageName', + rpcArgs + ); + return new ContainerResource(result, this._client); + } + + /** Sets the remote image name for publishing */ + withRemoteImageName(remoteImageName: string): ContainerResourcePromise { + return new ContainerResourcePromise(this._withRemoteImageNameInternal(remoteImageName)); + } + + /** @internal */ + private async _withRemoteImageTagInternal(remoteImageTag: string): Promise { + const rpcArgs: Record = { builder: this._handle, remoteImageTag }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withRemoteImageTag', + rpcArgs + ); + return new ContainerResource(result, this._client); + } + + /** Sets the remote image tag for publishing */ + withRemoteImageTag(remoteImageTag: string): ContainerResourcePromise { + return new ContainerResourcePromise(this._withRemoteImageTagInternal(remoteImageTag)); + } + + /** @internal */ + private async _withPipelineStepFactoryInternal(stepName: string, callback: (arg: PipelineStepContext) => Promise, dependsOn?: string[], requiredBy?: string[], tags?: string[], description?: string): Promise { + const callbackId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as PipelineStepContextHandle; + const arg = new PipelineStepContext(argHandle, this._client); + await callback(arg); + }); + const rpcArgs: Record = { builder: this._handle, stepName, callback: callbackId }; + if (dependsOn !== undefined) rpcArgs.dependsOn = dependsOn; + if (requiredBy !== undefined) rpcArgs.requiredBy = requiredBy; + if (tags !== undefined) rpcArgs.tags = tags; + if (description !== undefined) rpcArgs.description = description; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withPipelineStepFactory', + rpcArgs + ); + return new ContainerResource(result, this._client); + } + + /** Adds a pipeline step to the resource */ + withPipelineStepFactory(stepName: string, callback: (arg: PipelineStepContext) => Promise, options?: WithPipelineStepFactoryOptions): ContainerResourcePromise { + const dependsOn = options?.dependsOn; + const requiredBy = options?.requiredBy; + const tags = options?.tags; + const description = options?.description; + return new ContainerResourcePromise(this._withPipelineStepFactoryInternal(stepName, callback, dependsOn, requiredBy, tags, description)); + } + + /** @internal */ + private async _withPipelineConfigurationAsyncInternal(callback: (arg: PipelineConfigurationContext) => Promise): Promise { + const callbackId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as PipelineConfigurationContextHandle; + const arg = new PipelineConfigurationContext(argHandle, this._client); + await callback(arg); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withPipelineConfigurationAsync', + rpcArgs + ); + return new ContainerResource(result, this._client); + } + + /** Configures pipeline step dependencies via an async callback */ + withPipelineConfigurationAsync(callback: (arg: PipelineConfigurationContext) => Promise): ContainerResourcePromise { + return new ContainerResourcePromise(this._withPipelineConfigurationAsyncInternal(callback)); + } + + /** @internal */ + private async _withPipelineConfigurationInternal(callback: (obj: PipelineConfigurationContext) => Promise): Promise { + const callbackId = registerCallback(async (objData: unknown) => { + const objHandle = wrapIfHandle(objData) as PipelineConfigurationContextHandle; + const obj = new PipelineConfigurationContext(objHandle, this._client); + await callback(obj); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withPipelineConfiguration', + rpcArgs + ); + return new ContainerResource(result, this._client); + } + + /** Configures pipeline step dependencies via a callback */ + withPipelineConfiguration(callback: (obj: PipelineConfigurationContext) => Promise): ContainerResourcePromise { + return new ContainerResourcePromise(this._withPipelineConfigurationInternal(callback)); + } + + /** Gets the resource name */ + async getResourceName(): Promise { + const rpcArgs: Record = { resource: this._handle }; + return await this._client.invokeCapability( + 'Aspire.Hosting/getResourceName', + rpcArgs + ); + } + + /** @internal */ + private async _withStorageRoleAssignmentsInternal(target: AzureStorageResource, roles: AzureStorageRole[]): Promise { + const rpcArgs: Record = { builder: this._handle, target, roles }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure.Storage/withStorageRoleAssignments', + rpcArgs + ); + return new ContainerResource(result, this._client); + } + + /** Assigns Azure Storage roles to a resource */ + withStorageRoleAssignments(target: AzureStorageResource, roles: AzureStorageRole[]): ContainerResourcePromise { + return new ContainerResourcePromise(this._withStorageRoleAssignmentsInternal(target, roles)); + } + + /** @internal */ + private async _withEventHubsRoleAssignmentsInternal(target: AzureEventHubsResource, roles: AzureEventHubsRole[]): Promise { + const rpcArgs: Record = { builder: this._handle, target, roles }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure.EventHubs/withEventHubsRoleAssignments', + rpcArgs + ); + return new ContainerResource(result, this._client); + } + + /** Assigns Event Hubs roles to a resource */ + withEventHubsRoleAssignments(target: AzureEventHubsResource, roles: AzureEventHubsRole[]): ContainerResourcePromise { + return new ContainerResourcePromise(this._withEventHubsRoleAssignmentsInternal(target, roles)); + } + + /** @internal */ + private async _withEnvironmentFromOutputInternal(name: string, bicepOutputReference: BicepOutputReference): Promise { + const rpcArgs: Record = { builder: this._handle, name, bicepOutputReference }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure/withEnvironmentFromOutput', + rpcArgs + ); + return new ContainerResource(result, this._client); + } + + /** Sets an environment variable from a Bicep output reference */ + withEnvironmentFromOutput(name: string, bicepOutputReference: BicepOutputReference): ContainerResourcePromise { + return new ContainerResourcePromise(this._withEnvironmentFromOutputInternal(name, bicepOutputReference)); + } + + /** @internal */ + private async _withEnvironmentFromKeyVaultSecretInternal(name: string, secretReference: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, name, secretReference }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure/withEnvironmentFromKeyVaultSecret', + rpcArgs + ); + return new ContainerResource(result, this._client); + } + + /** Sets an environment variable from an Azure Key Vault secret reference */ + withEnvironmentFromKeyVaultSecret(name: string, secretReference: ResourceBuilderBase): ContainerResourcePromise { + return new ContainerResourcePromise(this._withEnvironmentFromKeyVaultSecretInternal(name, secretReference)); + } + + /** @internal */ + private async _withAzureUserAssignedIdentityInternal(identityResourceBuilder: AzureUserAssignedIdentityResource): Promise { + const rpcArgs: Record = { builder: this._handle, identityResourceBuilder }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure/withUserAssignedIdentityAzureUserAssignedIdentity', + rpcArgs + ); + return new ContainerResource(result, this._client); + } + + /** Associates an Azure user-assigned identity with a compute resource */ + withAzureUserAssignedIdentity(identityResourceBuilder: AzureUserAssignedIdentityResource): ContainerResourcePromise { + return new ContainerResourcePromise(this._withAzureUserAssignedIdentityInternal(identityResourceBuilder)); + } + +} + +/** + * Thenable wrapper for ContainerResource that enables fluent chaining. + * @example + * await builder.addSomething().withX().withY(); + */ +export class ContainerResourcePromise implements PromiseLike { + constructor(private _promise: Promise) {} + + then( + onfulfilled?: ((value: ContainerResource) => TResult1 | PromiseLike) | null, + onrejected?: ((reason: unknown) => TResult2 | PromiseLike) | null + ): PromiseLike { + return this._promise.then(onfulfilled, onrejected); + } + + /** Configures a resource to use a container registry */ + withContainerRegistry(registry: ResourceBuilderBase): ContainerResourcePromise { + return new ContainerResourcePromise(this._promise.then(obj => obj.withContainerRegistry(registry))); + } + + /** Sets the base image for a Dockerfile build */ + withDockerfileBaseImage(options?: WithDockerfileBaseImageOptions): ContainerResourcePromise { + return new ContainerResourcePromise(this._promise.then(obj => obj.withDockerfileBaseImage(options))); + } + + /** Configures an MCP server endpoint on the resource */ + withMcpServer(options?: WithMcpServerOptions): ContainerResourcePromise { + return new ContainerResourcePromise(this._promise.then(obj => obj.withMcpServer(options))); + } + + /** Configures OTLP telemetry export */ + withOtlpExporter(): ContainerResourcePromise { + return new ContainerResourcePromise(this._promise.then(obj => obj.withOtlpExporter())); + } + + /** Configures OTLP telemetry export with specific protocol */ + withOtlpExporterProtocol(protocol: OtlpProtocol): ContainerResourcePromise { + return new ContainerResourcePromise(this._promise.then(obj => obj.withOtlpExporterProtocol(protocol))); + } + + /** Adds a required command dependency */ + withRequiredCommand(command: string, options?: WithRequiredCommandOptions): ContainerResourcePromise { + return new ContainerResourcePromise(this._promise.then(obj => obj.withRequiredCommand(command, options))); + } + + /** Sets an environment variable */ + withEnvironment(name: string, value: string): ContainerResourcePromise { + return new ContainerResourcePromise(this._promise.then(obj => obj.withEnvironment(name, value))); + } + + /** Adds an environment variable with a reference expression */ + withEnvironmentExpression(name: string, value: ReferenceExpression): ContainerResourcePromise { + return new ContainerResourcePromise(this._promise.then(obj => obj.withEnvironmentExpression(name, value))); + } + + /** Sets environment variables via callback */ + withEnvironmentCallback(callback: (obj: EnvironmentCallbackContext) => Promise): ContainerResourcePromise { + return new ContainerResourcePromise(this._promise.then(obj => obj.withEnvironmentCallback(callback))); + } + + /** Sets environment variables via async callback */ + withEnvironmentCallbackAsync(callback: (arg: EnvironmentCallbackContext) => Promise): ContainerResourcePromise { + return new ContainerResourcePromise(this._promise.then(obj => obj.withEnvironmentCallbackAsync(callback))); + } + + /** Sets an environment variable from an endpoint reference */ + withEnvironmentEndpoint(name: string, endpointReference: EndpointReference): ContainerResourcePromise { + return new ContainerResourcePromise(this._promise.then(obj => obj.withEnvironmentEndpoint(name, endpointReference))); + } + + /** Sets an environment variable from a parameter resource */ + withEnvironmentParameter(name: string, parameter: ParameterResource): ContainerResourcePromise { + return new ContainerResourcePromise(this._promise.then(obj => obj.withEnvironmentParameter(name, parameter))); + } + + /** Sets an environment variable from a connection string resource */ + withEnvironmentConnectionString(envVarName: string, resource: ResourceBuilderBase): ContainerResourcePromise { + return new ContainerResourcePromise(this._promise.then(obj => obj.withEnvironmentConnectionString(envVarName, resource))); + } + + /** Adds arguments */ + withArgs(args: string[]): ContainerResourcePromise { + return new ContainerResourcePromise(this._promise.then(obj => obj.withArgs(args))); + } + + /** Sets command-line arguments via callback */ + withArgsCallback(callback: (obj: CommandLineArgsCallbackContext) => Promise): ContainerResourcePromise { + return new ContainerResourcePromise(this._promise.then(obj => obj.withArgsCallback(callback))); + } + + /** Sets command-line arguments via async callback */ + withArgsCallbackAsync(callback: (arg: CommandLineArgsCallbackContext) => Promise): ContainerResourcePromise { + return new ContainerResourcePromise(this._promise.then(obj => obj.withArgsCallbackAsync(callback))); + } + + /** Adds a reference to another resource */ + withReference(source: ResourceBuilderBase, options?: WithReferenceOptions): ContainerResourcePromise { + return new ContainerResourcePromise(this._promise.then(obj => obj.withReference(source, options))); + } + + /** Adds a service discovery reference to another resource */ + withServiceReference(source: ResourceBuilderBase): ContainerResourcePromise { + return new ContainerResourcePromise(this._promise.then(obj => obj.withServiceReference(source))); + } + + /** Adds a named service discovery reference */ + withServiceReferenceNamed(source: ResourceBuilderBase, name: string): ContainerResourcePromise { + return new ContainerResourcePromise(this._promise.then(obj => obj.withServiceReferenceNamed(source, name))); + } + + /** Adds a reference to a URI */ + withReferenceUri(name: string, uri: string): ContainerResourcePromise { + return new ContainerResourcePromise(this._promise.then(obj => obj.withReferenceUri(name, uri))); + } + + /** Adds a reference to an external service */ + withReferenceExternalService(externalService: ExternalServiceResource): ContainerResourcePromise { + return new ContainerResourcePromise(this._promise.then(obj => obj.withReferenceExternalService(externalService))); + } + + /** Adds a reference to an endpoint */ + withReferenceEndpoint(endpointReference: EndpointReference): ContainerResourcePromise { + return new ContainerResourcePromise(this._promise.then(obj => obj.withReferenceEndpoint(endpointReference))); + } + + /** Adds a network endpoint */ + withEndpoint(options?: WithEndpointOptions): ContainerResourcePromise { + return new ContainerResourcePromise(this._promise.then(obj => obj.withEndpoint(options))); + } + + /** Adds an HTTP endpoint */ + withHttpEndpoint(options?: WithHttpEndpointOptions): ContainerResourcePromise { + return new ContainerResourcePromise(this._promise.then(obj => obj.withHttpEndpoint(options))); + } + + /** Adds an HTTPS endpoint */ + withHttpsEndpoint(options?: WithHttpsEndpointOptions): ContainerResourcePromise { + return new ContainerResourcePromise(this._promise.then(obj => obj.withHttpsEndpoint(options))); + } + + /** Makes HTTP endpoints externally accessible */ + withExternalHttpEndpoints(): ContainerResourcePromise { + return new ContainerResourcePromise(this._promise.then(obj => obj.withExternalHttpEndpoints())); + } + + /** Gets an endpoint reference */ + getEndpoint(name: string): Promise { + return this._promise.then(obj => obj.getEndpoint(name)); + } + + /** Configures resource for HTTP/2 */ + asHttp2Service(): ContainerResourcePromise { + return new ContainerResourcePromise(this._promise.then(obj => obj.asHttp2Service())); + } + + /** Customizes displayed URLs via callback */ + withUrlsCallback(callback: (obj: ResourceUrlsCallbackContext) => Promise): ContainerResourcePromise { + return new ContainerResourcePromise(this._promise.then(obj => obj.withUrlsCallback(callback))); + } + + /** Customizes displayed URLs via async callback */ + withUrlsCallbackAsync(callback: (arg: ResourceUrlsCallbackContext) => Promise): ContainerResourcePromise { + return new ContainerResourcePromise(this._promise.then(obj => obj.withUrlsCallbackAsync(callback))); + } + + /** Adds or modifies displayed URLs */ + withUrl(url: string, options?: WithUrlOptions): ContainerResourcePromise { + return new ContainerResourcePromise(this._promise.then(obj => obj.withUrl(url, options))); + } + + /** Adds a URL using a reference expression */ + withUrlExpression(url: ReferenceExpression, options?: WithUrlExpressionOptions): ContainerResourcePromise { + return new ContainerResourcePromise(this._promise.then(obj => obj.withUrlExpression(url, options))); + } + + /** Customizes the URL for a specific endpoint via callback */ + withUrlForEndpoint(endpointName: string, callback: (obj: ResourceUrlAnnotation) => Promise): ContainerResourcePromise { + return new ContainerResourcePromise(this._promise.then(obj => obj.withUrlForEndpoint(endpointName, callback))); + } + + /** Adds a URL for a specific endpoint via factory callback */ + withUrlForEndpointFactory(endpointName: string, callback: (arg: EndpointReference) => Promise): ContainerResourcePromise { + return new ContainerResourcePromise(this._promise.then(obj => obj.withUrlForEndpointFactory(endpointName, callback))); + } + + /** Excludes the resource from the deployment manifest */ + excludeFromManifest(): ContainerResourcePromise { + return new ContainerResourcePromise(this._promise.then(obj => obj.excludeFromManifest())); + } + + /** Waits for another resource to be ready */ + waitFor(dependency: ResourceBuilderBase): ContainerResourcePromise { + return new ContainerResourcePromise(this._promise.then(obj => obj.waitFor(dependency))); + } + + /** Waits for another resource with specific behavior */ + waitForWithBehavior(dependency: ResourceBuilderBase, waitBehavior: WaitBehavior): ContainerResourcePromise { + return new ContainerResourcePromise(this._promise.then(obj => obj.waitForWithBehavior(dependency, waitBehavior))); + } + + /** Waits for another resource to start */ + waitForStart(dependency: ResourceBuilderBase): ContainerResourcePromise { + return new ContainerResourcePromise(this._promise.then(obj => obj.waitForStart(dependency))); + } + + /** Waits for another resource to start with specific behavior */ + waitForStartWithBehavior(dependency: ResourceBuilderBase, waitBehavior: WaitBehavior): ContainerResourcePromise { + return new ContainerResourcePromise(this._promise.then(obj => obj.waitForStartWithBehavior(dependency, waitBehavior))); + } + + /** Prevents resource from starting automatically */ + withExplicitStart(): ContainerResourcePromise { + return new ContainerResourcePromise(this._promise.then(obj => obj.withExplicitStart())); + } + + /** Waits for resource completion */ + waitForCompletion(dependency: ResourceBuilderBase, options?: WaitForCompletionOptions): ContainerResourcePromise { + return new ContainerResourcePromise(this._promise.then(obj => obj.waitForCompletion(dependency, options))); + } + + /** Adds a health check by key */ + withHealthCheck(key: string): ContainerResourcePromise { + return new ContainerResourcePromise(this._promise.then(obj => obj.withHealthCheck(key))); + } + + /** Adds an HTTP health check */ + withHttpHealthCheck(options?: WithHttpHealthCheckOptions): ContainerResourcePromise { + return new ContainerResourcePromise(this._promise.then(obj => obj.withHttpHealthCheck(options))); + } + + /** Adds a resource command */ + withCommand(name: string, displayName: string, executeCommand: (arg: ExecuteCommandContext) => Promise, options?: WithCommandOptions): ContainerResourcePromise { + return new ContainerResourcePromise(this._promise.then(obj => obj.withCommand(name, displayName, executeCommand, options))); + } + + /** Configures developer certificate trust */ + withDeveloperCertificateTrust(trust: boolean): ContainerResourcePromise { + return new ContainerResourcePromise(this._promise.then(obj => obj.withDeveloperCertificateTrust(trust))); + } + + /** Sets the certificate trust scope */ + withCertificateTrustScope(scope: CertificateTrustScope): ContainerResourcePromise { + return new ContainerResourcePromise(this._promise.then(obj => obj.withCertificateTrustScope(scope))); + } + + /** Configures HTTPS with a developer certificate */ + withHttpsDeveloperCertificate(options?: WithHttpsDeveloperCertificateOptions): ContainerResourcePromise { + return new ContainerResourcePromise(this._promise.then(obj => obj.withHttpsDeveloperCertificate(options))); + } + + /** Removes HTTPS certificate configuration */ + withoutHttpsCertificate(): ContainerResourcePromise { + return new ContainerResourcePromise(this._promise.then(obj => obj.withoutHttpsCertificate())); + } + + /** Sets the parent relationship */ + withParentRelationship(parent: ResourceBuilderBase): ContainerResourcePromise { + return new ContainerResourcePromise(this._promise.then(obj => obj.withParentRelationship(parent))); + } + + /** Sets a child relationship */ + withChildRelationship(child: ResourceBuilderBase): ContainerResourcePromise { + return new ContainerResourcePromise(this._promise.then(obj => obj.withChildRelationship(child))); + } + + /** Sets the icon for the resource */ + withIconName(iconName: string, options?: WithIconNameOptions): ContainerResourcePromise { + return new ContainerResourcePromise(this._promise.then(obj => obj.withIconName(iconName, options))); + } + + /** Adds an HTTP health probe to the resource */ + withHttpProbe(probeType: ProbeType, options?: WithHttpProbeOptions): ContainerResourcePromise { + return new ContainerResourcePromise(this._promise.then(obj => obj.withHttpProbe(probeType, options))); + } + + /** Excludes the resource from MCP server exposure */ + excludeFromMcp(): ContainerResourcePromise { + return new ContainerResourcePromise(this._promise.then(obj => obj.excludeFromMcp())); + } + + /** Sets the remote image name for publishing */ + withRemoteImageName(remoteImageName: string): ContainerResourcePromise { + return new ContainerResourcePromise(this._promise.then(obj => obj.withRemoteImageName(remoteImageName))); + } + + /** Sets the remote image tag for publishing */ + withRemoteImageTag(remoteImageTag: string): ContainerResourcePromise { + return new ContainerResourcePromise(this._promise.then(obj => obj.withRemoteImageTag(remoteImageTag))); + } + + /** Adds a pipeline step to the resource */ + withPipelineStepFactory(stepName: string, callback: (arg: PipelineStepContext) => Promise, options?: WithPipelineStepFactoryOptions): ContainerResourcePromise { + return new ContainerResourcePromise(this._promise.then(obj => obj.withPipelineStepFactory(stepName, callback, options))); + } + + /** Configures pipeline step dependencies via an async callback */ + withPipelineConfigurationAsync(callback: (arg: PipelineConfigurationContext) => Promise): ContainerResourcePromise { + return new ContainerResourcePromise(this._promise.then(obj => obj.withPipelineConfigurationAsync(callback))); + } + + /** Configures pipeline step dependencies via a callback */ + withPipelineConfiguration(callback: (obj: PipelineConfigurationContext) => Promise): ContainerResourcePromise { + return new ContainerResourcePromise(this._promise.then(obj => obj.withPipelineConfiguration(callback))); + } + + /** Gets the resource name */ + getResourceName(): Promise { + return this._promise.then(obj => obj.getResourceName()); + } + + /** Assigns Azure Storage roles to a resource */ + withStorageRoleAssignments(target: AzureStorageResource, roles: AzureStorageRole[]): ContainerResourcePromise { + return new ContainerResourcePromise(this._promise.then(obj => obj.withStorageRoleAssignments(target, roles))); + } + + /** Assigns Event Hubs roles to a resource */ + withEventHubsRoleAssignments(target: AzureEventHubsResource, roles: AzureEventHubsRole[]): ContainerResourcePromise { + return new ContainerResourcePromise(this._promise.then(obj => obj.withEventHubsRoleAssignments(target, roles))); + } + + /** Sets an environment variable from a Bicep output reference */ + withEnvironmentFromOutput(name: string, bicepOutputReference: BicepOutputReference): ContainerResourcePromise { + return new ContainerResourcePromise(this._promise.then(obj => obj.withEnvironmentFromOutput(name, bicepOutputReference))); + } + + /** Sets an environment variable from an Azure Key Vault secret reference */ + withEnvironmentFromKeyVaultSecret(name: string, secretReference: ResourceBuilderBase): ContainerResourcePromise { + return new ContainerResourcePromise(this._promise.then(obj => obj.withEnvironmentFromKeyVaultSecret(name, secretReference))); + } + + /** Associates an Azure user-assigned identity with a compute resource */ + withAzureUserAssignedIdentity(identityResourceBuilder: AzureUserAssignedIdentityResource): ContainerResourcePromise { + return new ContainerResourcePromise(this._promise.then(obj => obj.withAzureUserAssignedIdentity(identityResourceBuilder))); + } + +} + +// ============================================================================ +// CSharpAppResource +// ============================================================================ + +export class CSharpAppResource extends ResourceBuilderBase { + constructor(handle: CSharpAppResourceHandle, client: AspireClientRpc) { + super(handle, client); + } + + /** @internal */ + private async _withContainerRegistryInternal(registry: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, registry }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withContainerRegistry', + rpcArgs + ); + return new CSharpAppResource(result, this._client); + } + + /** Configures a resource to use a container registry */ + withContainerRegistry(registry: ResourceBuilderBase): CSharpAppResourcePromise { + return new CSharpAppResourcePromise(this._withContainerRegistryInternal(registry)); + } + + /** @internal */ + private async _withDockerfileBaseImageInternal(buildImage?: string, runtimeImage?: string): Promise { + const rpcArgs: Record = { builder: this._handle }; + if (buildImage !== undefined) rpcArgs.buildImage = buildImage; + if (runtimeImage !== undefined) rpcArgs.runtimeImage = runtimeImage; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withDockerfileBaseImage', + rpcArgs + ); + return new CSharpAppResource(result, this._client); + } + + /** Sets the base image for a Dockerfile build */ + withDockerfileBaseImage(options?: WithDockerfileBaseImageOptions): CSharpAppResourcePromise { + const buildImage = options?.buildImage; + const runtimeImage = options?.runtimeImage; + return new CSharpAppResourcePromise(this._withDockerfileBaseImageInternal(buildImage, runtimeImage)); + } + + /** @internal */ + private async _withMcpServerInternal(path?: string, endpointName?: string): Promise { + const rpcArgs: Record = { builder: this._handle }; + if (path !== undefined) rpcArgs.path = path; + if (endpointName !== undefined) rpcArgs.endpointName = endpointName; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withMcpServer', + rpcArgs + ); + return new CSharpAppResource(result, this._client); + } + + /** Configures an MCP server endpoint on the resource */ + withMcpServer(options?: WithMcpServerOptions): CSharpAppResourcePromise { + const path = options?.path; + const endpointName = options?.endpointName; + return new CSharpAppResourcePromise(this._withMcpServerInternal(path, endpointName)); + } + + /** @internal */ + private async _withOtlpExporterInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withOtlpExporter', + rpcArgs + ); + return new CSharpAppResource(result, this._client); + } + + /** Configures OTLP telemetry export */ + withOtlpExporter(): CSharpAppResourcePromise { + return new CSharpAppResourcePromise(this._withOtlpExporterInternal()); + } + + /** @internal */ + private async _withOtlpExporterProtocolInternal(protocol: OtlpProtocol): Promise { + const rpcArgs: Record = { builder: this._handle, protocol }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withOtlpExporterProtocol', + rpcArgs + ); + return new CSharpAppResource(result, this._client); + } + + /** Configures OTLP telemetry export with specific protocol */ + withOtlpExporterProtocol(protocol: OtlpProtocol): CSharpAppResourcePromise { + return new CSharpAppResourcePromise(this._withOtlpExporterProtocolInternal(protocol)); + } + + /** @internal */ + private async _withReplicasInternal(replicas: number): Promise { + const rpcArgs: Record = { builder: this._handle, replicas }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withReplicas', + rpcArgs + ); + return new CSharpAppResource(result, this._client); + } + + /** Sets the number of replicas */ + withReplicas(replicas: number): CSharpAppResourcePromise { + return new CSharpAppResourcePromise(this._withReplicasInternal(replicas)); + } + + /** @internal */ + private async _disableForwardedHeadersInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/disableForwardedHeaders', + rpcArgs + ); + return new CSharpAppResource(result, this._client); + } + + /** Disables forwarded headers for the project */ + disableForwardedHeaders(): CSharpAppResourcePromise { + return new CSharpAppResourcePromise(this._disableForwardedHeadersInternal()); + } + + /** @internal */ + private async _publishAsDockerFileInternal(configure?: (obj: ContainerResource) => Promise): Promise { + const configureId = configure ? registerCallback(async (objData: unknown) => { + const objHandle = wrapIfHandle(objData) as ContainerResourceHandle; + const obj = new ContainerResource(objHandle, this._client); + await configure(obj); + }) : undefined; + const rpcArgs: Record = { builder: this._handle }; + if (configure !== undefined) rpcArgs.configure = configureId; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/publishProjectAsDockerFileWithConfigure', + rpcArgs + ); + return new CSharpAppResource(result, this._client); + } + + /** Publishes a project as a Docker file with optional container configuration */ + publishAsDockerFile(options?: PublishAsDockerFileOptions): CSharpAppResourcePromise { + const configure = options?.configure; + return new CSharpAppResourcePromise(this._publishAsDockerFileInternal(configure)); + } + + /** @internal */ + private async _withRequiredCommandInternal(command: string, helpLink?: string): Promise { + const rpcArgs: Record = { builder: this._handle, command }; + if (helpLink !== undefined) rpcArgs.helpLink = helpLink; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withRequiredCommand', + rpcArgs + ); + return new CSharpAppResource(result, this._client); + } + + /** Adds a required command dependency */ + withRequiredCommand(command: string, options?: WithRequiredCommandOptions): CSharpAppResourcePromise { + const helpLink = options?.helpLink; + return new CSharpAppResourcePromise(this._withRequiredCommandInternal(command, helpLink)); + } + + /** @internal */ + private async _withEnvironmentInternal(name: string, value: string): Promise { + const rpcArgs: Record = { builder: this._handle, name, value }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withEnvironment', + rpcArgs + ); + return new CSharpAppResource(result, this._client); + } + + /** Sets an environment variable */ + withEnvironment(name: string, value: string): CSharpAppResourcePromise { + return new CSharpAppResourcePromise(this._withEnvironmentInternal(name, value)); + } + + /** @internal */ + private async _withEnvironmentExpressionInternal(name: string, value: ReferenceExpression): Promise { + const rpcArgs: Record = { builder: this._handle, name, value }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withEnvironmentExpression', + rpcArgs + ); + return new CSharpAppResource(result, this._client); + } + + /** Adds an environment variable with a reference expression */ + withEnvironmentExpression(name: string, value: ReferenceExpression): CSharpAppResourcePromise { + return new CSharpAppResourcePromise(this._withEnvironmentExpressionInternal(name, value)); + } + + /** @internal */ + private async _withEnvironmentCallbackInternal(callback: (obj: EnvironmentCallbackContext) => Promise): Promise { + const callbackId = registerCallback(async (objData: unknown) => { + const objHandle = wrapIfHandle(objData) as EnvironmentCallbackContextHandle; + const obj = new EnvironmentCallbackContext(objHandle, this._client); + await callback(obj); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withEnvironmentCallback', + rpcArgs + ); + return new CSharpAppResource(result, this._client); + } + + /** Sets environment variables via callback */ + withEnvironmentCallback(callback: (obj: EnvironmentCallbackContext) => Promise): CSharpAppResourcePromise { + return new CSharpAppResourcePromise(this._withEnvironmentCallbackInternal(callback)); + } + + /** @internal */ + private async _withEnvironmentCallbackAsyncInternal(callback: (arg: EnvironmentCallbackContext) => Promise): Promise { + const callbackId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as EnvironmentCallbackContextHandle; + const arg = new EnvironmentCallbackContext(argHandle, this._client); + await callback(arg); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withEnvironmentCallbackAsync', + rpcArgs + ); + return new CSharpAppResource(result, this._client); + } + + /** Sets environment variables via async callback */ + withEnvironmentCallbackAsync(callback: (arg: EnvironmentCallbackContext) => Promise): CSharpAppResourcePromise { + return new CSharpAppResourcePromise(this._withEnvironmentCallbackAsyncInternal(callback)); + } + + /** @internal */ + private async _withEnvironmentEndpointInternal(name: string, endpointReference: EndpointReference): Promise { + const rpcArgs: Record = { builder: this._handle, name, endpointReference }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withEnvironmentEndpoint', + rpcArgs + ); + return new CSharpAppResource(result, this._client); + } + + /** Sets an environment variable from an endpoint reference */ + withEnvironmentEndpoint(name: string, endpointReference: EndpointReference): CSharpAppResourcePromise { + return new CSharpAppResourcePromise(this._withEnvironmentEndpointInternal(name, endpointReference)); + } + + /** @internal */ + private async _withEnvironmentParameterInternal(name: string, parameter: ParameterResource): Promise { + const rpcArgs: Record = { builder: this._handle, name, parameter }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withEnvironmentParameter', + rpcArgs + ); + return new CSharpAppResource(result, this._client); + } + + /** Sets an environment variable from a parameter resource */ + withEnvironmentParameter(name: string, parameter: ParameterResource): CSharpAppResourcePromise { + return new CSharpAppResourcePromise(this._withEnvironmentParameterInternal(name, parameter)); + } + + /** @internal */ + private async _withEnvironmentConnectionStringInternal(envVarName: string, resource: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, envVarName, resource }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withEnvironmentConnectionString', + rpcArgs + ); + return new CSharpAppResource(result, this._client); + } + + /** Sets an environment variable from a connection string resource */ + withEnvironmentConnectionString(envVarName: string, resource: ResourceBuilderBase): CSharpAppResourcePromise { + return new CSharpAppResourcePromise(this._withEnvironmentConnectionStringInternal(envVarName, resource)); + } + + /** @internal */ + private async _withArgsInternal(args: string[]): Promise { + const rpcArgs: Record = { builder: this._handle, args }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withArgs', + rpcArgs + ); + return new CSharpAppResource(result, this._client); + } + + /** Adds arguments */ + withArgs(args: string[]): CSharpAppResourcePromise { + return new CSharpAppResourcePromise(this._withArgsInternal(args)); + } + + /** @internal */ + private async _withArgsCallbackInternal(callback: (obj: CommandLineArgsCallbackContext) => Promise): Promise { + const callbackId = registerCallback(async (objData: unknown) => { + const objHandle = wrapIfHandle(objData) as CommandLineArgsCallbackContextHandle; + const obj = new CommandLineArgsCallbackContext(objHandle, this._client); + await callback(obj); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withArgsCallback', + rpcArgs + ); + return new CSharpAppResource(result, this._client); + } + + /** Sets command-line arguments via callback */ + withArgsCallback(callback: (obj: CommandLineArgsCallbackContext) => Promise): CSharpAppResourcePromise { + return new CSharpAppResourcePromise(this._withArgsCallbackInternal(callback)); + } + + /** @internal */ + private async _withArgsCallbackAsyncInternal(callback: (arg: CommandLineArgsCallbackContext) => Promise): Promise { + const callbackId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as CommandLineArgsCallbackContextHandle; + const arg = new CommandLineArgsCallbackContext(argHandle, this._client); + await callback(arg); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withArgsCallbackAsync', + rpcArgs + ); + return new CSharpAppResource(result, this._client); + } + + /** Sets command-line arguments via async callback */ + withArgsCallbackAsync(callback: (arg: CommandLineArgsCallbackContext) => Promise): CSharpAppResourcePromise { + return new CSharpAppResourcePromise(this._withArgsCallbackAsyncInternal(callback)); + } + + /** @internal */ + private async _withReferenceInternal(source: ResourceBuilderBase, connectionName?: string, optional?: boolean): Promise { + const rpcArgs: Record = { builder: this._handle, source }; + if (connectionName !== undefined) rpcArgs.connectionName = connectionName; + if (optional !== undefined) rpcArgs.optional = optional; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withReference', + rpcArgs + ); + return new CSharpAppResource(result, this._client); + } + + /** Adds a reference to another resource */ + withReference(source: ResourceBuilderBase, options?: WithReferenceOptions): CSharpAppResourcePromise { + const connectionName = options?.connectionName; + const optional = options?.optional; + return new CSharpAppResourcePromise(this._withReferenceInternal(source, connectionName, optional)); + } + + /** @internal */ + private async _withServiceReferenceInternal(source: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, source }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withServiceReference', + rpcArgs + ); + return new CSharpAppResource(result, this._client); + } + + /** Adds a service discovery reference to another resource */ + withServiceReference(source: ResourceBuilderBase): CSharpAppResourcePromise { + return new CSharpAppResourcePromise(this._withServiceReferenceInternal(source)); + } + + /** @internal */ + private async _withServiceReferenceNamedInternal(source: ResourceBuilderBase, name: string): Promise { + const rpcArgs: Record = { builder: this._handle, source, name }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withServiceReferenceNamed', + rpcArgs + ); + return new CSharpAppResource(result, this._client); + } + + /** Adds a named service discovery reference */ + withServiceReferenceNamed(source: ResourceBuilderBase, name: string): CSharpAppResourcePromise { + return new CSharpAppResourcePromise(this._withServiceReferenceNamedInternal(source, name)); + } + + /** @internal */ + private async _withReferenceUriInternal(name: string, uri: string): Promise { + const rpcArgs: Record = { builder: this._handle, name, uri }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withReferenceUri', + rpcArgs + ); + return new CSharpAppResource(result, this._client); + } + + /** Adds a reference to a URI */ + withReferenceUri(name: string, uri: string): CSharpAppResourcePromise { + return new CSharpAppResourcePromise(this._withReferenceUriInternal(name, uri)); + } + + /** @internal */ + private async _withReferenceExternalServiceInternal(externalService: ExternalServiceResource): Promise { + const rpcArgs: Record = { builder: this._handle, externalService }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withReferenceExternalService', + rpcArgs + ); + return new CSharpAppResource(result, this._client); + } + + /** Adds a reference to an external service */ + withReferenceExternalService(externalService: ExternalServiceResource): CSharpAppResourcePromise { + return new CSharpAppResourcePromise(this._withReferenceExternalServiceInternal(externalService)); + } + + /** @internal */ + private async _withReferenceEndpointInternal(endpointReference: EndpointReference): Promise { + const rpcArgs: Record = { builder: this._handle, endpointReference }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withReferenceEndpoint', + rpcArgs + ); + return new CSharpAppResource(result, this._client); + } + + /** Adds a reference to an endpoint */ + withReferenceEndpoint(endpointReference: EndpointReference): CSharpAppResourcePromise { + return new CSharpAppResourcePromise(this._withReferenceEndpointInternal(endpointReference)); + } + + /** @internal */ + private async _withEndpointInternal(port?: number, targetPort?: number, scheme?: string, name?: string, env?: string, isProxied?: boolean, isExternal?: boolean, protocol?: ProtocolType): Promise { + const rpcArgs: Record = { builder: this._handle }; + if (port !== undefined) rpcArgs.port = port; + if (targetPort !== undefined) rpcArgs.targetPort = targetPort; + if (scheme !== undefined) rpcArgs.scheme = scheme; + if (name !== undefined) rpcArgs.name = name; + if (env !== undefined) rpcArgs.env = env; + if (isProxied !== undefined) rpcArgs.isProxied = isProxied; + if (isExternal !== undefined) rpcArgs.isExternal = isExternal; + if (protocol !== undefined) rpcArgs.protocol = protocol; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withEndpoint', + rpcArgs + ); + return new CSharpAppResource(result, this._client); + } + + /** Adds a network endpoint */ + withEndpoint(options?: WithEndpointOptions): CSharpAppResourcePromise { + const port = options?.port; + const targetPort = options?.targetPort; + const scheme = options?.scheme; + const name = options?.name; + const env = options?.env; + const isProxied = options?.isProxied; + const isExternal = options?.isExternal; + const protocol = options?.protocol; + return new CSharpAppResourcePromise(this._withEndpointInternal(port, targetPort, scheme, name, env, isProxied, isExternal, protocol)); + } + + /** @internal */ + private async _withHttpEndpointInternal(port?: number, targetPort?: number, name?: string, env?: string, isProxied?: boolean): Promise { + const rpcArgs: Record = { builder: this._handle }; + if (port !== undefined) rpcArgs.port = port; + if (targetPort !== undefined) rpcArgs.targetPort = targetPort; + if (name !== undefined) rpcArgs.name = name; + if (env !== undefined) rpcArgs.env = env; + if (isProxied !== undefined) rpcArgs.isProxied = isProxied; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withHttpEndpoint', + rpcArgs + ); + return new CSharpAppResource(result, this._client); + } + + /** Adds an HTTP endpoint */ + withHttpEndpoint(options?: WithHttpEndpointOptions): CSharpAppResourcePromise { + const port = options?.port; + const targetPort = options?.targetPort; + const name = options?.name; + const env = options?.env; + const isProxied = options?.isProxied; + return new CSharpAppResourcePromise(this._withHttpEndpointInternal(port, targetPort, name, env, isProxied)); + } + + /** @internal */ + private async _withHttpsEndpointInternal(port?: number, targetPort?: number, name?: string, env?: string, isProxied?: boolean): Promise { + const rpcArgs: Record = { builder: this._handle }; + if (port !== undefined) rpcArgs.port = port; + if (targetPort !== undefined) rpcArgs.targetPort = targetPort; + if (name !== undefined) rpcArgs.name = name; + if (env !== undefined) rpcArgs.env = env; + if (isProxied !== undefined) rpcArgs.isProxied = isProxied; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withHttpsEndpoint', + rpcArgs + ); + return new CSharpAppResource(result, this._client); + } + + /** Adds an HTTPS endpoint */ + withHttpsEndpoint(options?: WithHttpsEndpointOptions): CSharpAppResourcePromise { + const port = options?.port; + const targetPort = options?.targetPort; + const name = options?.name; + const env = options?.env; + const isProxied = options?.isProxied; + return new CSharpAppResourcePromise(this._withHttpsEndpointInternal(port, targetPort, name, env, isProxied)); + } + + /** @internal */ + private async _withExternalHttpEndpointsInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withExternalHttpEndpoints', + rpcArgs + ); + return new CSharpAppResource(result, this._client); + } + + /** Makes HTTP endpoints externally accessible */ + withExternalHttpEndpoints(): CSharpAppResourcePromise { + return new CSharpAppResourcePromise(this._withExternalHttpEndpointsInternal()); + } + + /** Gets an endpoint reference */ + async getEndpoint(name: string): Promise { + const rpcArgs: Record = { builder: this._handle, name }; + return await this._client.invokeCapability( + 'Aspire.Hosting/getEndpoint', + rpcArgs + ); + } + + /** @internal */ + private async _asHttp2ServiceInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/asHttp2Service', + rpcArgs + ); + return new CSharpAppResource(result, this._client); + } + + /** Configures resource for HTTP/2 */ + asHttp2Service(): CSharpAppResourcePromise { + return new CSharpAppResourcePromise(this._asHttp2ServiceInternal()); + } + + /** @internal */ + private async _withUrlsCallbackInternal(callback: (obj: ResourceUrlsCallbackContext) => Promise): Promise { + const callbackId = registerCallback(async (objData: unknown) => { + const objHandle = wrapIfHandle(objData) as ResourceUrlsCallbackContextHandle; + const obj = new ResourceUrlsCallbackContext(objHandle, this._client); + await callback(obj); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrlsCallback', + rpcArgs + ); + return new CSharpAppResource(result, this._client); + } + + /** Customizes displayed URLs via callback */ + withUrlsCallback(callback: (obj: ResourceUrlsCallbackContext) => Promise): CSharpAppResourcePromise { + return new CSharpAppResourcePromise(this._withUrlsCallbackInternal(callback)); + } + + /** @internal */ + private async _withUrlsCallbackAsyncInternal(callback: (arg: ResourceUrlsCallbackContext) => Promise): Promise { + const callbackId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as ResourceUrlsCallbackContextHandle; + const arg = new ResourceUrlsCallbackContext(argHandle, this._client); + await callback(arg); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrlsCallbackAsync', + rpcArgs + ); + return new CSharpAppResource(result, this._client); + } + + /** Customizes displayed URLs via async callback */ + withUrlsCallbackAsync(callback: (arg: ResourceUrlsCallbackContext) => Promise): CSharpAppResourcePromise { + return new CSharpAppResourcePromise(this._withUrlsCallbackAsyncInternal(callback)); + } + + /** @internal */ + private async _withUrlInternal(url: string, displayText?: string): Promise { + const rpcArgs: Record = { builder: this._handle, url }; + if (displayText !== undefined) rpcArgs.displayText = displayText; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrl', + rpcArgs + ); + return new CSharpAppResource(result, this._client); + } + + /** Adds or modifies displayed URLs */ + withUrl(url: string, options?: WithUrlOptions): CSharpAppResourcePromise { + const displayText = options?.displayText; + return new CSharpAppResourcePromise(this._withUrlInternal(url, displayText)); + } + + /** @internal */ + private async _withUrlExpressionInternal(url: ReferenceExpression, displayText?: string): Promise { + const rpcArgs: Record = { builder: this._handle, url }; + if (displayText !== undefined) rpcArgs.displayText = displayText; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrlExpression', + rpcArgs + ); + return new CSharpAppResource(result, this._client); + } + + /** Adds a URL using a reference expression */ + withUrlExpression(url: ReferenceExpression, options?: WithUrlExpressionOptions): CSharpAppResourcePromise { + const displayText = options?.displayText; + return new CSharpAppResourcePromise(this._withUrlExpressionInternal(url, displayText)); + } + + /** @internal */ + private async _withUrlForEndpointInternal(endpointName: string, callback: (obj: ResourceUrlAnnotation) => Promise): Promise { + const callbackId = registerCallback(async (objData: unknown) => { + const obj = wrapIfHandle(objData) as ResourceUrlAnnotation; + await callback(obj); + }); + const rpcArgs: Record = { builder: this._handle, endpointName, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrlForEndpoint', + rpcArgs + ); + return new CSharpAppResource(result, this._client); + } + + /** Customizes the URL for a specific endpoint via callback */ + withUrlForEndpoint(endpointName: string, callback: (obj: ResourceUrlAnnotation) => Promise): CSharpAppResourcePromise { + return new CSharpAppResourcePromise(this._withUrlForEndpointInternal(endpointName, callback)); + } + + /** @internal */ + private async _withUrlForEndpointFactoryInternal(endpointName: string, callback: (arg: EndpointReference) => Promise): Promise { + const callbackId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as EndpointReferenceHandle; + const arg = new EndpointReference(argHandle, this._client); + return await callback(arg); + }); + const rpcArgs: Record = { builder: this._handle, endpointName, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrlForEndpointFactory', + rpcArgs + ); + return new CSharpAppResource(result, this._client); + } + + /** Adds a URL for a specific endpoint via factory callback */ + withUrlForEndpointFactory(endpointName: string, callback: (arg: EndpointReference) => Promise): CSharpAppResourcePromise { + return new CSharpAppResourcePromise(this._withUrlForEndpointFactoryInternal(endpointName, callback)); + } + + /** @internal */ + private async _publishWithContainerFilesInternal(source: ResourceBuilderBase, destinationPath: string): Promise { + const rpcArgs: Record = { builder: this._handle, source, destinationPath }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/publishWithContainerFiles', + rpcArgs + ); + return new CSharpAppResource(result, this._client); + } + + /** Configures the resource to copy container files from the specified source during publishing */ + publishWithContainerFiles(source: ResourceBuilderBase, destinationPath: string): CSharpAppResourcePromise { + return new CSharpAppResourcePromise(this._publishWithContainerFilesInternal(source, destinationPath)); + } + + /** @internal */ + private async _excludeFromManifestInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/excludeFromManifest', + rpcArgs + ); + return new CSharpAppResource(result, this._client); + } + + /** Excludes the resource from the deployment manifest */ + excludeFromManifest(): CSharpAppResourcePromise { + return new CSharpAppResourcePromise(this._excludeFromManifestInternal()); + } + + /** @internal */ + private async _waitForInternal(dependency: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, dependency }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/waitFor', + rpcArgs + ); + return new CSharpAppResource(result, this._client); + } + + /** Waits for another resource to be ready */ + waitFor(dependency: ResourceBuilderBase): CSharpAppResourcePromise { + return new CSharpAppResourcePromise(this._waitForInternal(dependency)); + } + + /** @internal */ + private async _waitForWithBehaviorInternal(dependency: ResourceBuilderBase, waitBehavior: WaitBehavior): Promise { + const rpcArgs: Record = { builder: this._handle, dependency, waitBehavior }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/waitForWithBehavior', + rpcArgs + ); + return new CSharpAppResource(result, this._client); + } + + /** Waits for another resource with specific behavior */ + waitForWithBehavior(dependency: ResourceBuilderBase, waitBehavior: WaitBehavior): CSharpAppResourcePromise { + return new CSharpAppResourcePromise(this._waitForWithBehaviorInternal(dependency, waitBehavior)); + } + + /** @internal */ + private async _waitForStartInternal(dependency: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, dependency }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/waitForStart', + rpcArgs + ); + return new CSharpAppResource(result, this._client); + } + + /** Waits for another resource to start */ + waitForStart(dependency: ResourceBuilderBase): CSharpAppResourcePromise { + return new CSharpAppResourcePromise(this._waitForStartInternal(dependency)); + } + + /** @internal */ + private async _waitForStartWithBehaviorInternal(dependency: ResourceBuilderBase, waitBehavior: WaitBehavior): Promise { + const rpcArgs: Record = { builder: this._handle, dependency, waitBehavior }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/waitForStartWithBehavior', + rpcArgs + ); + return new CSharpAppResource(result, this._client); + } + + /** Waits for another resource to start with specific behavior */ + waitForStartWithBehavior(dependency: ResourceBuilderBase, waitBehavior: WaitBehavior): CSharpAppResourcePromise { + return new CSharpAppResourcePromise(this._waitForStartWithBehaviorInternal(dependency, waitBehavior)); + } + + /** @internal */ + private async _withExplicitStartInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withExplicitStart', + rpcArgs + ); + return new CSharpAppResource(result, this._client); + } + + /** Prevents resource from starting automatically */ + withExplicitStart(): CSharpAppResourcePromise { + return new CSharpAppResourcePromise(this._withExplicitStartInternal()); + } + + /** @internal */ + private async _waitForCompletionInternal(dependency: ResourceBuilderBase, exitCode?: number): Promise { + const rpcArgs: Record = { builder: this._handle, dependency }; + if (exitCode !== undefined) rpcArgs.exitCode = exitCode; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/waitForCompletion', + rpcArgs + ); + return new CSharpAppResource(result, this._client); + } + + /** Waits for resource completion */ + waitForCompletion(dependency: ResourceBuilderBase, options?: WaitForCompletionOptions): CSharpAppResourcePromise { + const exitCode = options?.exitCode; + return new CSharpAppResourcePromise(this._waitForCompletionInternal(dependency, exitCode)); + } + + /** @internal */ + private async _withHealthCheckInternal(key: string): Promise { + const rpcArgs: Record = { builder: this._handle, key }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withHealthCheck', + rpcArgs + ); + return new CSharpAppResource(result, this._client); + } + + /** Adds a health check by key */ + withHealthCheck(key: string): CSharpAppResourcePromise { + return new CSharpAppResourcePromise(this._withHealthCheckInternal(key)); + } + + /** @internal */ + private async _withHttpHealthCheckInternal(path?: string, statusCode?: number, endpointName?: string): Promise { + const rpcArgs: Record = { builder: this._handle }; + if (path !== undefined) rpcArgs.path = path; + if (statusCode !== undefined) rpcArgs.statusCode = statusCode; + if (endpointName !== undefined) rpcArgs.endpointName = endpointName; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withHttpHealthCheck', + rpcArgs + ); + return new CSharpAppResource(result, this._client); + } + + /** Adds an HTTP health check */ + withHttpHealthCheck(options?: WithHttpHealthCheckOptions): CSharpAppResourcePromise { + const path = options?.path; + const statusCode = options?.statusCode; + const endpointName = options?.endpointName; + return new CSharpAppResourcePromise(this._withHttpHealthCheckInternal(path, statusCode, endpointName)); + } + + /** @internal */ + private async _withCommandInternal(name: string, displayName: string, executeCommand: (arg: ExecuteCommandContext) => Promise, commandOptions?: CommandOptions): Promise { + const executeCommandId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as ExecuteCommandContextHandle; + const arg = new ExecuteCommandContext(argHandle, this._client); + return await executeCommand(arg); + }); + const rpcArgs: Record = { builder: this._handle, name, displayName, executeCommand: executeCommandId }; + if (commandOptions !== undefined) rpcArgs.commandOptions = commandOptions; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withCommand', + rpcArgs + ); + return new CSharpAppResource(result, this._client); + } + + /** Adds a resource command */ + withCommand(name: string, displayName: string, executeCommand: (arg: ExecuteCommandContext) => Promise, options?: WithCommandOptions): CSharpAppResourcePromise { + const commandOptions = options?.commandOptions; + return new CSharpAppResourcePromise(this._withCommandInternal(name, displayName, executeCommand, commandOptions)); + } + + /** @internal */ + private async _withDeveloperCertificateTrustInternal(trust: boolean): Promise { + const rpcArgs: Record = { builder: this._handle, trust }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withDeveloperCertificateTrust', + rpcArgs + ); + return new CSharpAppResource(result, this._client); + } + + /** Configures developer certificate trust */ + withDeveloperCertificateTrust(trust: boolean): CSharpAppResourcePromise { + return new CSharpAppResourcePromise(this._withDeveloperCertificateTrustInternal(trust)); + } + + /** @internal */ + private async _withCertificateTrustScopeInternal(scope: CertificateTrustScope): Promise { + const rpcArgs: Record = { builder: this._handle, scope }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withCertificateTrustScope', + rpcArgs + ); + return new CSharpAppResource(result, this._client); + } + + /** Sets the certificate trust scope */ + withCertificateTrustScope(scope: CertificateTrustScope): CSharpAppResourcePromise { + return new CSharpAppResourcePromise(this._withCertificateTrustScopeInternal(scope)); + } + + /** @internal */ + private async _withHttpsDeveloperCertificateInternal(password?: ParameterResource): Promise { + const rpcArgs: Record = { builder: this._handle }; + if (password !== undefined) rpcArgs.password = password; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withHttpsDeveloperCertificate', + rpcArgs + ); + return new CSharpAppResource(result, this._client); + } + + /** Configures HTTPS with a developer certificate */ + withHttpsDeveloperCertificate(options?: WithHttpsDeveloperCertificateOptions): CSharpAppResourcePromise { + const password = options?.password; + return new CSharpAppResourcePromise(this._withHttpsDeveloperCertificateInternal(password)); + } + + /** @internal */ + private async _withoutHttpsCertificateInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withoutHttpsCertificate', + rpcArgs + ); + return new CSharpAppResource(result, this._client); + } + + /** Removes HTTPS certificate configuration */ + withoutHttpsCertificate(): CSharpAppResourcePromise { + return new CSharpAppResourcePromise(this._withoutHttpsCertificateInternal()); + } + + /** @internal */ + private async _withParentRelationshipInternal(parent: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, parent }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withParentRelationship', + rpcArgs + ); + return new CSharpAppResource(result, this._client); + } + + /** Sets the parent relationship */ + withParentRelationship(parent: ResourceBuilderBase): CSharpAppResourcePromise { + return new CSharpAppResourcePromise(this._withParentRelationshipInternal(parent)); + } + + /** @internal */ + private async _withChildRelationshipInternal(child: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, child }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withChildRelationship', + rpcArgs + ); + return new CSharpAppResource(result, this._client); + } + + /** Sets a child relationship */ + withChildRelationship(child: ResourceBuilderBase): CSharpAppResourcePromise { + return new CSharpAppResourcePromise(this._withChildRelationshipInternal(child)); + } + + /** @internal */ + private async _withIconNameInternal(iconName: string, iconVariant?: IconVariant): Promise { + const rpcArgs: Record = { builder: this._handle, iconName }; + if (iconVariant !== undefined) rpcArgs.iconVariant = iconVariant; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withIconName', + rpcArgs + ); + return new CSharpAppResource(result, this._client); + } + + /** Sets the icon for the resource */ + withIconName(iconName: string, options?: WithIconNameOptions): CSharpAppResourcePromise { + const iconVariant = options?.iconVariant; + return new CSharpAppResourcePromise(this._withIconNameInternal(iconName, iconVariant)); + } + + /** @internal */ + private async _withHttpProbeInternal(probeType: ProbeType, path?: string, initialDelaySeconds?: number, periodSeconds?: number, timeoutSeconds?: number, failureThreshold?: number, successThreshold?: number, endpointName?: string): Promise { + const rpcArgs: Record = { builder: this._handle, probeType }; + if (path !== undefined) rpcArgs.path = path; + if (initialDelaySeconds !== undefined) rpcArgs.initialDelaySeconds = initialDelaySeconds; + if (periodSeconds !== undefined) rpcArgs.periodSeconds = periodSeconds; + if (timeoutSeconds !== undefined) rpcArgs.timeoutSeconds = timeoutSeconds; + if (failureThreshold !== undefined) rpcArgs.failureThreshold = failureThreshold; + if (successThreshold !== undefined) rpcArgs.successThreshold = successThreshold; + if (endpointName !== undefined) rpcArgs.endpointName = endpointName; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withHttpProbe', + rpcArgs + ); + return new CSharpAppResource(result, this._client); + } + + /** Adds an HTTP health probe to the resource */ + withHttpProbe(probeType: ProbeType, options?: WithHttpProbeOptions): CSharpAppResourcePromise { + const path = options?.path; + const initialDelaySeconds = options?.initialDelaySeconds; + const periodSeconds = options?.periodSeconds; + const timeoutSeconds = options?.timeoutSeconds; + const failureThreshold = options?.failureThreshold; + const successThreshold = options?.successThreshold; + const endpointName = options?.endpointName; + return new CSharpAppResourcePromise(this._withHttpProbeInternal(probeType, path, initialDelaySeconds, periodSeconds, timeoutSeconds, failureThreshold, successThreshold, endpointName)); + } + + /** @internal */ + private async _excludeFromMcpInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/excludeFromMcp', + rpcArgs + ); + return new CSharpAppResource(result, this._client); + } + + /** Excludes the resource from MCP server exposure */ + excludeFromMcp(): CSharpAppResourcePromise { + return new CSharpAppResourcePromise(this._excludeFromMcpInternal()); + } + + /** @internal */ + private async _withRemoteImageNameInternal(remoteImageName: string): Promise { + const rpcArgs: Record = { builder: this._handle, remoteImageName }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withRemoteImageName', + rpcArgs + ); + return new CSharpAppResource(result, this._client); + } + + /** Sets the remote image name for publishing */ + withRemoteImageName(remoteImageName: string): CSharpAppResourcePromise { + return new CSharpAppResourcePromise(this._withRemoteImageNameInternal(remoteImageName)); + } + + /** @internal */ + private async _withRemoteImageTagInternal(remoteImageTag: string): Promise { + const rpcArgs: Record = { builder: this._handle, remoteImageTag }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withRemoteImageTag', + rpcArgs + ); + return new CSharpAppResource(result, this._client); + } + + /** Sets the remote image tag for publishing */ + withRemoteImageTag(remoteImageTag: string): CSharpAppResourcePromise { + return new CSharpAppResourcePromise(this._withRemoteImageTagInternal(remoteImageTag)); + } + + /** @internal */ + private async _withPipelineStepFactoryInternal(stepName: string, callback: (arg: PipelineStepContext) => Promise, dependsOn?: string[], requiredBy?: string[], tags?: string[], description?: string): Promise { + const callbackId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as PipelineStepContextHandle; + const arg = new PipelineStepContext(argHandle, this._client); + await callback(arg); + }); + const rpcArgs: Record = { builder: this._handle, stepName, callback: callbackId }; + if (dependsOn !== undefined) rpcArgs.dependsOn = dependsOn; + if (requiredBy !== undefined) rpcArgs.requiredBy = requiredBy; + if (tags !== undefined) rpcArgs.tags = tags; + if (description !== undefined) rpcArgs.description = description; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withPipelineStepFactory', + rpcArgs + ); + return new CSharpAppResource(result, this._client); + } + + /** Adds a pipeline step to the resource */ + withPipelineStepFactory(stepName: string, callback: (arg: PipelineStepContext) => Promise, options?: WithPipelineStepFactoryOptions): CSharpAppResourcePromise { + const dependsOn = options?.dependsOn; + const requiredBy = options?.requiredBy; + const tags = options?.tags; + const description = options?.description; + return new CSharpAppResourcePromise(this._withPipelineStepFactoryInternal(stepName, callback, dependsOn, requiredBy, tags, description)); + } + + /** @internal */ + private async _withPipelineConfigurationAsyncInternal(callback: (arg: PipelineConfigurationContext) => Promise): Promise { + const callbackId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as PipelineConfigurationContextHandle; + const arg = new PipelineConfigurationContext(argHandle, this._client); + await callback(arg); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withPipelineConfigurationAsync', + rpcArgs + ); + return new CSharpAppResource(result, this._client); + } + + /** Configures pipeline step dependencies via an async callback */ + withPipelineConfigurationAsync(callback: (arg: PipelineConfigurationContext) => Promise): CSharpAppResourcePromise { + return new CSharpAppResourcePromise(this._withPipelineConfigurationAsyncInternal(callback)); + } + + /** @internal */ + private async _withPipelineConfigurationInternal(callback: (obj: PipelineConfigurationContext) => Promise): Promise { + const callbackId = registerCallback(async (objData: unknown) => { + const objHandle = wrapIfHandle(objData) as PipelineConfigurationContextHandle; + const obj = new PipelineConfigurationContext(objHandle, this._client); + await callback(obj); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withPipelineConfiguration', + rpcArgs + ); + return new CSharpAppResource(result, this._client); + } + + /** Configures pipeline step dependencies via a callback */ + withPipelineConfiguration(callback: (obj: PipelineConfigurationContext) => Promise): CSharpAppResourcePromise { + return new CSharpAppResourcePromise(this._withPipelineConfigurationInternal(callback)); + } + + /** Gets the resource name */ + async getResourceName(): Promise { + const rpcArgs: Record = { resource: this._handle }; + return await this._client.invokeCapability( + 'Aspire.Hosting/getResourceName', + rpcArgs + ); + } + + /** @internal */ + private async _withStorageRoleAssignmentsInternal(target: AzureStorageResource, roles: AzureStorageRole[]): Promise { + const rpcArgs: Record = { builder: this._handle, target, roles }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure.Storage/withStorageRoleAssignments', + rpcArgs + ); + return new CSharpAppResource(result, this._client); + } + + /** Assigns Azure Storage roles to a resource */ + withStorageRoleAssignments(target: AzureStorageResource, roles: AzureStorageRole[]): CSharpAppResourcePromise { + return new CSharpAppResourcePromise(this._withStorageRoleAssignmentsInternal(target, roles)); + } + + /** @internal */ + private async _withEventHubsRoleAssignmentsInternal(target: AzureEventHubsResource, roles: AzureEventHubsRole[]): Promise { + const rpcArgs: Record = { builder: this._handle, target, roles }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure.EventHubs/withEventHubsRoleAssignments', + rpcArgs + ); + return new CSharpAppResource(result, this._client); + } + + /** Assigns Event Hubs roles to a resource */ + withEventHubsRoleAssignments(target: AzureEventHubsResource, roles: AzureEventHubsRole[]): CSharpAppResourcePromise { + return new CSharpAppResourcePromise(this._withEventHubsRoleAssignmentsInternal(target, roles)); + } + + /** @internal */ + private async _withEnvironmentFromOutputInternal(name: string, bicepOutputReference: BicepOutputReference): Promise { + const rpcArgs: Record = { builder: this._handle, name, bicepOutputReference }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure/withEnvironmentFromOutput', + rpcArgs + ); + return new CSharpAppResource(result, this._client); + } + + /** Sets an environment variable from a Bicep output reference */ + withEnvironmentFromOutput(name: string, bicepOutputReference: BicepOutputReference): CSharpAppResourcePromise { + return new CSharpAppResourcePromise(this._withEnvironmentFromOutputInternal(name, bicepOutputReference)); + } + + /** @internal */ + private async _withEnvironmentFromKeyVaultSecretInternal(name: string, secretReference: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, name, secretReference }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure/withEnvironmentFromKeyVaultSecret', + rpcArgs + ); + return new CSharpAppResource(result, this._client); + } + + /** Sets an environment variable from an Azure Key Vault secret reference */ + withEnvironmentFromKeyVaultSecret(name: string, secretReference: ResourceBuilderBase): CSharpAppResourcePromise { + return new CSharpAppResourcePromise(this._withEnvironmentFromKeyVaultSecretInternal(name, secretReference)); + } + + /** @internal */ + private async _withAzureUserAssignedIdentityInternal(identityResourceBuilder: AzureUserAssignedIdentityResource): Promise { + const rpcArgs: Record = { builder: this._handle, identityResourceBuilder }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure/withUserAssignedIdentityAzureUserAssignedIdentity', + rpcArgs + ); + return new CSharpAppResource(result, this._client); + } + + /** Associates an Azure user-assigned identity with a compute resource */ + withAzureUserAssignedIdentity(identityResourceBuilder: AzureUserAssignedIdentityResource): CSharpAppResourcePromise { + return new CSharpAppResourcePromise(this._withAzureUserAssignedIdentityInternal(identityResourceBuilder)); + } + +} + +/** + * Thenable wrapper for CSharpAppResource that enables fluent chaining. + * @example + * await builder.addSomething().withX().withY(); + */ +export class CSharpAppResourcePromise implements PromiseLike { + constructor(private _promise: Promise) {} + + then( + onfulfilled?: ((value: CSharpAppResource) => TResult1 | PromiseLike) | null, + onrejected?: ((reason: unknown) => TResult2 | PromiseLike) | null + ): PromiseLike { + return this._promise.then(onfulfilled, onrejected); + } + + /** Configures a resource to use a container registry */ + withContainerRegistry(registry: ResourceBuilderBase): CSharpAppResourcePromise { + return new CSharpAppResourcePromise(this._promise.then(obj => obj.withContainerRegistry(registry))); + } + + /** Sets the base image for a Dockerfile build */ + withDockerfileBaseImage(options?: WithDockerfileBaseImageOptions): CSharpAppResourcePromise { + return new CSharpAppResourcePromise(this._promise.then(obj => obj.withDockerfileBaseImage(options))); + } + + /** Configures an MCP server endpoint on the resource */ + withMcpServer(options?: WithMcpServerOptions): CSharpAppResourcePromise { + return new CSharpAppResourcePromise(this._promise.then(obj => obj.withMcpServer(options))); + } + + /** Configures OTLP telemetry export */ + withOtlpExporter(): CSharpAppResourcePromise { + return new CSharpAppResourcePromise(this._promise.then(obj => obj.withOtlpExporter())); + } + + /** Configures OTLP telemetry export with specific protocol */ + withOtlpExporterProtocol(protocol: OtlpProtocol): CSharpAppResourcePromise { + return new CSharpAppResourcePromise(this._promise.then(obj => obj.withOtlpExporterProtocol(protocol))); + } + + /** Sets the number of replicas */ + withReplicas(replicas: number): CSharpAppResourcePromise { + return new CSharpAppResourcePromise(this._promise.then(obj => obj.withReplicas(replicas))); + } + + /** Disables forwarded headers for the project */ + disableForwardedHeaders(): CSharpAppResourcePromise { + return new CSharpAppResourcePromise(this._promise.then(obj => obj.disableForwardedHeaders())); + } + + /** Publishes a project as a Docker file with optional container configuration */ + publishAsDockerFile(options?: PublishAsDockerFileOptions): CSharpAppResourcePromise { + return new CSharpAppResourcePromise(this._promise.then(obj => obj.publishAsDockerFile(options))); + } + + /** Adds a required command dependency */ + withRequiredCommand(command: string, options?: WithRequiredCommandOptions): CSharpAppResourcePromise { + return new CSharpAppResourcePromise(this._promise.then(obj => obj.withRequiredCommand(command, options))); + } + + /** Sets an environment variable */ + withEnvironment(name: string, value: string): CSharpAppResourcePromise { + return new CSharpAppResourcePromise(this._promise.then(obj => obj.withEnvironment(name, value))); + } + + /** Adds an environment variable with a reference expression */ + withEnvironmentExpression(name: string, value: ReferenceExpression): CSharpAppResourcePromise { + return new CSharpAppResourcePromise(this._promise.then(obj => obj.withEnvironmentExpression(name, value))); + } + + /** Sets environment variables via callback */ + withEnvironmentCallback(callback: (obj: EnvironmentCallbackContext) => Promise): CSharpAppResourcePromise { + return new CSharpAppResourcePromise(this._promise.then(obj => obj.withEnvironmentCallback(callback))); + } + + /** Sets environment variables via async callback */ + withEnvironmentCallbackAsync(callback: (arg: EnvironmentCallbackContext) => Promise): CSharpAppResourcePromise { + return new CSharpAppResourcePromise(this._promise.then(obj => obj.withEnvironmentCallbackAsync(callback))); + } + + /** Sets an environment variable from an endpoint reference */ + withEnvironmentEndpoint(name: string, endpointReference: EndpointReference): CSharpAppResourcePromise { + return new CSharpAppResourcePromise(this._promise.then(obj => obj.withEnvironmentEndpoint(name, endpointReference))); + } + + /** Sets an environment variable from a parameter resource */ + withEnvironmentParameter(name: string, parameter: ParameterResource): CSharpAppResourcePromise { + return new CSharpAppResourcePromise(this._promise.then(obj => obj.withEnvironmentParameter(name, parameter))); + } + + /** Sets an environment variable from a connection string resource */ + withEnvironmentConnectionString(envVarName: string, resource: ResourceBuilderBase): CSharpAppResourcePromise { + return new CSharpAppResourcePromise(this._promise.then(obj => obj.withEnvironmentConnectionString(envVarName, resource))); + } + + /** Adds arguments */ + withArgs(args: string[]): CSharpAppResourcePromise { + return new CSharpAppResourcePromise(this._promise.then(obj => obj.withArgs(args))); + } + + /** Sets command-line arguments via callback */ + withArgsCallback(callback: (obj: CommandLineArgsCallbackContext) => Promise): CSharpAppResourcePromise { + return new CSharpAppResourcePromise(this._promise.then(obj => obj.withArgsCallback(callback))); + } + + /** Sets command-line arguments via async callback */ + withArgsCallbackAsync(callback: (arg: CommandLineArgsCallbackContext) => Promise): CSharpAppResourcePromise { + return new CSharpAppResourcePromise(this._promise.then(obj => obj.withArgsCallbackAsync(callback))); + } + + /** Adds a reference to another resource */ + withReference(source: ResourceBuilderBase, options?: WithReferenceOptions): CSharpAppResourcePromise { + return new CSharpAppResourcePromise(this._promise.then(obj => obj.withReference(source, options))); + } + + /** Adds a service discovery reference to another resource */ + withServiceReference(source: ResourceBuilderBase): CSharpAppResourcePromise { + return new CSharpAppResourcePromise(this._promise.then(obj => obj.withServiceReference(source))); + } + + /** Adds a named service discovery reference */ + withServiceReferenceNamed(source: ResourceBuilderBase, name: string): CSharpAppResourcePromise { + return new CSharpAppResourcePromise(this._promise.then(obj => obj.withServiceReferenceNamed(source, name))); + } + + /** Adds a reference to a URI */ + withReferenceUri(name: string, uri: string): CSharpAppResourcePromise { + return new CSharpAppResourcePromise(this._promise.then(obj => obj.withReferenceUri(name, uri))); + } + + /** Adds a reference to an external service */ + withReferenceExternalService(externalService: ExternalServiceResource): CSharpAppResourcePromise { + return new CSharpAppResourcePromise(this._promise.then(obj => obj.withReferenceExternalService(externalService))); + } + + /** Adds a reference to an endpoint */ + withReferenceEndpoint(endpointReference: EndpointReference): CSharpAppResourcePromise { + return new CSharpAppResourcePromise(this._promise.then(obj => obj.withReferenceEndpoint(endpointReference))); + } + + /** Adds a network endpoint */ + withEndpoint(options?: WithEndpointOptions): CSharpAppResourcePromise { + return new CSharpAppResourcePromise(this._promise.then(obj => obj.withEndpoint(options))); + } + + /** Adds an HTTP endpoint */ + withHttpEndpoint(options?: WithHttpEndpointOptions): CSharpAppResourcePromise { + return new CSharpAppResourcePromise(this._promise.then(obj => obj.withHttpEndpoint(options))); + } + + /** Adds an HTTPS endpoint */ + withHttpsEndpoint(options?: WithHttpsEndpointOptions): CSharpAppResourcePromise { + return new CSharpAppResourcePromise(this._promise.then(obj => obj.withHttpsEndpoint(options))); + } + + /** Makes HTTP endpoints externally accessible */ + withExternalHttpEndpoints(): CSharpAppResourcePromise { + return new CSharpAppResourcePromise(this._promise.then(obj => obj.withExternalHttpEndpoints())); + } + + /** Gets an endpoint reference */ + getEndpoint(name: string): Promise { + return this._promise.then(obj => obj.getEndpoint(name)); + } + + /** Configures resource for HTTP/2 */ + asHttp2Service(): CSharpAppResourcePromise { + return new CSharpAppResourcePromise(this._promise.then(obj => obj.asHttp2Service())); + } + + /** Customizes displayed URLs via callback */ + withUrlsCallback(callback: (obj: ResourceUrlsCallbackContext) => Promise): CSharpAppResourcePromise { + return new CSharpAppResourcePromise(this._promise.then(obj => obj.withUrlsCallback(callback))); + } + + /** Customizes displayed URLs via async callback */ + withUrlsCallbackAsync(callback: (arg: ResourceUrlsCallbackContext) => Promise): CSharpAppResourcePromise { + return new CSharpAppResourcePromise(this._promise.then(obj => obj.withUrlsCallbackAsync(callback))); + } + + /** Adds or modifies displayed URLs */ + withUrl(url: string, options?: WithUrlOptions): CSharpAppResourcePromise { + return new CSharpAppResourcePromise(this._promise.then(obj => obj.withUrl(url, options))); + } + + /** Adds a URL using a reference expression */ + withUrlExpression(url: ReferenceExpression, options?: WithUrlExpressionOptions): CSharpAppResourcePromise { + return new CSharpAppResourcePromise(this._promise.then(obj => obj.withUrlExpression(url, options))); + } + + /** Customizes the URL for a specific endpoint via callback */ + withUrlForEndpoint(endpointName: string, callback: (obj: ResourceUrlAnnotation) => Promise): CSharpAppResourcePromise { + return new CSharpAppResourcePromise(this._promise.then(obj => obj.withUrlForEndpoint(endpointName, callback))); + } + + /** Adds a URL for a specific endpoint via factory callback */ + withUrlForEndpointFactory(endpointName: string, callback: (arg: EndpointReference) => Promise): CSharpAppResourcePromise { + return new CSharpAppResourcePromise(this._promise.then(obj => obj.withUrlForEndpointFactory(endpointName, callback))); + } + + /** Configures the resource to copy container files from the specified source during publishing */ + publishWithContainerFiles(source: ResourceBuilderBase, destinationPath: string): CSharpAppResourcePromise { + return new CSharpAppResourcePromise(this._promise.then(obj => obj.publishWithContainerFiles(source, destinationPath))); + } + + /** Excludes the resource from the deployment manifest */ + excludeFromManifest(): CSharpAppResourcePromise { + return new CSharpAppResourcePromise(this._promise.then(obj => obj.excludeFromManifest())); + } + + /** Waits for another resource to be ready */ + waitFor(dependency: ResourceBuilderBase): CSharpAppResourcePromise { + return new CSharpAppResourcePromise(this._promise.then(obj => obj.waitFor(dependency))); + } + + /** Waits for another resource with specific behavior */ + waitForWithBehavior(dependency: ResourceBuilderBase, waitBehavior: WaitBehavior): CSharpAppResourcePromise { + return new CSharpAppResourcePromise(this._promise.then(obj => obj.waitForWithBehavior(dependency, waitBehavior))); + } + + /** Waits for another resource to start */ + waitForStart(dependency: ResourceBuilderBase): CSharpAppResourcePromise { + return new CSharpAppResourcePromise(this._promise.then(obj => obj.waitForStart(dependency))); + } + + /** Waits for another resource to start with specific behavior */ + waitForStartWithBehavior(dependency: ResourceBuilderBase, waitBehavior: WaitBehavior): CSharpAppResourcePromise { + return new CSharpAppResourcePromise(this._promise.then(obj => obj.waitForStartWithBehavior(dependency, waitBehavior))); + } + + /** Prevents resource from starting automatically */ + withExplicitStart(): CSharpAppResourcePromise { + return new CSharpAppResourcePromise(this._promise.then(obj => obj.withExplicitStart())); + } + + /** Waits for resource completion */ + waitForCompletion(dependency: ResourceBuilderBase, options?: WaitForCompletionOptions): CSharpAppResourcePromise { + return new CSharpAppResourcePromise(this._promise.then(obj => obj.waitForCompletion(dependency, options))); + } + + /** Adds a health check by key */ + withHealthCheck(key: string): CSharpAppResourcePromise { + return new CSharpAppResourcePromise(this._promise.then(obj => obj.withHealthCheck(key))); + } + + /** Adds an HTTP health check */ + withHttpHealthCheck(options?: WithHttpHealthCheckOptions): CSharpAppResourcePromise { + return new CSharpAppResourcePromise(this._promise.then(obj => obj.withHttpHealthCheck(options))); + } + + /** Adds a resource command */ + withCommand(name: string, displayName: string, executeCommand: (arg: ExecuteCommandContext) => Promise, options?: WithCommandOptions): CSharpAppResourcePromise { + return new CSharpAppResourcePromise(this._promise.then(obj => obj.withCommand(name, displayName, executeCommand, options))); + } + + /** Configures developer certificate trust */ + withDeveloperCertificateTrust(trust: boolean): CSharpAppResourcePromise { + return new CSharpAppResourcePromise(this._promise.then(obj => obj.withDeveloperCertificateTrust(trust))); + } + + /** Sets the certificate trust scope */ + withCertificateTrustScope(scope: CertificateTrustScope): CSharpAppResourcePromise { + return new CSharpAppResourcePromise(this._promise.then(obj => obj.withCertificateTrustScope(scope))); + } + + /** Configures HTTPS with a developer certificate */ + withHttpsDeveloperCertificate(options?: WithHttpsDeveloperCertificateOptions): CSharpAppResourcePromise { + return new CSharpAppResourcePromise(this._promise.then(obj => obj.withHttpsDeveloperCertificate(options))); + } + + /** Removes HTTPS certificate configuration */ + withoutHttpsCertificate(): CSharpAppResourcePromise { + return new CSharpAppResourcePromise(this._promise.then(obj => obj.withoutHttpsCertificate())); + } + + /** Sets the parent relationship */ + withParentRelationship(parent: ResourceBuilderBase): CSharpAppResourcePromise { + return new CSharpAppResourcePromise(this._promise.then(obj => obj.withParentRelationship(parent))); + } + + /** Sets a child relationship */ + withChildRelationship(child: ResourceBuilderBase): CSharpAppResourcePromise { + return new CSharpAppResourcePromise(this._promise.then(obj => obj.withChildRelationship(child))); + } + + /** Sets the icon for the resource */ + withIconName(iconName: string, options?: WithIconNameOptions): CSharpAppResourcePromise { + return new CSharpAppResourcePromise(this._promise.then(obj => obj.withIconName(iconName, options))); + } + + /** Adds an HTTP health probe to the resource */ + withHttpProbe(probeType: ProbeType, options?: WithHttpProbeOptions): CSharpAppResourcePromise { + return new CSharpAppResourcePromise(this._promise.then(obj => obj.withHttpProbe(probeType, options))); + } + + /** Excludes the resource from MCP server exposure */ + excludeFromMcp(): CSharpAppResourcePromise { + return new CSharpAppResourcePromise(this._promise.then(obj => obj.excludeFromMcp())); + } + + /** Sets the remote image name for publishing */ + withRemoteImageName(remoteImageName: string): CSharpAppResourcePromise { + return new CSharpAppResourcePromise(this._promise.then(obj => obj.withRemoteImageName(remoteImageName))); + } + + /** Sets the remote image tag for publishing */ + withRemoteImageTag(remoteImageTag: string): CSharpAppResourcePromise { + return new CSharpAppResourcePromise(this._promise.then(obj => obj.withRemoteImageTag(remoteImageTag))); + } + + /** Adds a pipeline step to the resource */ + withPipelineStepFactory(stepName: string, callback: (arg: PipelineStepContext) => Promise, options?: WithPipelineStepFactoryOptions): CSharpAppResourcePromise { + return new CSharpAppResourcePromise(this._promise.then(obj => obj.withPipelineStepFactory(stepName, callback, options))); + } + + /** Configures pipeline step dependencies via an async callback */ + withPipelineConfigurationAsync(callback: (arg: PipelineConfigurationContext) => Promise): CSharpAppResourcePromise { + return new CSharpAppResourcePromise(this._promise.then(obj => obj.withPipelineConfigurationAsync(callback))); + } + + /** Configures pipeline step dependencies via a callback */ + withPipelineConfiguration(callback: (obj: PipelineConfigurationContext) => Promise): CSharpAppResourcePromise { + return new CSharpAppResourcePromise(this._promise.then(obj => obj.withPipelineConfiguration(callback))); + } + + /** Gets the resource name */ + getResourceName(): Promise { + return this._promise.then(obj => obj.getResourceName()); + } + + /** Assigns Azure Storage roles to a resource */ + withStorageRoleAssignments(target: AzureStorageResource, roles: AzureStorageRole[]): CSharpAppResourcePromise { + return new CSharpAppResourcePromise(this._promise.then(obj => obj.withStorageRoleAssignments(target, roles))); + } + + /** Assigns Event Hubs roles to a resource */ + withEventHubsRoleAssignments(target: AzureEventHubsResource, roles: AzureEventHubsRole[]): CSharpAppResourcePromise { + return new CSharpAppResourcePromise(this._promise.then(obj => obj.withEventHubsRoleAssignments(target, roles))); + } + + /** Sets an environment variable from a Bicep output reference */ + withEnvironmentFromOutput(name: string, bicepOutputReference: BicepOutputReference): CSharpAppResourcePromise { + return new CSharpAppResourcePromise(this._promise.then(obj => obj.withEnvironmentFromOutput(name, bicepOutputReference))); + } + + /** Sets an environment variable from an Azure Key Vault secret reference */ + withEnvironmentFromKeyVaultSecret(name: string, secretReference: ResourceBuilderBase): CSharpAppResourcePromise { + return new CSharpAppResourcePromise(this._promise.then(obj => obj.withEnvironmentFromKeyVaultSecret(name, secretReference))); + } + + /** Associates an Azure user-assigned identity with a compute resource */ + withAzureUserAssignedIdentity(identityResourceBuilder: AzureUserAssignedIdentityResource): CSharpAppResourcePromise { + return new CSharpAppResourcePromise(this._promise.then(obj => obj.withAzureUserAssignedIdentity(identityResourceBuilder))); + } + +} + +// ============================================================================ +// DotnetToolResource +// ============================================================================ + +export class DotnetToolResource extends ResourceBuilderBase { + constructor(handle: DotnetToolResourceHandle, client: AspireClientRpc) { + super(handle, client); + } + + /** @internal */ + private async _withContainerRegistryInternal(registry: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, registry }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withContainerRegistry', + rpcArgs + ); + return new DotnetToolResource(result, this._client); + } + + /** Configures a resource to use a container registry */ + withContainerRegistry(registry: ResourceBuilderBase): DotnetToolResourcePromise { + return new DotnetToolResourcePromise(this._withContainerRegistryInternal(registry)); + } + + /** @internal */ + private async _withDockerfileBaseImageInternal(buildImage?: string, runtimeImage?: string): Promise { + const rpcArgs: Record = { builder: this._handle }; + if (buildImage !== undefined) rpcArgs.buildImage = buildImage; + if (runtimeImage !== undefined) rpcArgs.runtimeImage = runtimeImage; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withDockerfileBaseImage', + rpcArgs + ); + return new DotnetToolResource(result, this._client); + } + + /** Sets the base image for a Dockerfile build */ + withDockerfileBaseImage(options?: WithDockerfileBaseImageOptions): DotnetToolResourcePromise { + const buildImage = options?.buildImage; + const runtimeImage = options?.runtimeImage; + return new DotnetToolResourcePromise(this._withDockerfileBaseImageInternal(buildImage, runtimeImage)); + } + + /** @internal */ + private async _withToolPackageInternal(packageId: string): Promise { + const rpcArgs: Record = { builder: this._handle, packageId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withToolPackage', + rpcArgs + ); + return new DotnetToolResource(result, this._client); + } + + /** Sets the tool package ID */ + withToolPackage(packageId: string): DotnetToolResourcePromise { + return new DotnetToolResourcePromise(this._withToolPackageInternal(packageId)); + } + + /** @internal */ + private async _withToolVersionInternal(version: string): Promise { + const rpcArgs: Record = { builder: this._handle, version }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withToolVersion', + rpcArgs + ); + return new DotnetToolResource(result, this._client); + } + + /** Sets the tool version */ + withToolVersion(version: string): DotnetToolResourcePromise { + return new DotnetToolResourcePromise(this._withToolVersionInternal(version)); + } + + /** @internal */ + private async _withToolPrereleaseInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withToolPrerelease', + rpcArgs + ); + return new DotnetToolResource(result, this._client); + } + + /** Allows prerelease tool versions */ + withToolPrerelease(): DotnetToolResourcePromise { + return new DotnetToolResourcePromise(this._withToolPrereleaseInternal()); + } + + /** @internal */ + private async _withToolSourceInternal(source: string): Promise { + const rpcArgs: Record = { builder: this._handle, source }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withToolSource', + rpcArgs + ); + return new DotnetToolResource(result, this._client); + } + + /** Adds a NuGet source for the tool */ + withToolSource(source: string): DotnetToolResourcePromise { + return new DotnetToolResourcePromise(this._withToolSourceInternal(source)); + } + + /** @internal */ + private async _withToolIgnoreExistingFeedsInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withToolIgnoreExistingFeeds', + rpcArgs + ); + return new DotnetToolResource(result, this._client); + } + + /** Ignores existing NuGet feeds */ + withToolIgnoreExistingFeeds(): DotnetToolResourcePromise { + return new DotnetToolResourcePromise(this._withToolIgnoreExistingFeedsInternal()); + } + + /** @internal */ + private async _withToolIgnoreFailedSourcesInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withToolIgnoreFailedSources', + rpcArgs + ); + return new DotnetToolResource(result, this._client); + } + + /** Ignores failed NuGet sources */ + withToolIgnoreFailedSources(): DotnetToolResourcePromise { + return new DotnetToolResourcePromise(this._withToolIgnoreFailedSourcesInternal()); + } + + /** @internal */ + private async _publishAsDockerFileInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/publishAsDockerFile', + rpcArgs + ); + return new DotnetToolResource(result, this._client); + } + + /** Publishes the executable as a Docker container */ + publishAsDockerFile(): DotnetToolResourcePromise { + return new DotnetToolResourcePromise(this._publishAsDockerFileInternal()); + } + + /** @internal */ + private async _publishAsDockerFileWithConfigureInternal(configure: (obj: ContainerResource) => Promise): Promise { + const configureId = registerCallback(async (objData: unknown) => { + const objHandle = wrapIfHandle(objData) as ContainerResourceHandle; + const obj = new ContainerResource(objHandle, this._client); + await configure(obj); + }); + const rpcArgs: Record = { builder: this._handle, configure: configureId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/publishAsDockerFileWithConfigure', + rpcArgs + ); + return new DotnetToolResource(result, this._client); + } + + /** Publishes an executable as a Docker file with optional container configuration */ + publishAsDockerFileWithConfigure(configure: (obj: ContainerResource) => Promise): DotnetToolResourcePromise { + return new DotnetToolResourcePromise(this._publishAsDockerFileWithConfigureInternal(configure)); + } + + /** @internal */ + private async _withExecutableCommandInternal(command: string): Promise { + const rpcArgs: Record = { builder: this._handle, command }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withExecutableCommand', + rpcArgs + ); + return new DotnetToolResource(result, this._client); + } + + /** Sets the executable command */ + withExecutableCommand(command: string): DotnetToolResourcePromise { + return new DotnetToolResourcePromise(this._withExecutableCommandInternal(command)); + } + + /** @internal */ + private async _withWorkingDirectoryInternal(workingDirectory: string): Promise { + const rpcArgs: Record = { builder: this._handle, workingDirectory }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withWorkingDirectory', + rpcArgs + ); + return new DotnetToolResource(result, this._client); + } + + /** Sets the executable working directory */ + withWorkingDirectory(workingDirectory: string): DotnetToolResourcePromise { + return new DotnetToolResourcePromise(this._withWorkingDirectoryInternal(workingDirectory)); + } + + /** @internal */ + private async _withMcpServerInternal(path?: string, endpointName?: string): Promise { + const rpcArgs: Record = { builder: this._handle }; + if (path !== undefined) rpcArgs.path = path; + if (endpointName !== undefined) rpcArgs.endpointName = endpointName; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withMcpServer', + rpcArgs + ); + return new DotnetToolResource(result, this._client); + } + + /** Configures an MCP server endpoint on the resource */ + withMcpServer(options?: WithMcpServerOptions): DotnetToolResourcePromise { + const path = options?.path; + const endpointName = options?.endpointName; + return new DotnetToolResourcePromise(this._withMcpServerInternal(path, endpointName)); + } + + /** @internal */ + private async _withOtlpExporterInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withOtlpExporter', + rpcArgs + ); + return new DotnetToolResource(result, this._client); + } + + /** Configures OTLP telemetry export */ + withOtlpExporter(): DotnetToolResourcePromise { + return new DotnetToolResourcePromise(this._withOtlpExporterInternal()); + } + + /** @internal */ + private async _withOtlpExporterProtocolInternal(protocol: OtlpProtocol): Promise { + const rpcArgs: Record = { builder: this._handle, protocol }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withOtlpExporterProtocol', + rpcArgs + ); + return new DotnetToolResource(result, this._client); + } + + /** Configures OTLP telemetry export with specific protocol */ + withOtlpExporterProtocol(protocol: OtlpProtocol): DotnetToolResourcePromise { + return new DotnetToolResourcePromise(this._withOtlpExporterProtocolInternal(protocol)); + } + + /** @internal */ + private async _withRequiredCommandInternal(command: string, helpLink?: string): Promise { + const rpcArgs: Record = { builder: this._handle, command }; + if (helpLink !== undefined) rpcArgs.helpLink = helpLink; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withRequiredCommand', + rpcArgs + ); + return new DotnetToolResource(result, this._client); + } + + /** Adds a required command dependency */ + withRequiredCommand(command: string, options?: WithRequiredCommandOptions): DotnetToolResourcePromise { + const helpLink = options?.helpLink; + return new DotnetToolResourcePromise(this._withRequiredCommandInternal(command, helpLink)); + } + + /** @internal */ + private async _withEnvironmentInternal(name: string, value: string): Promise { + const rpcArgs: Record = { builder: this._handle, name, value }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withEnvironment', + rpcArgs + ); + return new DotnetToolResource(result, this._client); + } + + /** Sets an environment variable */ + withEnvironment(name: string, value: string): DotnetToolResourcePromise { + return new DotnetToolResourcePromise(this._withEnvironmentInternal(name, value)); + } + + /** @internal */ + private async _withEnvironmentExpressionInternal(name: string, value: ReferenceExpression): Promise { + const rpcArgs: Record = { builder: this._handle, name, value }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withEnvironmentExpression', + rpcArgs + ); + return new DotnetToolResource(result, this._client); + } + + /** Adds an environment variable with a reference expression */ + withEnvironmentExpression(name: string, value: ReferenceExpression): DotnetToolResourcePromise { + return new DotnetToolResourcePromise(this._withEnvironmentExpressionInternal(name, value)); + } + + /** @internal */ + private async _withEnvironmentCallbackInternal(callback: (obj: EnvironmentCallbackContext) => Promise): Promise { + const callbackId = registerCallback(async (objData: unknown) => { + const objHandle = wrapIfHandle(objData) as EnvironmentCallbackContextHandle; + const obj = new EnvironmentCallbackContext(objHandle, this._client); + await callback(obj); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withEnvironmentCallback', + rpcArgs + ); + return new DotnetToolResource(result, this._client); + } + + /** Sets environment variables via callback */ + withEnvironmentCallback(callback: (obj: EnvironmentCallbackContext) => Promise): DotnetToolResourcePromise { + return new DotnetToolResourcePromise(this._withEnvironmentCallbackInternal(callback)); + } + + /** @internal */ + private async _withEnvironmentCallbackAsyncInternal(callback: (arg: EnvironmentCallbackContext) => Promise): Promise { + const callbackId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as EnvironmentCallbackContextHandle; + const arg = new EnvironmentCallbackContext(argHandle, this._client); + await callback(arg); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withEnvironmentCallbackAsync', + rpcArgs + ); + return new DotnetToolResource(result, this._client); + } + + /** Sets environment variables via async callback */ + withEnvironmentCallbackAsync(callback: (arg: EnvironmentCallbackContext) => Promise): DotnetToolResourcePromise { + return new DotnetToolResourcePromise(this._withEnvironmentCallbackAsyncInternal(callback)); + } + + /** @internal */ + private async _withEnvironmentEndpointInternal(name: string, endpointReference: EndpointReference): Promise { + const rpcArgs: Record = { builder: this._handle, name, endpointReference }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withEnvironmentEndpoint', + rpcArgs + ); + return new DotnetToolResource(result, this._client); + } + + /** Sets an environment variable from an endpoint reference */ + withEnvironmentEndpoint(name: string, endpointReference: EndpointReference): DotnetToolResourcePromise { + return new DotnetToolResourcePromise(this._withEnvironmentEndpointInternal(name, endpointReference)); + } + + /** @internal */ + private async _withEnvironmentParameterInternal(name: string, parameter: ParameterResource): Promise { + const rpcArgs: Record = { builder: this._handle, name, parameter }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withEnvironmentParameter', + rpcArgs + ); + return new DotnetToolResource(result, this._client); + } + + /** Sets an environment variable from a parameter resource */ + withEnvironmentParameter(name: string, parameter: ParameterResource): DotnetToolResourcePromise { + return new DotnetToolResourcePromise(this._withEnvironmentParameterInternal(name, parameter)); + } + + /** @internal */ + private async _withEnvironmentConnectionStringInternal(envVarName: string, resource: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, envVarName, resource }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withEnvironmentConnectionString', + rpcArgs + ); + return new DotnetToolResource(result, this._client); + } + + /** Sets an environment variable from a connection string resource */ + withEnvironmentConnectionString(envVarName: string, resource: ResourceBuilderBase): DotnetToolResourcePromise { + return new DotnetToolResourcePromise(this._withEnvironmentConnectionStringInternal(envVarName, resource)); + } + + /** @internal */ + private async _withArgsInternal(args: string[]): Promise { + const rpcArgs: Record = { builder: this._handle, args }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withArgs', + rpcArgs + ); + return new DotnetToolResource(result, this._client); + } + + /** Adds arguments */ + withArgs(args: string[]): DotnetToolResourcePromise { + return new DotnetToolResourcePromise(this._withArgsInternal(args)); + } + + /** @internal */ + private async _withArgsCallbackInternal(callback: (obj: CommandLineArgsCallbackContext) => Promise): Promise { + const callbackId = registerCallback(async (objData: unknown) => { + const objHandle = wrapIfHandle(objData) as CommandLineArgsCallbackContextHandle; + const obj = new CommandLineArgsCallbackContext(objHandle, this._client); + await callback(obj); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withArgsCallback', + rpcArgs + ); + return new DotnetToolResource(result, this._client); + } + + /** Sets command-line arguments via callback */ + withArgsCallback(callback: (obj: CommandLineArgsCallbackContext) => Promise): DotnetToolResourcePromise { + return new DotnetToolResourcePromise(this._withArgsCallbackInternal(callback)); + } + + /** @internal */ + private async _withArgsCallbackAsyncInternal(callback: (arg: CommandLineArgsCallbackContext) => Promise): Promise { + const callbackId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as CommandLineArgsCallbackContextHandle; + const arg = new CommandLineArgsCallbackContext(argHandle, this._client); + await callback(arg); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withArgsCallbackAsync', + rpcArgs + ); + return new DotnetToolResource(result, this._client); + } + + /** Sets command-line arguments via async callback */ + withArgsCallbackAsync(callback: (arg: CommandLineArgsCallbackContext) => Promise): DotnetToolResourcePromise { + return new DotnetToolResourcePromise(this._withArgsCallbackAsyncInternal(callback)); + } + + /** @internal */ + private async _withReferenceInternal(source: ResourceBuilderBase, connectionName?: string, optional?: boolean): Promise { + const rpcArgs: Record = { builder: this._handle, source }; + if (connectionName !== undefined) rpcArgs.connectionName = connectionName; + if (optional !== undefined) rpcArgs.optional = optional; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withReference', + rpcArgs + ); + return new DotnetToolResource(result, this._client); + } + + /** Adds a reference to another resource */ + withReference(source: ResourceBuilderBase, options?: WithReferenceOptions): DotnetToolResourcePromise { + const connectionName = options?.connectionName; + const optional = options?.optional; + return new DotnetToolResourcePromise(this._withReferenceInternal(source, connectionName, optional)); + } + + /** @internal */ + private async _withServiceReferenceInternal(source: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, source }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withServiceReference', + rpcArgs + ); + return new DotnetToolResource(result, this._client); + } + + /** Adds a service discovery reference to another resource */ + withServiceReference(source: ResourceBuilderBase): DotnetToolResourcePromise { + return new DotnetToolResourcePromise(this._withServiceReferenceInternal(source)); + } + + /** @internal */ + private async _withServiceReferenceNamedInternal(source: ResourceBuilderBase, name: string): Promise { + const rpcArgs: Record = { builder: this._handle, source, name }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withServiceReferenceNamed', + rpcArgs + ); + return new DotnetToolResource(result, this._client); + } + + /** Adds a named service discovery reference */ + withServiceReferenceNamed(source: ResourceBuilderBase, name: string): DotnetToolResourcePromise { + return new DotnetToolResourcePromise(this._withServiceReferenceNamedInternal(source, name)); + } + + /** @internal */ + private async _withReferenceUriInternal(name: string, uri: string): Promise { + const rpcArgs: Record = { builder: this._handle, name, uri }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withReferenceUri', + rpcArgs + ); + return new DotnetToolResource(result, this._client); + } + + /** Adds a reference to a URI */ + withReferenceUri(name: string, uri: string): DotnetToolResourcePromise { + return new DotnetToolResourcePromise(this._withReferenceUriInternal(name, uri)); + } + + /** @internal */ + private async _withReferenceExternalServiceInternal(externalService: ExternalServiceResource): Promise { + const rpcArgs: Record = { builder: this._handle, externalService }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withReferenceExternalService', + rpcArgs + ); + return new DotnetToolResource(result, this._client); + } + + /** Adds a reference to an external service */ + withReferenceExternalService(externalService: ExternalServiceResource): DotnetToolResourcePromise { + return new DotnetToolResourcePromise(this._withReferenceExternalServiceInternal(externalService)); + } + + /** @internal */ + private async _withReferenceEndpointInternal(endpointReference: EndpointReference): Promise { + const rpcArgs: Record = { builder: this._handle, endpointReference }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withReferenceEndpoint', + rpcArgs + ); + return new DotnetToolResource(result, this._client); + } + + /** Adds a reference to an endpoint */ + withReferenceEndpoint(endpointReference: EndpointReference): DotnetToolResourcePromise { + return new DotnetToolResourcePromise(this._withReferenceEndpointInternal(endpointReference)); + } + + /** @internal */ + private async _withEndpointInternal(port?: number, targetPort?: number, scheme?: string, name?: string, env?: string, isProxied?: boolean, isExternal?: boolean, protocol?: ProtocolType): Promise { + const rpcArgs: Record = { builder: this._handle }; + if (port !== undefined) rpcArgs.port = port; + if (targetPort !== undefined) rpcArgs.targetPort = targetPort; + if (scheme !== undefined) rpcArgs.scheme = scheme; + if (name !== undefined) rpcArgs.name = name; + if (env !== undefined) rpcArgs.env = env; + if (isProxied !== undefined) rpcArgs.isProxied = isProxied; + if (isExternal !== undefined) rpcArgs.isExternal = isExternal; + if (protocol !== undefined) rpcArgs.protocol = protocol; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withEndpoint', + rpcArgs + ); + return new DotnetToolResource(result, this._client); + } + + /** Adds a network endpoint */ + withEndpoint(options?: WithEndpointOptions): DotnetToolResourcePromise { + const port = options?.port; + const targetPort = options?.targetPort; + const scheme = options?.scheme; + const name = options?.name; + const env = options?.env; + const isProxied = options?.isProxied; + const isExternal = options?.isExternal; + const protocol = options?.protocol; + return new DotnetToolResourcePromise(this._withEndpointInternal(port, targetPort, scheme, name, env, isProxied, isExternal, protocol)); + } + + /** @internal */ + private async _withHttpEndpointInternal(port?: number, targetPort?: number, name?: string, env?: string, isProxied?: boolean): Promise { + const rpcArgs: Record = { builder: this._handle }; + if (port !== undefined) rpcArgs.port = port; + if (targetPort !== undefined) rpcArgs.targetPort = targetPort; + if (name !== undefined) rpcArgs.name = name; + if (env !== undefined) rpcArgs.env = env; + if (isProxied !== undefined) rpcArgs.isProxied = isProxied; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withHttpEndpoint', + rpcArgs + ); + return new DotnetToolResource(result, this._client); + } + + /** Adds an HTTP endpoint */ + withHttpEndpoint(options?: WithHttpEndpointOptions): DotnetToolResourcePromise { + const port = options?.port; + const targetPort = options?.targetPort; + const name = options?.name; + const env = options?.env; + const isProxied = options?.isProxied; + return new DotnetToolResourcePromise(this._withHttpEndpointInternal(port, targetPort, name, env, isProxied)); + } + + /** @internal */ + private async _withHttpsEndpointInternal(port?: number, targetPort?: number, name?: string, env?: string, isProxied?: boolean): Promise { + const rpcArgs: Record = { builder: this._handle }; + if (port !== undefined) rpcArgs.port = port; + if (targetPort !== undefined) rpcArgs.targetPort = targetPort; + if (name !== undefined) rpcArgs.name = name; + if (env !== undefined) rpcArgs.env = env; + if (isProxied !== undefined) rpcArgs.isProxied = isProxied; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withHttpsEndpoint', + rpcArgs + ); + return new DotnetToolResource(result, this._client); + } + + /** Adds an HTTPS endpoint */ + withHttpsEndpoint(options?: WithHttpsEndpointOptions): DotnetToolResourcePromise { + const port = options?.port; + const targetPort = options?.targetPort; + const name = options?.name; + const env = options?.env; + const isProxied = options?.isProxied; + return new DotnetToolResourcePromise(this._withHttpsEndpointInternal(port, targetPort, name, env, isProxied)); + } + + /** @internal */ + private async _withExternalHttpEndpointsInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withExternalHttpEndpoints', + rpcArgs + ); + return new DotnetToolResource(result, this._client); + } + + /** Makes HTTP endpoints externally accessible */ + withExternalHttpEndpoints(): DotnetToolResourcePromise { + return new DotnetToolResourcePromise(this._withExternalHttpEndpointsInternal()); + } + + /** Gets an endpoint reference */ + async getEndpoint(name: string): Promise { + const rpcArgs: Record = { builder: this._handle, name }; + return await this._client.invokeCapability( + 'Aspire.Hosting/getEndpoint', + rpcArgs + ); + } + + /** @internal */ + private async _asHttp2ServiceInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/asHttp2Service', + rpcArgs + ); + return new DotnetToolResource(result, this._client); + } + + /** Configures resource for HTTP/2 */ + asHttp2Service(): DotnetToolResourcePromise { + return new DotnetToolResourcePromise(this._asHttp2ServiceInternal()); + } + + /** @internal */ + private async _withUrlsCallbackInternal(callback: (obj: ResourceUrlsCallbackContext) => Promise): Promise { + const callbackId = registerCallback(async (objData: unknown) => { + const objHandle = wrapIfHandle(objData) as ResourceUrlsCallbackContextHandle; + const obj = new ResourceUrlsCallbackContext(objHandle, this._client); + await callback(obj); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrlsCallback', + rpcArgs + ); + return new DotnetToolResource(result, this._client); + } + + /** Customizes displayed URLs via callback */ + withUrlsCallback(callback: (obj: ResourceUrlsCallbackContext) => Promise): DotnetToolResourcePromise { + return new DotnetToolResourcePromise(this._withUrlsCallbackInternal(callback)); + } + + /** @internal */ + private async _withUrlsCallbackAsyncInternal(callback: (arg: ResourceUrlsCallbackContext) => Promise): Promise { + const callbackId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as ResourceUrlsCallbackContextHandle; + const arg = new ResourceUrlsCallbackContext(argHandle, this._client); + await callback(arg); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrlsCallbackAsync', + rpcArgs + ); + return new DotnetToolResource(result, this._client); + } + + /** Customizes displayed URLs via async callback */ + withUrlsCallbackAsync(callback: (arg: ResourceUrlsCallbackContext) => Promise): DotnetToolResourcePromise { + return new DotnetToolResourcePromise(this._withUrlsCallbackAsyncInternal(callback)); + } + + /** @internal */ + private async _withUrlInternal(url: string, displayText?: string): Promise { + const rpcArgs: Record = { builder: this._handle, url }; + if (displayText !== undefined) rpcArgs.displayText = displayText; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrl', + rpcArgs + ); + return new DotnetToolResource(result, this._client); + } + + /** Adds or modifies displayed URLs */ + withUrl(url: string, options?: WithUrlOptions): DotnetToolResourcePromise { + const displayText = options?.displayText; + return new DotnetToolResourcePromise(this._withUrlInternal(url, displayText)); + } + + /** @internal */ + private async _withUrlExpressionInternal(url: ReferenceExpression, displayText?: string): Promise { + const rpcArgs: Record = { builder: this._handle, url }; + if (displayText !== undefined) rpcArgs.displayText = displayText; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrlExpression', + rpcArgs + ); + return new DotnetToolResource(result, this._client); + } + + /** Adds a URL using a reference expression */ + withUrlExpression(url: ReferenceExpression, options?: WithUrlExpressionOptions): DotnetToolResourcePromise { + const displayText = options?.displayText; + return new DotnetToolResourcePromise(this._withUrlExpressionInternal(url, displayText)); + } + + /** @internal */ + private async _withUrlForEndpointInternal(endpointName: string, callback: (obj: ResourceUrlAnnotation) => Promise): Promise { + const callbackId = registerCallback(async (objData: unknown) => { + const obj = wrapIfHandle(objData) as ResourceUrlAnnotation; + await callback(obj); + }); + const rpcArgs: Record = { builder: this._handle, endpointName, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrlForEndpoint', + rpcArgs + ); + return new DotnetToolResource(result, this._client); + } + + /** Customizes the URL for a specific endpoint via callback */ + withUrlForEndpoint(endpointName: string, callback: (obj: ResourceUrlAnnotation) => Promise): DotnetToolResourcePromise { + return new DotnetToolResourcePromise(this._withUrlForEndpointInternal(endpointName, callback)); + } + + /** @internal */ + private async _withUrlForEndpointFactoryInternal(endpointName: string, callback: (arg: EndpointReference) => Promise): Promise { + const callbackId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as EndpointReferenceHandle; + const arg = new EndpointReference(argHandle, this._client); + return await callback(arg); + }); + const rpcArgs: Record = { builder: this._handle, endpointName, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrlForEndpointFactory', + rpcArgs + ); + return new DotnetToolResource(result, this._client); + } + + /** Adds a URL for a specific endpoint via factory callback */ + withUrlForEndpointFactory(endpointName: string, callback: (arg: EndpointReference) => Promise): DotnetToolResourcePromise { + return new DotnetToolResourcePromise(this._withUrlForEndpointFactoryInternal(endpointName, callback)); + } + + /** @internal */ + private async _excludeFromManifestInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/excludeFromManifest', + rpcArgs + ); + return new DotnetToolResource(result, this._client); + } + + /** Excludes the resource from the deployment manifest */ + excludeFromManifest(): DotnetToolResourcePromise { + return new DotnetToolResourcePromise(this._excludeFromManifestInternal()); + } + + /** @internal */ + private async _waitForInternal(dependency: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, dependency }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/waitFor', + rpcArgs + ); + return new DotnetToolResource(result, this._client); + } + + /** Waits for another resource to be ready */ + waitFor(dependency: ResourceBuilderBase): DotnetToolResourcePromise { + return new DotnetToolResourcePromise(this._waitForInternal(dependency)); + } + + /** @internal */ + private async _waitForWithBehaviorInternal(dependency: ResourceBuilderBase, waitBehavior: WaitBehavior): Promise { + const rpcArgs: Record = { builder: this._handle, dependency, waitBehavior }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/waitForWithBehavior', + rpcArgs + ); + return new DotnetToolResource(result, this._client); + } + + /** Waits for another resource with specific behavior */ + waitForWithBehavior(dependency: ResourceBuilderBase, waitBehavior: WaitBehavior): DotnetToolResourcePromise { + return new DotnetToolResourcePromise(this._waitForWithBehaviorInternal(dependency, waitBehavior)); + } + + /** @internal */ + private async _waitForStartInternal(dependency: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, dependency }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/waitForStart', + rpcArgs + ); + return new DotnetToolResource(result, this._client); + } + + /** Waits for another resource to start */ + waitForStart(dependency: ResourceBuilderBase): DotnetToolResourcePromise { + return new DotnetToolResourcePromise(this._waitForStartInternal(dependency)); + } + + /** @internal */ + private async _waitForStartWithBehaviorInternal(dependency: ResourceBuilderBase, waitBehavior: WaitBehavior): Promise { + const rpcArgs: Record = { builder: this._handle, dependency, waitBehavior }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/waitForStartWithBehavior', + rpcArgs + ); + return new DotnetToolResource(result, this._client); + } + + /** Waits for another resource to start with specific behavior */ + waitForStartWithBehavior(dependency: ResourceBuilderBase, waitBehavior: WaitBehavior): DotnetToolResourcePromise { + return new DotnetToolResourcePromise(this._waitForStartWithBehaviorInternal(dependency, waitBehavior)); + } + + /** @internal */ + private async _withExplicitStartInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withExplicitStart', + rpcArgs + ); + return new DotnetToolResource(result, this._client); + } + + /** Prevents resource from starting automatically */ + withExplicitStart(): DotnetToolResourcePromise { + return new DotnetToolResourcePromise(this._withExplicitStartInternal()); + } + + /** @internal */ + private async _waitForCompletionInternal(dependency: ResourceBuilderBase, exitCode?: number): Promise { + const rpcArgs: Record = { builder: this._handle, dependency }; + if (exitCode !== undefined) rpcArgs.exitCode = exitCode; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/waitForCompletion', + rpcArgs + ); + return new DotnetToolResource(result, this._client); + } + + /** Waits for resource completion */ + waitForCompletion(dependency: ResourceBuilderBase, options?: WaitForCompletionOptions): DotnetToolResourcePromise { + const exitCode = options?.exitCode; + return new DotnetToolResourcePromise(this._waitForCompletionInternal(dependency, exitCode)); + } + + /** @internal */ + private async _withHealthCheckInternal(key: string): Promise { + const rpcArgs: Record = { builder: this._handle, key }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withHealthCheck', + rpcArgs + ); + return new DotnetToolResource(result, this._client); + } + + /** Adds a health check by key */ + withHealthCheck(key: string): DotnetToolResourcePromise { + return new DotnetToolResourcePromise(this._withHealthCheckInternal(key)); + } + + /** @internal */ + private async _withHttpHealthCheckInternal(path?: string, statusCode?: number, endpointName?: string): Promise { + const rpcArgs: Record = { builder: this._handle }; + if (path !== undefined) rpcArgs.path = path; + if (statusCode !== undefined) rpcArgs.statusCode = statusCode; + if (endpointName !== undefined) rpcArgs.endpointName = endpointName; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withHttpHealthCheck', + rpcArgs + ); + return new DotnetToolResource(result, this._client); + } + + /** Adds an HTTP health check */ + withHttpHealthCheck(options?: WithHttpHealthCheckOptions): DotnetToolResourcePromise { + const path = options?.path; + const statusCode = options?.statusCode; + const endpointName = options?.endpointName; + return new DotnetToolResourcePromise(this._withHttpHealthCheckInternal(path, statusCode, endpointName)); + } + + /** @internal */ + private async _withCommandInternal(name: string, displayName: string, executeCommand: (arg: ExecuteCommandContext) => Promise, commandOptions?: CommandOptions): Promise { + const executeCommandId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as ExecuteCommandContextHandle; + const arg = new ExecuteCommandContext(argHandle, this._client); + return await executeCommand(arg); + }); + const rpcArgs: Record = { builder: this._handle, name, displayName, executeCommand: executeCommandId }; + if (commandOptions !== undefined) rpcArgs.commandOptions = commandOptions; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withCommand', + rpcArgs + ); + return new DotnetToolResource(result, this._client); + } + + /** Adds a resource command */ + withCommand(name: string, displayName: string, executeCommand: (arg: ExecuteCommandContext) => Promise, options?: WithCommandOptions): DotnetToolResourcePromise { + const commandOptions = options?.commandOptions; + return new DotnetToolResourcePromise(this._withCommandInternal(name, displayName, executeCommand, commandOptions)); + } + + /** @internal */ + private async _withDeveloperCertificateTrustInternal(trust: boolean): Promise { + const rpcArgs: Record = { builder: this._handle, trust }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withDeveloperCertificateTrust', + rpcArgs + ); + return new DotnetToolResource(result, this._client); + } + + /** Configures developer certificate trust */ + withDeveloperCertificateTrust(trust: boolean): DotnetToolResourcePromise { + return new DotnetToolResourcePromise(this._withDeveloperCertificateTrustInternal(trust)); + } + + /** @internal */ + private async _withCertificateTrustScopeInternal(scope: CertificateTrustScope): Promise { + const rpcArgs: Record = { builder: this._handle, scope }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withCertificateTrustScope', + rpcArgs + ); + return new DotnetToolResource(result, this._client); + } + + /** Sets the certificate trust scope */ + withCertificateTrustScope(scope: CertificateTrustScope): DotnetToolResourcePromise { + return new DotnetToolResourcePromise(this._withCertificateTrustScopeInternal(scope)); + } + + /** @internal */ + private async _withHttpsDeveloperCertificateInternal(password?: ParameterResource): Promise { + const rpcArgs: Record = { builder: this._handle }; + if (password !== undefined) rpcArgs.password = password; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withHttpsDeveloperCertificate', + rpcArgs + ); + return new DotnetToolResource(result, this._client); + } + + /** Configures HTTPS with a developer certificate */ + withHttpsDeveloperCertificate(options?: WithHttpsDeveloperCertificateOptions): DotnetToolResourcePromise { + const password = options?.password; + return new DotnetToolResourcePromise(this._withHttpsDeveloperCertificateInternal(password)); + } + + /** @internal */ + private async _withoutHttpsCertificateInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withoutHttpsCertificate', + rpcArgs + ); + return new DotnetToolResource(result, this._client); + } + + /** Removes HTTPS certificate configuration */ + withoutHttpsCertificate(): DotnetToolResourcePromise { + return new DotnetToolResourcePromise(this._withoutHttpsCertificateInternal()); + } + + /** @internal */ + private async _withParentRelationshipInternal(parent: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, parent }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withParentRelationship', + rpcArgs + ); + return new DotnetToolResource(result, this._client); + } + + /** Sets the parent relationship */ + withParentRelationship(parent: ResourceBuilderBase): DotnetToolResourcePromise { + return new DotnetToolResourcePromise(this._withParentRelationshipInternal(parent)); + } + + /** @internal */ + private async _withChildRelationshipInternal(child: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, child }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withChildRelationship', + rpcArgs + ); + return new DotnetToolResource(result, this._client); + } + + /** Sets a child relationship */ + withChildRelationship(child: ResourceBuilderBase): DotnetToolResourcePromise { + return new DotnetToolResourcePromise(this._withChildRelationshipInternal(child)); + } + + /** @internal */ + private async _withIconNameInternal(iconName: string, iconVariant?: IconVariant): Promise { + const rpcArgs: Record = { builder: this._handle, iconName }; + if (iconVariant !== undefined) rpcArgs.iconVariant = iconVariant; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withIconName', + rpcArgs + ); + return new DotnetToolResource(result, this._client); + } + + /** Sets the icon for the resource */ + withIconName(iconName: string, options?: WithIconNameOptions): DotnetToolResourcePromise { + const iconVariant = options?.iconVariant; + return new DotnetToolResourcePromise(this._withIconNameInternal(iconName, iconVariant)); + } + + /** @internal */ + private async _withHttpProbeInternal(probeType: ProbeType, path?: string, initialDelaySeconds?: number, periodSeconds?: number, timeoutSeconds?: number, failureThreshold?: number, successThreshold?: number, endpointName?: string): Promise { + const rpcArgs: Record = { builder: this._handle, probeType }; + if (path !== undefined) rpcArgs.path = path; + if (initialDelaySeconds !== undefined) rpcArgs.initialDelaySeconds = initialDelaySeconds; + if (periodSeconds !== undefined) rpcArgs.periodSeconds = periodSeconds; + if (timeoutSeconds !== undefined) rpcArgs.timeoutSeconds = timeoutSeconds; + if (failureThreshold !== undefined) rpcArgs.failureThreshold = failureThreshold; + if (successThreshold !== undefined) rpcArgs.successThreshold = successThreshold; + if (endpointName !== undefined) rpcArgs.endpointName = endpointName; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withHttpProbe', + rpcArgs + ); + return new DotnetToolResource(result, this._client); + } + + /** Adds an HTTP health probe to the resource */ + withHttpProbe(probeType: ProbeType, options?: WithHttpProbeOptions): DotnetToolResourcePromise { + const path = options?.path; + const initialDelaySeconds = options?.initialDelaySeconds; + const periodSeconds = options?.periodSeconds; + const timeoutSeconds = options?.timeoutSeconds; + const failureThreshold = options?.failureThreshold; + const successThreshold = options?.successThreshold; + const endpointName = options?.endpointName; + return new DotnetToolResourcePromise(this._withHttpProbeInternal(probeType, path, initialDelaySeconds, periodSeconds, timeoutSeconds, failureThreshold, successThreshold, endpointName)); + } + + /** @internal */ + private async _excludeFromMcpInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/excludeFromMcp', + rpcArgs + ); + return new DotnetToolResource(result, this._client); + } + + /** Excludes the resource from MCP server exposure */ + excludeFromMcp(): DotnetToolResourcePromise { + return new DotnetToolResourcePromise(this._excludeFromMcpInternal()); + } + + /** @internal */ + private async _withRemoteImageNameInternal(remoteImageName: string): Promise { + const rpcArgs: Record = { builder: this._handle, remoteImageName }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withRemoteImageName', + rpcArgs + ); + return new DotnetToolResource(result, this._client); + } + + /** Sets the remote image name for publishing */ + withRemoteImageName(remoteImageName: string): DotnetToolResourcePromise { + return new DotnetToolResourcePromise(this._withRemoteImageNameInternal(remoteImageName)); + } + + /** @internal */ + private async _withRemoteImageTagInternal(remoteImageTag: string): Promise { + const rpcArgs: Record = { builder: this._handle, remoteImageTag }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withRemoteImageTag', + rpcArgs + ); + return new DotnetToolResource(result, this._client); + } + + /** Sets the remote image tag for publishing */ + withRemoteImageTag(remoteImageTag: string): DotnetToolResourcePromise { + return new DotnetToolResourcePromise(this._withRemoteImageTagInternal(remoteImageTag)); + } + + /** @internal */ + private async _withPipelineStepFactoryInternal(stepName: string, callback: (arg: PipelineStepContext) => Promise, dependsOn?: string[], requiredBy?: string[], tags?: string[], description?: string): Promise { + const callbackId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as PipelineStepContextHandle; + const arg = new PipelineStepContext(argHandle, this._client); + await callback(arg); + }); + const rpcArgs: Record = { builder: this._handle, stepName, callback: callbackId }; + if (dependsOn !== undefined) rpcArgs.dependsOn = dependsOn; + if (requiredBy !== undefined) rpcArgs.requiredBy = requiredBy; + if (tags !== undefined) rpcArgs.tags = tags; + if (description !== undefined) rpcArgs.description = description; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withPipelineStepFactory', + rpcArgs + ); + return new DotnetToolResource(result, this._client); + } + + /** Adds a pipeline step to the resource */ + withPipelineStepFactory(stepName: string, callback: (arg: PipelineStepContext) => Promise, options?: WithPipelineStepFactoryOptions): DotnetToolResourcePromise { + const dependsOn = options?.dependsOn; + const requiredBy = options?.requiredBy; + const tags = options?.tags; + const description = options?.description; + return new DotnetToolResourcePromise(this._withPipelineStepFactoryInternal(stepName, callback, dependsOn, requiredBy, tags, description)); + } + + /** @internal */ + private async _withPipelineConfigurationAsyncInternal(callback: (arg: PipelineConfigurationContext) => Promise): Promise { + const callbackId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as PipelineConfigurationContextHandle; + const arg = new PipelineConfigurationContext(argHandle, this._client); + await callback(arg); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withPipelineConfigurationAsync', + rpcArgs + ); + return new DotnetToolResource(result, this._client); + } + + /** Configures pipeline step dependencies via an async callback */ + withPipelineConfigurationAsync(callback: (arg: PipelineConfigurationContext) => Promise): DotnetToolResourcePromise { + return new DotnetToolResourcePromise(this._withPipelineConfigurationAsyncInternal(callback)); + } + + /** @internal */ + private async _withPipelineConfigurationInternal(callback: (obj: PipelineConfigurationContext) => Promise): Promise { + const callbackId = registerCallback(async (objData: unknown) => { + const objHandle = wrapIfHandle(objData) as PipelineConfigurationContextHandle; + const obj = new PipelineConfigurationContext(objHandle, this._client); + await callback(obj); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withPipelineConfiguration', + rpcArgs + ); + return new DotnetToolResource(result, this._client); + } + + /** Configures pipeline step dependencies via a callback */ + withPipelineConfiguration(callback: (obj: PipelineConfigurationContext) => Promise): DotnetToolResourcePromise { + return new DotnetToolResourcePromise(this._withPipelineConfigurationInternal(callback)); + } + + /** Gets the resource name */ + async getResourceName(): Promise { + const rpcArgs: Record = { resource: this._handle }; + return await this._client.invokeCapability( + 'Aspire.Hosting/getResourceName', + rpcArgs + ); + } + + /** @internal */ + private async _withStorageRoleAssignmentsInternal(target: AzureStorageResource, roles: AzureStorageRole[]): Promise { + const rpcArgs: Record = { builder: this._handle, target, roles }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure.Storage/withStorageRoleAssignments', + rpcArgs + ); + return new DotnetToolResource(result, this._client); + } + + /** Assigns Azure Storage roles to a resource */ + withStorageRoleAssignments(target: AzureStorageResource, roles: AzureStorageRole[]): DotnetToolResourcePromise { + return new DotnetToolResourcePromise(this._withStorageRoleAssignmentsInternal(target, roles)); + } + + /** @internal */ + private async _withEventHubsRoleAssignmentsInternal(target: AzureEventHubsResource, roles: AzureEventHubsRole[]): Promise { + const rpcArgs: Record = { builder: this._handle, target, roles }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure.EventHubs/withEventHubsRoleAssignments', + rpcArgs + ); + return new DotnetToolResource(result, this._client); + } + + /** Assigns Event Hubs roles to a resource */ + withEventHubsRoleAssignments(target: AzureEventHubsResource, roles: AzureEventHubsRole[]): DotnetToolResourcePromise { + return new DotnetToolResourcePromise(this._withEventHubsRoleAssignmentsInternal(target, roles)); + } + + /** @internal */ + private async _withEnvironmentFromOutputInternal(name: string, bicepOutputReference: BicepOutputReference): Promise { + const rpcArgs: Record = { builder: this._handle, name, bicepOutputReference }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure/withEnvironmentFromOutput', + rpcArgs + ); + return new DotnetToolResource(result, this._client); + } + + /** Sets an environment variable from a Bicep output reference */ + withEnvironmentFromOutput(name: string, bicepOutputReference: BicepOutputReference): DotnetToolResourcePromise { + return new DotnetToolResourcePromise(this._withEnvironmentFromOutputInternal(name, bicepOutputReference)); + } + + /** @internal */ + private async _withEnvironmentFromKeyVaultSecretInternal(name: string, secretReference: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, name, secretReference }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure/withEnvironmentFromKeyVaultSecret', + rpcArgs + ); + return new DotnetToolResource(result, this._client); + } + + /** Sets an environment variable from an Azure Key Vault secret reference */ + withEnvironmentFromKeyVaultSecret(name: string, secretReference: ResourceBuilderBase): DotnetToolResourcePromise { + return new DotnetToolResourcePromise(this._withEnvironmentFromKeyVaultSecretInternal(name, secretReference)); + } + + /** @internal */ + private async _withAzureUserAssignedIdentityInternal(identityResourceBuilder: AzureUserAssignedIdentityResource): Promise { + const rpcArgs: Record = { builder: this._handle, identityResourceBuilder }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure/withUserAssignedIdentityAzureUserAssignedIdentity', + rpcArgs + ); + return new DotnetToolResource(result, this._client); + } + + /** Associates an Azure user-assigned identity with a compute resource */ + withAzureUserAssignedIdentity(identityResourceBuilder: AzureUserAssignedIdentityResource): DotnetToolResourcePromise { + return new DotnetToolResourcePromise(this._withAzureUserAssignedIdentityInternal(identityResourceBuilder)); + } + +} + +/** + * Thenable wrapper for DotnetToolResource that enables fluent chaining. + * @example + * await builder.addSomething().withX().withY(); + */ +export class DotnetToolResourcePromise implements PromiseLike { + constructor(private _promise: Promise) {} + + then( + onfulfilled?: ((value: DotnetToolResource) => TResult1 | PromiseLike) | null, + onrejected?: ((reason: unknown) => TResult2 | PromiseLike) | null + ): PromiseLike { + return this._promise.then(onfulfilled, onrejected); + } + + /** Configures a resource to use a container registry */ + withContainerRegistry(registry: ResourceBuilderBase): DotnetToolResourcePromise { + return new DotnetToolResourcePromise(this._promise.then(obj => obj.withContainerRegistry(registry))); + } + + /** Sets the base image for a Dockerfile build */ + withDockerfileBaseImage(options?: WithDockerfileBaseImageOptions): DotnetToolResourcePromise { + return new DotnetToolResourcePromise(this._promise.then(obj => obj.withDockerfileBaseImage(options))); + } + + /** Sets the tool package ID */ + withToolPackage(packageId: string): DotnetToolResourcePromise { + return new DotnetToolResourcePromise(this._promise.then(obj => obj.withToolPackage(packageId))); + } + + /** Sets the tool version */ + withToolVersion(version: string): DotnetToolResourcePromise { + return new DotnetToolResourcePromise(this._promise.then(obj => obj.withToolVersion(version))); + } + + /** Allows prerelease tool versions */ + withToolPrerelease(): DotnetToolResourcePromise { + return new DotnetToolResourcePromise(this._promise.then(obj => obj.withToolPrerelease())); + } + + /** Adds a NuGet source for the tool */ + withToolSource(source: string): DotnetToolResourcePromise { + return new DotnetToolResourcePromise(this._promise.then(obj => obj.withToolSource(source))); + } + + /** Ignores existing NuGet feeds */ + withToolIgnoreExistingFeeds(): DotnetToolResourcePromise { + return new DotnetToolResourcePromise(this._promise.then(obj => obj.withToolIgnoreExistingFeeds())); + } + + /** Ignores failed NuGet sources */ + withToolIgnoreFailedSources(): DotnetToolResourcePromise { + return new DotnetToolResourcePromise(this._promise.then(obj => obj.withToolIgnoreFailedSources())); + } + + /** Publishes the executable as a Docker container */ + publishAsDockerFile(): DotnetToolResourcePromise { + return new DotnetToolResourcePromise(this._promise.then(obj => obj.publishAsDockerFile())); + } + + /** Publishes an executable as a Docker file with optional container configuration */ + publishAsDockerFileWithConfigure(configure: (obj: ContainerResource) => Promise): DotnetToolResourcePromise { + return new DotnetToolResourcePromise(this._promise.then(obj => obj.publishAsDockerFileWithConfigure(configure))); + } + + /** Sets the executable command */ + withExecutableCommand(command: string): DotnetToolResourcePromise { + return new DotnetToolResourcePromise(this._promise.then(obj => obj.withExecutableCommand(command))); + } + + /** Sets the executable working directory */ + withWorkingDirectory(workingDirectory: string): DotnetToolResourcePromise { + return new DotnetToolResourcePromise(this._promise.then(obj => obj.withWorkingDirectory(workingDirectory))); + } + + /** Configures an MCP server endpoint on the resource */ + withMcpServer(options?: WithMcpServerOptions): DotnetToolResourcePromise { + return new DotnetToolResourcePromise(this._promise.then(obj => obj.withMcpServer(options))); + } + + /** Configures OTLP telemetry export */ + withOtlpExporter(): DotnetToolResourcePromise { + return new DotnetToolResourcePromise(this._promise.then(obj => obj.withOtlpExporter())); + } + + /** Configures OTLP telemetry export with specific protocol */ + withOtlpExporterProtocol(protocol: OtlpProtocol): DotnetToolResourcePromise { + return new DotnetToolResourcePromise(this._promise.then(obj => obj.withOtlpExporterProtocol(protocol))); + } + + /** Adds a required command dependency */ + withRequiredCommand(command: string, options?: WithRequiredCommandOptions): DotnetToolResourcePromise { + return new DotnetToolResourcePromise(this._promise.then(obj => obj.withRequiredCommand(command, options))); + } + + /** Sets an environment variable */ + withEnvironment(name: string, value: string): DotnetToolResourcePromise { + return new DotnetToolResourcePromise(this._promise.then(obj => obj.withEnvironment(name, value))); + } + + /** Adds an environment variable with a reference expression */ + withEnvironmentExpression(name: string, value: ReferenceExpression): DotnetToolResourcePromise { + return new DotnetToolResourcePromise(this._promise.then(obj => obj.withEnvironmentExpression(name, value))); + } + + /** Sets environment variables via callback */ + withEnvironmentCallback(callback: (obj: EnvironmentCallbackContext) => Promise): DotnetToolResourcePromise { + return new DotnetToolResourcePromise(this._promise.then(obj => obj.withEnvironmentCallback(callback))); + } + + /** Sets environment variables via async callback */ + withEnvironmentCallbackAsync(callback: (arg: EnvironmentCallbackContext) => Promise): DotnetToolResourcePromise { + return new DotnetToolResourcePromise(this._promise.then(obj => obj.withEnvironmentCallbackAsync(callback))); + } + + /** Sets an environment variable from an endpoint reference */ + withEnvironmentEndpoint(name: string, endpointReference: EndpointReference): DotnetToolResourcePromise { + return new DotnetToolResourcePromise(this._promise.then(obj => obj.withEnvironmentEndpoint(name, endpointReference))); + } + + /** Sets an environment variable from a parameter resource */ + withEnvironmentParameter(name: string, parameter: ParameterResource): DotnetToolResourcePromise { + return new DotnetToolResourcePromise(this._promise.then(obj => obj.withEnvironmentParameter(name, parameter))); + } + + /** Sets an environment variable from a connection string resource */ + withEnvironmentConnectionString(envVarName: string, resource: ResourceBuilderBase): DotnetToolResourcePromise { + return new DotnetToolResourcePromise(this._promise.then(obj => obj.withEnvironmentConnectionString(envVarName, resource))); + } + + /** Adds arguments */ + withArgs(args: string[]): DotnetToolResourcePromise { + return new DotnetToolResourcePromise(this._promise.then(obj => obj.withArgs(args))); + } + + /** Sets command-line arguments via callback */ + withArgsCallback(callback: (obj: CommandLineArgsCallbackContext) => Promise): DotnetToolResourcePromise { + return new DotnetToolResourcePromise(this._promise.then(obj => obj.withArgsCallback(callback))); + } + + /** Sets command-line arguments via async callback */ + withArgsCallbackAsync(callback: (arg: CommandLineArgsCallbackContext) => Promise): DotnetToolResourcePromise { + return new DotnetToolResourcePromise(this._promise.then(obj => obj.withArgsCallbackAsync(callback))); + } + + /** Adds a reference to another resource */ + withReference(source: ResourceBuilderBase, options?: WithReferenceOptions): DotnetToolResourcePromise { + return new DotnetToolResourcePromise(this._promise.then(obj => obj.withReference(source, options))); + } + + /** Adds a service discovery reference to another resource */ + withServiceReference(source: ResourceBuilderBase): DotnetToolResourcePromise { + return new DotnetToolResourcePromise(this._promise.then(obj => obj.withServiceReference(source))); + } + + /** Adds a named service discovery reference */ + withServiceReferenceNamed(source: ResourceBuilderBase, name: string): DotnetToolResourcePromise { + return new DotnetToolResourcePromise(this._promise.then(obj => obj.withServiceReferenceNamed(source, name))); + } + + /** Adds a reference to a URI */ + withReferenceUri(name: string, uri: string): DotnetToolResourcePromise { + return new DotnetToolResourcePromise(this._promise.then(obj => obj.withReferenceUri(name, uri))); + } + + /** Adds a reference to an external service */ + withReferenceExternalService(externalService: ExternalServiceResource): DotnetToolResourcePromise { + return new DotnetToolResourcePromise(this._promise.then(obj => obj.withReferenceExternalService(externalService))); + } + + /** Adds a reference to an endpoint */ + withReferenceEndpoint(endpointReference: EndpointReference): DotnetToolResourcePromise { + return new DotnetToolResourcePromise(this._promise.then(obj => obj.withReferenceEndpoint(endpointReference))); + } + + /** Adds a network endpoint */ + withEndpoint(options?: WithEndpointOptions): DotnetToolResourcePromise { + return new DotnetToolResourcePromise(this._promise.then(obj => obj.withEndpoint(options))); + } + + /** Adds an HTTP endpoint */ + withHttpEndpoint(options?: WithHttpEndpointOptions): DotnetToolResourcePromise { + return new DotnetToolResourcePromise(this._promise.then(obj => obj.withHttpEndpoint(options))); + } + + /** Adds an HTTPS endpoint */ + withHttpsEndpoint(options?: WithHttpsEndpointOptions): DotnetToolResourcePromise { + return new DotnetToolResourcePromise(this._promise.then(obj => obj.withHttpsEndpoint(options))); + } + + /** Makes HTTP endpoints externally accessible */ + withExternalHttpEndpoints(): DotnetToolResourcePromise { + return new DotnetToolResourcePromise(this._promise.then(obj => obj.withExternalHttpEndpoints())); + } + + /** Gets an endpoint reference */ + getEndpoint(name: string): Promise { + return this._promise.then(obj => obj.getEndpoint(name)); + } + + /** Configures resource for HTTP/2 */ + asHttp2Service(): DotnetToolResourcePromise { + return new DotnetToolResourcePromise(this._promise.then(obj => obj.asHttp2Service())); + } + + /** Customizes displayed URLs via callback */ + withUrlsCallback(callback: (obj: ResourceUrlsCallbackContext) => Promise): DotnetToolResourcePromise { + return new DotnetToolResourcePromise(this._promise.then(obj => obj.withUrlsCallback(callback))); + } + + /** Customizes displayed URLs via async callback */ + withUrlsCallbackAsync(callback: (arg: ResourceUrlsCallbackContext) => Promise): DotnetToolResourcePromise { + return new DotnetToolResourcePromise(this._promise.then(obj => obj.withUrlsCallbackAsync(callback))); + } + + /** Adds or modifies displayed URLs */ + withUrl(url: string, options?: WithUrlOptions): DotnetToolResourcePromise { + return new DotnetToolResourcePromise(this._promise.then(obj => obj.withUrl(url, options))); + } + + /** Adds a URL using a reference expression */ + withUrlExpression(url: ReferenceExpression, options?: WithUrlExpressionOptions): DotnetToolResourcePromise { + return new DotnetToolResourcePromise(this._promise.then(obj => obj.withUrlExpression(url, options))); + } + + /** Customizes the URL for a specific endpoint via callback */ + withUrlForEndpoint(endpointName: string, callback: (obj: ResourceUrlAnnotation) => Promise): DotnetToolResourcePromise { + return new DotnetToolResourcePromise(this._promise.then(obj => obj.withUrlForEndpoint(endpointName, callback))); + } + + /** Adds a URL for a specific endpoint via factory callback */ + withUrlForEndpointFactory(endpointName: string, callback: (arg: EndpointReference) => Promise): DotnetToolResourcePromise { + return new DotnetToolResourcePromise(this._promise.then(obj => obj.withUrlForEndpointFactory(endpointName, callback))); + } + + /** Excludes the resource from the deployment manifest */ + excludeFromManifest(): DotnetToolResourcePromise { + return new DotnetToolResourcePromise(this._promise.then(obj => obj.excludeFromManifest())); + } + + /** Waits for another resource to be ready */ + waitFor(dependency: ResourceBuilderBase): DotnetToolResourcePromise { + return new DotnetToolResourcePromise(this._promise.then(obj => obj.waitFor(dependency))); + } + + /** Waits for another resource with specific behavior */ + waitForWithBehavior(dependency: ResourceBuilderBase, waitBehavior: WaitBehavior): DotnetToolResourcePromise { + return new DotnetToolResourcePromise(this._promise.then(obj => obj.waitForWithBehavior(dependency, waitBehavior))); + } + + /** Waits for another resource to start */ + waitForStart(dependency: ResourceBuilderBase): DotnetToolResourcePromise { + return new DotnetToolResourcePromise(this._promise.then(obj => obj.waitForStart(dependency))); + } + + /** Waits for another resource to start with specific behavior */ + waitForStartWithBehavior(dependency: ResourceBuilderBase, waitBehavior: WaitBehavior): DotnetToolResourcePromise { + return new DotnetToolResourcePromise(this._promise.then(obj => obj.waitForStartWithBehavior(dependency, waitBehavior))); + } + + /** Prevents resource from starting automatically */ + withExplicitStart(): DotnetToolResourcePromise { + return new DotnetToolResourcePromise(this._promise.then(obj => obj.withExplicitStart())); + } + + /** Waits for resource completion */ + waitForCompletion(dependency: ResourceBuilderBase, options?: WaitForCompletionOptions): DotnetToolResourcePromise { + return new DotnetToolResourcePromise(this._promise.then(obj => obj.waitForCompletion(dependency, options))); + } + + /** Adds a health check by key */ + withHealthCheck(key: string): DotnetToolResourcePromise { + return new DotnetToolResourcePromise(this._promise.then(obj => obj.withHealthCheck(key))); + } + + /** Adds an HTTP health check */ + withHttpHealthCheck(options?: WithHttpHealthCheckOptions): DotnetToolResourcePromise { + return new DotnetToolResourcePromise(this._promise.then(obj => obj.withHttpHealthCheck(options))); + } + + /** Adds a resource command */ + withCommand(name: string, displayName: string, executeCommand: (arg: ExecuteCommandContext) => Promise, options?: WithCommandOptions): DotnetToolResourcePromise { + return new DotnetToolResourcePromise(this._promise.then(obj => obj.withCommand(name, displayName, executeCommand, options))); + } + + /** Configures developer certificate trust */ + withDeveloperCertificateTrust(trust: boolean): DotnetToolResourcePromise { + return new DotnetToolResourcePromise(this._promise.then(obj => obj.withDeveloperCertificateTrust(trust))); + } + + /** Sets the certificate trust scope */ + withCertificateTrustScope(scope: CertificateTrustScope): DotnetToolResourcePromise { + return new DotnetToolResourcePromise(this._promise.then(obj => obj.withCertificateTrustScope(scope))); + } + + /** Configures HTTPS with a developer certificate */ + withHttpsDeveloperCertificate(options?: WithHttpsDeveloperCertificateOptions): DotnetToolResourcePromise { + return new DotnetToolResourcePromise(this._promise.then(obj => obj.withHttpsDeveloperCertificate(options))); + } + + /** Removes HTTPS certificate configuration */ + withoutHttpsCertificate(): DotnetToolResourcePromise { + return new DotnetToolResourcePromise(this._promise.then(obj => obj.withoutHttpsCertificate())); + } + + /** Sets the parent relationship */ + withParentRelationship(parent: ResourceBuilderBase): DotnetToolResourcePromise { + return new DotnetToolResourcePromise(this._promise.then(obj => obj.withParentRelationship(parent))); + } + + /** Sets a child relationship */ + withChildRelationship(child: ResourceBuilderBase): DotnetToolResourcePromise { + return new DotnetToolResourcePromise(this._promise.then(obj => obj.withChildRelationship(child))); + } + + /** Sets the icon for the resource */ + withIconName(iconName: string, options?: WithIconNameOptions): DotnetToolResourcePromise { + return new DotnetToolResourcePromise(this._promise.then(obj => obj.withIconName(iconName, options))); + } + + /** Adds an HTTP health probe to the resource */ + withHttpProbe(probeType: ProbeType, options?: WithHttpProbeOptions): DotnetToolResourcePromise { + return new DotnetToolResourcePromise(this._promise.then(obj => obj.withHttpProbe(probeType, options))); + } + + /** Excludes the resource from MCP server exposure */ + excludeFromMcp(): DotnetToolResourcePromise { + return new DotnetToolResourcePromise(this._promise.then(obj => obj.excludeFromMcp())); + } + + /** Sets the remote image name for publishing */ + withRemoteImageName(remoteImageName: string): DotnetToolResourcePromise { + return new DotnetToolResourcePromise(this._promise.then(obj => obj.withRemoteImageName(remoteImageName))); + } + + /** Sets the remote image tag for publishing */ + withRemoteImageTag(remoteImageTag: string): DotnetToolResourcePromise { + return new DotnetToolResourcePromise(this._promise.then(obj => obj.withRemoteImageTag(remoteImageTag))); + } + + /** Adds a pipeline step to the resource */ + withPipelineStepFactory(stepName: string, callback: (arg: PipelineStepContext) => Promise, options?: WithPipelineStepFactoryOptions): DotnetToolResourcePromise { + return new DotnetToolResourcePromise(this._promise.then(obj => obj.withPipelineStepFactory(stepName, callback, options))); + } + + /** Configures pipeline step dependencies via an async callback */ + withPipelineConfigurationAsync(callback: (arg: PipelineConfigurationContext) => Promise): DotnetToolResourcePromise { + return new DotnetToolResourcePromise(this._promise.then(obj => obj.withPipelineConfigurationAsync(callback))); + } + + /** Configures pipeline step dependencies via a callback */ + withPipelineConfiguration(callback: (obj: PipelineConfigurationContext) => Promise): DotnetToolResourcePromise { + return new DotnetToolResourcePromise(this._promise.then(obj => obj.withPipelineConfiguration(callback))); + } + + /** Gets the resource name */ + getResourceName(): Promise { + return this._promise.then(obj => obj.getResourceName()); + } + + /** Assigns Azure Storage roles to a resource */ + withStorageRoleAssignments(target: AzureStorageResource, roles: AzureStorageRole[]): DotnetToolResourcePromise { + return new DotnetToolResourcePromise(this._promise.then(obj => obj.withStorageRoleAssignments(target, roles))); + } + + /** Assigns Event Hubs roles to a resource */ + withEventHubsRoleAssignments(target: AzureEventHubsResource, roles: AzureEventHubsRole[]): DotnetToolResourcePromise { + return new DotnetToolResourcePromise(this._promise.then(obj => obj.withEventHubsRoleAssignments(target, roles))); + } + + /** Sets an environment variable from a Bicep output reference */ + withEnvironmentFromOutput(name: string, bicepOutputReference: BicepOutputReference): DotnetToolResourcePromise { + return new DotnetToolResourcePromise(this._promise.then(obj => obj.withEnvironmentFromOutput(name, bicepOutputReference))); + } + + /** Sets an environment variable from an Azure Key Vault secret reference */ + withEnvironmentFromKeyVaultSecret(name: string, secretReference: ResourceBuilderBase): DotnetToolResourcePromise { + return new DotnetToolResourcePromise(this._promise.then(obj => obj.withEnvironmentFromKeyVaultSecret(name, secretReference))); + } + + /** Associates an Azure user-assigned identity with a compute resource */ + withAzureUserAssignedIdentity(identityResourceBuilder: AzureUserAssignedIdentityResource): DotnetToolResourcePromise { + return new DotnetToolResourcePromise(this._promise.then(obj => obj.withAzureUserAssignedIdentity(identityResourceBuilder))); + } + +} + +// ============================================================================ +// ExecutableResource +// ============================================================================ + +export class ExecutableResource extends ResourceBuilderBase { + constructor(handle: ExecutableResourceHandle, client: AspireClientRpc) { + super(handle, client); + } + + /** @internal */ + private async _withContainerRegistryInternal(registry: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, registry }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withContainerRegistry', + rpcArgs + ); + return new ExecutableResource(result, this._client); + } + + /** Configures a resource to use a container registry */ + withContainerRegistry(registry: ResourceBuilderBase): ExecutableResourcePromise { + return new ExecutableResourcePromise(this._withContainerRegistryInternal(registry)); + } + + /** @internal */ + private async _withDockerfileBaseImageInternal(buildImage?: string, runtimeImage?: string): Promise { + const rpcArgs: Record = { builder: this._handle }; + if (buildImage !== undefined) rpcArgs.buildImage = buildImage; + if (runtimeImage !== undefined) rpcArgs.runtimeImage = runtimeImage; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withDockerfileBaseImage', + rpcArgs + ); + return new ExecutableResource(result, this._client); + } + + /** Sets the base image for a Dockerfile build */ + withDockerfileBaseImage(options?: WithDockerfileBaseImageOptions): ExecutableResourcePromise { + const buildImage = options?.buildImage; + const runtimeImage = options?.runtimeImage; + return new ExecutableResourcePromise(this._withDockerfileBaseImageInternal(buildImage, runtimeImage)); + } + + /** @internal */ + private async _withMcpServerInternal(path?: string, endpointName?: string): Promise { + const rpcArgs: Record = { builder: this._handle }; + if (path !== undefined) rpcArgs.path = path; + if (endpointName !== undefined) rpcArgs.endpointName = endpointName; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withMcpServer', + rpcArgs + ); + return new ExecutableResource(result, this._client); + } + + /** Configures an MCP server endpoint on the resource */ + withMcpServer(options?: WithMcpServerOptions): ExecutableResourcePromise { + const path = options?.path; + const endpointName = options?.endpointName; + return new ExecutableResourcePromise(this._withMcpServerInternal(path, endpointName)); + } + + /** @internal */ + private async _withOtlpExporterInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withOtlpExporter', + rpcArgs + ); + return new ExecutableResource(result, this._client); + } + + /** Configures OTLP telemetry export */ + withOtlpExporter(): ExecutableResourcePromise { + return new ExecutableResourcePromise(this._withOtlpExporterInternal()); + } + + /** @internal */ + private async _withOtlpExporterProtocolInternal(protocol: OtlpProtocol): Promise { + const rpcArgs: Record = { builder: this._handle, protocol }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withOtlpExporterProtocol', + rpcArgs + ); + return new ExecutableResource(result, this._client); + } + + /** Configures OTLP telemetry export with specific protocol */ + withOtlpExporterProtocol(protocol: OtlpProtocol): ExecutableResourcePromise { + return new ExecutableResourcePromise(this._withOtlpExporterProtocolInternal(protocol)); + } + + /** @internal */ + private async _withRequiredCommandInternal(command: string, helpLink?: string): Promise { + const rpcArgs: Record = { builder: this._handle, command }; + if (helpLink !== undefined) rpcArgs.helpLink = helpLink; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withRequiredCommand', + rpcArgs + ); + return new ExecutableResource(result, this._client); + } + + /** Adds a required command dependency */ + withRequiredCommand(command: string, options?: WithRequiredCommandOptions): ExecutableResourcePromise { + const helpLink = options?.helpLink; + return new ExecutableResourcePromise(this._withRequiredCommandInternal(command, helpLink)); + } + + /** @internal */ + private async _withEnvironmentInternal(name: string, value: string): Promise { + const rpcArgs: Record = { builder: this._handle, name, value }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withEnvironment', + rpcArgs + ); + return new ExecutableResource(result, this._client); + } + + /** Sets an environment variable */ + withEnvironment(name: string, value: string): ExecutableResourcePromise { + return new ExecutableResourcePromise(this._withEnvironmentInternal(name, value)); + } + + /** @internal */ + private async _withEnvironmentExpressionInternal(name: string, value: ReferenceExpression): Promise { + const rpcArgs: Record = { builder: this._handle, name, value }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withEnvironmentExpression', + rpcArgs + ); + return new ExecutableResource(result, this._client); + } + + /** Adds an environment variable with a reference expression */ + withEnvironmentExpression(name: string, value: ReferenceExpression): ExecutableResourcePromise { + return new ExecutableResourcePromise(this._withEnvironmentExpressionInternal(name, value)); + } + + /** @internal */ + private async _withEnvironmentCallbackInternal(callback: (obj: EnvironmentCallbackContext) => Promise): Promise { + const callbackId = registerCallback(async (objData: unknown) => { + const objHandle = wrapIfHandle(objData) as EnvironmentCallbackContextHandle; + const obj = new EnvironmentCallbackContext(objHandle, this._client); + await callback(obj); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withEnvironmentCallback', + rpcArgs + ); + return new ExecutableResource(result, this._client); + } + + /** Sets environment variables via callback */ + withEnvironmentCallback(callback: (obj: EnvironmentCallbackContext) => Promise): ExecutableResourcePromise { + return new ExecutableResourcePromise(this._withEnvironmentCallbackInternal(callback)); + } + + /** @internal */ + private async _withEnvironmentCallbackAsyncInternal(callback: (arg: EnvironmentCallbackContext) => Promise): Promise { + const callbackId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as EnvironmentCallbackContextHandle; + const arg = new EnvironmentCallbackContext(argHandle, this._client); + await callback(arg); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withEnvironmentCallbackAsync', + rpcArgs + ); + return new ExecutableResource(result, this._client); + } + + /** Sets environment variables via async callback */ + withEnvironmentCallbackAsync(callback: (arg: EnvironmentCallbackContext) => Promise): ExecutableResourcePromise { + return new ExecutableResourcePromise(this._withEnvironmentCallbackAsyncInternal(callback)); + } + + /** @internal */ + private async _withEnvironmentEndpointInternal(name: string, endpointReference: EndpointReference): Promise { + const rpcArgs: Record = { builder: this._handle, name, endpointReference }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withEnvironmentEndpoint', + rpcArgs + ); + return new ExecutableResource(result, this._client); + } + + /** Sets an environment variable from an endpoint reference */ + withEnvironmentEndpoint(name: string, endpointReference: EndpointReference): ExecutableResourcePromise { + return new ExecutableResourcePromise(this._withEnvironmentEndpointInternal(name, endpointReference)); + } + + /** @internal */ + private async _withEnvironmentParameterInternal(name: string, parameter: ParameterResource): Promise { + const rpcArgs: Record = { builder: this._handle, name, parameter }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withEnvironmentParameter', + rpcArgs + ); + return new ExecutableResource(result, this._client); + } + + /** Sets an environment variable from a parameter resource */ + withEnvironmentParameter(name: string, parameter: ParameterResource): ExecutableResourcePromise { + return new ExecutableResourcePromise(this._withEnvironmentParameterInternal(name, parameter)); + } + + /** @internal */ + private async _withEnvironmentConnectionStringInternal(envVarName: string, resource: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, envVarName, resource }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withEnvironmentConnectionString', + rpcArgs + ); + return new ExecutableResource(result, this._client); + } + + /** Sets an environment variable from a connection string resource */ + withEnvironmentConnectionString(envVarName: string, resource: ResourceBuilderBase): ExecutableResourcePromise { + return new ExecutableResourcePromise(this._withEnvironmentConnectionStringInternal(envVarName, resource)); + } + + /** @internal */ + private async _withArgsInternal(args: string[]): Promise { + const rpcArgs: Record = { builder: this._handle, args }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withArgs', + rpcArgs + ); + return new ExecutableResource(result, this._client); + } + + /** Adds arguments */ + withArgs(args: string[]): ExecutableResourcePromise { + return new ExecutableResourcePromise(this._withArgsInternal(args)); + } + + /** @internal */ + private async _withArgsCallbackInternal(callback: (obj: CommandLineArgsCallbackContext) => Promise): Promise { + const callbackId = registerCallback(async (objData: unknown) => { + const objHandle = wrapIfHandle(objData) as CommandLineArgsCallbackContextHandle; + const obj = new CommandLineArgsCallbackContext(objHandle, this._client); + await callback(obj); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withArgsCallback', + rpcArgs + ); + return new ExecutableResource(result, this._client); + } + + /** Sets command-line arguments via callback */ + withArgsCallback(callback: (obj: CommandLineArgsCallbackContext) => Promise): ExecutableResourcePromise { + return new ExecutableResourcePromise(this._withArgsCallbackInternal(callback)); + } + + /** @internal */ + private async _withArgsCallbackAsyncInternal(callback: (arg: CommandLineArgsCallbackContext) => Promise): Promise { + const callbackId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as CommandLineArgsCallbackContextHandle; + const arg = new CommandLineArgsCallbackContext(argHandle, this._client); + await callback(arg); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withArgsCallbackAsync', + rpcArgs + ); + return new ExecutableResource(result, this._client); + } + + /** Sets command-line arguments via async callback */ + withArgsCallbackAsync(callback: (arg: CommandLineArgsCallbackContext) => Promise): ExecutableResourcePromise { + return new ExecutableResourcePromise(this._withArgsCallbackAsyncInternal(callback)); + } + + /** @internal */ + private async _withReferenceInternal(source: ResourceBuilderBase, connectionName?: string, optional?: boolean): Promise { + const rpcArgs: Record = { builder: this._handle, source }; + if (connectionName !== undefined) rpcArgs.connectionName = connectionName; + if (optional !== undefined) rpcArgs.optional = optional; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withReference', + rpcArgs + ); + return new ExecutableResource(result, this._client); + } + + /** Adds a reference to another resource */ + withReference(source: ResourceBuilderBase, options?: WithReferenceOptions): ExecutableResourcePromise { + const connectionName = options?.connectionName; + const optional = options?.optional; + return new ExecutableResourcePromise(this._withReferenceInternal(source, connectionName, optional)); + } + + /** @internal */ + private async _withServiceReferenceInternal(source: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, source }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withServiceReference', + rpcArgs + ); + return new ExecutableResource(result, this._client); + } + + /** Adds a service discovery reference to another resource */ + withServiceReference(source: ResourceBuilderBase): ExecutableResourcePromise { + return new ExecutableResourcePromise(this._withServiceReferenceInternal(source)); + } + + /** @internal */ + private async _withServiceReferenceNamedInternal(source: ResourceBuilderBase, name: string): Promise { + const rpcArgs: Record = { builder: this._handle, source, name }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withServiceReferenceNamed', + rpcArgs + ); + return new ExecutableResource(result, this._client); + } + + /** Adds a named service discovery reference */ + withServiceReferenceNamed(source: ResourceBuilderBase, name: string): ExecutableResourcePromise { + return new ExecutableResourcePromise(this._withServiceReferenceNamedInternal(source, name)); + } + + /** @internal */ + private async _withReferenceUriInternal(name: string, uri: string): Promise { + const rpcArgs: Record = { builder: this._handle, name, uri }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withReferenceUri', + rpcArgs + ); + return new ExecutableResource(result, this._client); + } + + /** Adds a reference to a URI */ + withReferenceUri(name: string, uri: string): ExecutableResourcePromise { + return new ExecutableResourcePromise(this._withReferenceUriInternal(name, uri)); + } + + /** @internal */ + private async _withReferenceExternalServiceInternal(externalService: ExternalServiceResource): Promise { + const rpcArgs: Record = { builder: this._handle, externalService }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withReferenceExternalService', + rpcArgs + ); + return new ExecutableResource(result, this._client); + } + + /** Adds a reference to an external service */ + withReferenceExternalService(externalService: ExternalServiceResource): ExecutableResourcePromise { + return new ExecutableResourcePromise(this._withReferenceExternalServiceInternal(externalService)); + } + + /** @internal */ + private async _withReferenceEndpointInternal(endpointReference: EndpointReference): Promise { + const rpcArgs: Record = { builder: this._handle, endpointReference }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withReferenceEndpoint', + rpcArgs + ); + return new ExecutableResource(result, this._client); + } + + /** Adds a reference to an endpoint */ + withReferenceEndpoint(endpointReference: EndpointReference): ExecutableResourcePromise { + return new ExecutableResourcePromise(this._withReferenceEndpointInternal(endpointReference)); + } + + /** @internal */ + private async _withEndpointInternal(port?: number, targetPort?: number, scheme?: string, name?: string, env?: string, isProxied?: boolean, isExternal?: boolean, protocol?: ProtocolType): Promise { + const rpcArgs: Record = { builder: this._handle }; + if (port !== undefined) rpcArgs.port = port; + if (targetPort !== undefined) rpcArgs.targetPort = targetPort; + if (scheme !== undefined) rpcArgs.scheme = scheme; + if (name !== undefined) rpcArgs.name = name; + if (env !== undefined) rpcArgs.env = env; + if (isProxied !== undefined) rpcArgs.isProxied = isProxied; + if (isExternal !== undefined) rpcArgs.isExternal = isExternal; + if (protocol !== undefined) rpcArgs.protocol = protocol; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withEndpoint', + rpcArgs + ); + return new ExecutableResource(result, this._client); + } + + /** Adds a network endpoint */ + withEndpoint(options?: WithEndpointOptions): ExecutableResourcePromise { + const port = options?.port; + const targetPort = options?.targetPort; + const scheme = options?.scheme; + const name = options?.name; + const env = options?.env; + const isProxied = options?.isProxied; + const isExternal = options?.isExternal; + const protocol = options?.protocol; + return new ExecutableResourcePromise(this._withEndpointInternal(port, targetPort, scheme, name, env, isProxied, isExternal, protocol)); + } + + /** @internal */ + private async _withHttpEndpointInternal(port?: number, targetPort?: number, name?: string, env?: string, isProxied?: boolean): Promise { + const rpcArgs: Record = { builder: this._handle }; + if (port !== undefined) rpcArgs.port = port; + if (targetPort !== undefined) rpcArgs.targetPort = targetPort; + if (name !== undefined) rpcArgs.name = name; + if (env !== undefined) rpcArgs.env = env; + if (isProxied !== undefined) rpcArgs.isProxied = isProxied; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withHttpEndpoint', + rpcArgs + ); + return new ExecutableResource(result, this._client); + } + + /** Adds an HTTP endpoint */ + withHttpEndpoint(options?: WithHttpEndpointOptions): ExecutableResourcePromise { + const port = options?.port; + const targetPort = options?.targetPort; + const name = options?.name; + const env = options?.env; + const isProxied = options?.isProxied; + return new ExecutableResourcePromise(this._withHttpEndpointInternal(port, targetPort, name, env, isProxied)); + } + + /** @internal */ + private async _withHttpsEndpointInternal(port?: number, targetPort?: number, name?: string, env?: string, isProxied?: boolean): Promise { + const rpcArgs: Record = { builder: this._handle }; + if (port !== undefined) rpcArgs.port = port; + if (targetPort !== undefined) rpcArgs.targetPort = targetPort; + if (name !== undefined) rpcArgs.name = name; + if (env !== undefined) rpcArgs.env = env; + if (isProxied !== undefined) rpcArgs.isProxied = isProxied; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withHttpsEndpoint', + rpcArgs + ); + return new ExecutableResource(result, this._client); + } + + /** Adds an HTTPS endpoint */ + withHttpsEndpoint(options?: WithHttpsEndpointOptions): ExecutableResourcePromise { + const port = options?.port; + const targetPort = options?.targetPort; + const name = options?.name; + const env = options?.env; + const isProxied = options?.isProxied; + return new ExecutableResourcePromise(this._withHttpsEndpointInternal(port, targetPort, name, env, isProxied)); + } + + /** @internal */ + private async _withExternalHttpEndpointsInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withExternalHttpEndpoints', + rpcArgs + ); + return new ExecutableResource(result, this._client); + } + + /** Makes HTTP endpoints externally accessible */ + withExternalHttpEndpoints(): ExecutableResourcePromise { + return new ExecutableResourcePromise(this._withExternalHttpEndpointsInternal()); + } + + /** Gets an endpoint reference */ + async getEndpoint(name: string): Promise { + const rpcArgs: Record = { builder: this._handle, name }; + return await this._client.invokeCapability( + 'Aspire.Hosting/getEndpoint', + rpcArgs + ); + } + + /** @internal */ + private async _asHttp2ServiceInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/asHttp2Service', + rpcArgs + ); + return new ExecutableResource(result, this._client); + } + + /** Configures resource for HTTP/2 */ + asHttp2Service(): ExecutableResourcePromise { + return new ExecutableResourcePromise(this._asHttp2ServiceInternal()); + } + + /** @internal */ + private async _withUrlsCallbackInternal(callback: (obj: ResourceUrlsCallbackContext) => Promise): Promise { + const callbackId = registerCallback(async (objData: unknown) => { + const objHandle = wrapIfHandle(objData) as ResourceUrlsCallbackContextHandle; + const obj = new ResourceUrlsCallbackContext(objHandle, this._client); + await callback(obj); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrlsCallback', + rpcArgs + ); + return new ExecutableResource(result, this._client); + } + + /** Customizes displayed URLs via callback */ + withUrlsCallback(callback: (obj: ResourceUrlsCallbackContext) => Promise): ExecutableResourcePromise { + return new ExecutableResourcePromise(this._withUrlsCallbackInternal(callback)); + } + + /** @internal */ + private async _withUrlsCallbackAsyncInternal(callback: (arg: ResourceUrlsCallbackContext) => Promise): Promise { + const callbackId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as ResourceUrlsCallbackContextHandle; + const arg = new ResourceUrlsCallbackContext(argHandle, this._client); + await callback(arg); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrlsCallbackAsync', + rpcArgs + ); + return new ExecutableResource(result, this._client); + } + + /** Customizes displayed URLs via async callback */ + withUrlsCallbackAsync(callback: (arg: ResourceUrlsCallbackContext) => Promise): ExecutableResourcePromise { + return new ExecutableResourcePromise(this._withUrlsCallbackAsyncInternal(callback)); + } + + /** @internal */ + private async _withUrlInternal(url: string, displayText?: string): Promise { + const rpcArgs: Record = { builder: this._handle, url }; + if (displayText !== undefined) rpcArgs.displayText = displayText; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrl', + rpcArgs + ); + return new ExecutableResource(result, this._client); + } + + /** Adds or modifies displayed URLs */ + withUrl(url: string, options?: WithUrlOptions): ExecutableResourcePromise { + const displayText = options?.displayText; + return new ExecutableResourcePromise(this._withUrlInternal(url, displayText)); + } + + /** @internal */ + private async _withUrlExpressionInternal(url: ReferenceExpression, displayText?: string): Promise { + const rpcArgs: Record = { builder: this._handle, url }; + if (displayText !== undefined) rpcArgs.displayText = displayText; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrlExpression', + rpcArgs + ); + return new ExecutableResource(result, this._client); + } + + /** Adds a URL using a reference expression */ + withUrlExpression(url: ReferenceExpression, options?: WithUrlExpressionOptions): ExecutableResourcePromise { + const displayText = options?.displayText; + return new ExecutableResourcePromise(this._withUrlExpressionInternal(url, displayText)); + } + + /** @internal */ + private async _withUrlForEndpointInternal(endpointName: string, callback: (obj: ResourceUrlAnnotation) => Promise): Promise { + const callbackId = registerCallback(async (objData: unknown) => { + const obj = wrapIfHandle(objData) as ResourceUrlAnnotation; + await callback(obj); + }); + const rpcArgs: Record = { builder: this._handle, endpointName, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrlForEndpoint', + rpcArgs + ); + return new ExecutableResource(result, this._client); + } + + /** Customizes the URL for a specific endpoint via callback */ + withUrlForEndpoint(endpointName: string, callback: (obj: ResourceUrlAnnotation) => Promise): ExecutableResourcePromise { + return new ExecutableResourcePromise(this._withUrlForEndpointInternal(endpointName, callback)); + } + + /** @internal */ + private async _withUrlForEndpointFactoryInternal(endpointName: string, callback: (arg: EndpointReference) => Promise): Promise { + const callbackId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as EndpointReferenceHandle; + const arg = new EndpointReference(argHandle, this._client); + return await callback(arg); + }); + const rpcArgs: Record = { builder: this._handle, endpointName, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrlForEndpointFactory', + rpcArgs + ); + return new ExecutableResource(result, this._client); + } + + /** Adds a URL for a specific endpoint via factory callback */ + withUrlForEndpointFactory(endpointName: string, callback: (arg: EndpointReference) => Promise): ExecutableResourcePromise { + return new ExecutableResourcePromise(this._withUrlForEndpointFactoryInternal(endpointName, callback)); + } + + /** @internal */ + private async _excludeFromManifestInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/excludeFromManifest', + rpcArgs + ); + return new ExecutableResource(result, this._client); + } + + /** Excludes the resource from the deployment manifest */ + excludeFromManifest(): ExecutableResourcePromise { + return new ExecutableResourcePromise(this._excludeFromManifestInternal()); + } + + /** @internal */ + private async _waitForInternal(dependency: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, dependency }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/waitFor', + rpcArgs + ); + return new ExecutableResource(result, this._client); + } + + /** Waits for another resource to be ready */ + waitFor(dependency: ResourceBuilderBase): ExecutableResourcePromise { + return new ExecutableResourcePromise(this._waitForInternal(dependency)); + } + + /** @internal */ + private async _waitForWithBehaviorInternal(dependency: ResourceBuilderBase, waitBehavior: WaitBehavior): Promise { + const rpcArgs: Record = { builder: this._handle, dependency, waitBehavior }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/waitForWithBehavior', + rpcArgs + ); + return new ExecutableResource(result, this._client); + } + + /** Waits for another resource with specific behavior */ + waitForWithBehavior(dependency: ResourceBuilderBase, waitBehavior: WaitBehavior): ExecutableResourcePromise { + return new ExecutableResourcePromise(this._waitForWithBehaviorInternal(dependency, waitBehavior)); + } + + /** @internal */ + private async _waitForStartInternal(dependency: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, dependency }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/waitForStart', + rpcArgs + ); + return new ExecutableResource(result, this._client); + } + + /** Waits for another resource to start */ + waitForStart(dependency: ResourceBuilderBase): ExecutableResourcePromise { + return new ExecutableResourcePromise(this._waitForStartInternal(dependency)); + } + + /** @internal */ + private async _waitForStartWithBehaviorInternal(dependency: ResourceBuilderBase, waitBehavior: WaitBehavior): Promise { + const rpcArgs: Record = { builder: this._handle, dependency, waitBehavior }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/waitForStartWithBehavior', + rpcArgs + ); + return new ExecutableResource(result, this._client); + } + + /** Waits for another resource to start with specific behavior */ + waitForStartWithBehavior(dependency: ResourceBuilderBase, waitBehavior: WaitBehavior): ExecutableResourcePromise { + return new ExecutableResourcePromise(this._waitForStartWithBehaviorInternal(dependency, waitBehavior)); + } + + /** @internal */ + private async _withExplicitStartInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withExplicitStart', + rpcArgs + ); + return new ExecutableResource(result, this._client); + } + + /** Prevents resource from starting automatically */ + withExplicitStart(): ExecutableResourcePromise { + return new ExecutableResourcePromise(this._withExplicitStartInternal()); + } + + /** @internal */ + private async _waitForCompletionInternal(dependency: ResourceBuilderBase, exitCode?: number): Promise { + const rpcArgs: Record = { builder: this._handle, dependency }; + if (exitCode !== undefined) rpcArgs.exitCode = exitCode; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/waitForCompletion', + rpcArgs + ); + return new ExecutableResource(result, this._client); + } + + /** Waits for resource completion */ + waitForCompletion(dependency: ResourceBuilderBase, options?: WaitForCompletionOptions): ExecutableResourcePromise { + const exitCode = options?.exitCode; + return new ExecutableResourcePromise(this._waitForCompletionInternal(dependency, exitCode)); + } + + /** @internal */ + private async _withHealthCheckInternal(key: string): Promise { + const rpcArgs: Record = { builder: this._handle, key }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withHealthCheck', + rpcArgs + ); + return new ExecutableResource(result, this._client); + } + + /** Adds a health check by key */ + withHealthCheck(key: string): ExecutableResourcePromise { + return new ExecutableResourcePromise(this._withHealthCheckInternal(key)); + } + + /** @internal */ + private async _withHttpHealthCheckInternal(path?: string, statusCode?: number, endpointName?: string): Promise { + const rpcArgs: Record = { builder: this._handle }; + if (path !== undefined) rpcArgs.path = path; + if (statusCode !== undefined) rpcArgs.statusCode = statusCode; + if (endpointName !== undefined) rpcArgs.endpointName = endpointName; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withHttpHealthCheck', + rpcArgs + ); + return new ExecutableResource(result, this._client); + } + + /** Adds an HTTP health check */ + withHttpHealthCheck(options?: WithHttpHealthCheckOptions): ExecutableResourcePromise { + const path = options?.path; + const statusCode = options?.statusCode; + const endpointName = options?.endpointName; + return new ExecutableResourcePromise(this._withHttpHealthCheckInternal(path, statusCode, endpointName)); + } + + /** @internal */ + private async _withCommandInternal(name: string, displayName: string, executeCommand: (arg: ExecuteCommandContext) => Promise, commandOptions?: CommandOptions): Promise { + const executeCommandId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as ExecuteCommandContextHandle; + const arg = new ExecuteCommandContext(argHandle, this._client); + return await executeCommand(arg); + }); + const rpcArgs: Record = { builder: this._handle, name, displayName, executeCommand: executeCommandId }; + if (commandOptions !== undefined) rpcArgs.commandOptions = commandOptions; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withCommand', + rpcArgs + ); + return new ExecutableResource(result, this._client); + } + + /** Adds a resource command */ + withCommand(name: string, displayName: string, executeCommand: (arg: ExecuteCommandContext) => Promise, options?: WithCommandOptions): ExecutableResourcePromise { + const commandOptions = options?.commandOptions; + return new ExecutableResourcePromise(this._withCommandInternal(name, displayName, executeCommand, commandOptions)); + } + + /** @internal */ + private async _withDeveloperCertificateTrustInternal(trust: boolean): Promise { + const rpcArgs: Record = { builder: this._handle, trust }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withDeveloperCertificateTrust', + rpcArgs + ); + return new ExecutableResource(result, this._client); + } + + /** Configures developer certificate trust */ + withDeveloperCertificateTrust(trust: boolean): ExecutableResourcePromise { + return new ExecutableResourcePromise(this._withDeveloperCertificateTrustInternal(trust)); + } + + /** @internal */ + private async _withCertificateTrustScopeInternal(scope: CertificateTrustScope): Promise { + const rpcArgs: Record = { builder: this._handle, scope }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withCertificateTrustScope', + rpcArgs + ); + return new ExecutableResource(result, this._client); + } + + /** Sets the certificate trust scope */ + withCertificateTrustScope(scope: CertificateTrustScope): ExecutableResourcePromise { + return new ExecutableResourcePromise(this._withCertificateTrustScopeInternal(scope)); + } + + /** @internal */ + private async _withHttpsDeveloperCertificateInternal(password?: ParameterResource): Promise { + const rpcArgs: Record = { builder: this._handle }; + if (password !== undefined) rpcArgs.password = password; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withHttpsDeveloperCertificate', + rpcArgs + ); + return new ExecutableResource(result, this._client); + } + + /** Configures HTTPS with a developer certificate */ + withHttpsDeveloperCertificate(options?: WithHttpsDeveloperCertificateOptions): ExecutableResourcePromise { + const password = options?.password; + return new ExecutableResourcePromise(this._withHttpsDeveloperCertificateInternal(password)); + } + + /** @internal */ + private async _withoutHttpsCertificateInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withoutHttpsCertificate', + rpcArgs + ); + return new ExecutableResource(result, this._client); + } + + /** Removes HTTPS certificate configuration */ + withoutHttpsCertificate(): ExecutableResourcePromise { + return new ExecutableResourcePromise(this._withoutHttpsCertificateInternal()); + } + + /** @internal */ + private async _withParentRelationshipInternal(parent: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, parent }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withParentRelationship', + rpcArgs + ); + return new ExecutableResource(result, this._client); + } + + /** Sets the parent relationship */ + withParentRelationship(parent: ResourceBuilderBase): ExecutableResourcePromise { + return new ExecutableResourcePromise(this._withParentRelationshipInternal(parent)); + } + + /** @internal */ + private async _withChildRelationshipInternal(child: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, child }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withChildRelationship', + rpcArgs + ); + return new ExecutableResource(result, this._client); + } + + /** Sets a child relationship */ + withChildRelationship(child: ResourceBuilderBase): ExecutableResourcePromise { + return new ExecutableResourcePromise(this._withChildRelationshipInternal(child)); + } + + /** @internal */ + private async _withIconNameInternal(iconName: string, iconVariant?: IconVariant): Promise { + const rpcArgs: Record = { builder: this._handle, iconName }; + if (iconVariant !== undefined) rpcArgs.iconVariant = iconVariant; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withIconName', + rpcArgs + ); + return new ExecutableResource(result, this._client); + } + + /** Sets the icon for the resource */ + withIconName(iconName: string, options?: WithIconNameOptions): ExecutableResourcePromise { + const iconVariant = options?.iconVariant; + return new ExecutableResourcePromise(this._withIconNameInternal(iconName, iconVariant)); + } + + /** @internal */ + private async _withHttpProbeInternal(probeType: ProbeType, path?: string, initialDelaySeconds?: number, periodSeconds?: number, timeoutSeconds?: number, failureThreshold?: number, successThreshold?: number, endpointName?: string): Promise { + const rpcArgs: Record = { builder: this._handle, probeType }; + if (path !== undefined) rpcArgs.path = path; + if (initialDelaySeconds !== undefined) rpcArgs.initialDelaySeconds = initialDelaySeconds; + if (periodSeconds !== undefined) rpcArgs.periodSeconds = periodSeconds; + if (timeoutSeconds !== undefined) rpcArgs.timeoutSeconds = timeoutSeconds; + if (failureThreshold !== undefined) rpcArgs.failureThreshold = failureThreshold; + if (successThreshold !== undefined) rpcArgs.successThreshold = successThreshold; + if (endpointName !== undefined) rpcArgs.endpointName = endpointName; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withHttpProbe', + rpcArgs + ); + return new ExecutableResource(result, this._client); + } + + /** Adds an HTTP health probe to the resource */ + withHttpProbe(probeType: ProbeType, options?: WithHttpProbeOptions): ExecutableResourcePromise { + const path = options?.path; + const initialDelaySeconds = options?.initialDelaySeconds; + const periodSeconds = options?.periodSeconds; + const timeoutSeconds = options?.timeoutSeconds; + const failureThreshold = options?.failureThreshold; + const successThreshold = options?.successThreshold; + const endpointName = options?.endpointName; + return new ExecutableResourcePromise(this._withHttpProbeInternal(probeType, path, initialDelaySeconds, periodSeconds, timeoutSeconds, failureThreshold, successThreshold, endpointName)); + } + + /** @internal */ + private async _excludeFromMcpInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/excludeFromMcp', + rpcArgs + ); + return new ExecutableResource(result, this._client); + } + + /** Excludes the resource from MCP server exposure */ + excludeFromMcp(): ExecutableResourcePromise { + return new ExecutableResourcePromise(this._excludeFromMcpInternal()); + } + + /** @internal */ + private async _withRemoteImageNameInternal(remoteImageName: string): Promise { + const rpcArgs: Record = { builder: this._handle, remoteImageName }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withRemoteImageName', + rpcArgs + ); + return new ExecutableResource(result, this._client); + } + + /** Sets the remote image name for publishing */ + withRemoteImageName(remoteImageName: string): ExecutableResourcePromise { + return new ExecutableResourcePromise(this._withRemoteImageNameInternal(remoteImageName)); + } + + /** @internal */ + private async _withRemoteImageTagInternal(remoteImageTag: string): Promise { + const rpcArgs: Record = { builder: this._handle, remoteImageTag }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withRemoteImageTag', + rpcArgs + ); + return new ExecutableResource(result, this._client); + } + + /** Sets the remote image tag for publishing */ + withRemoteImageTag(remoteImageTag: string): ExecutableResourcePromise { + return new ExecutableResourcePromise(this._withRemoteImageTagInternal(remoteImageTag)); + } + + /** @internal */ + private async _withPipelineStepFactoryInternal(stepName: string, callback: (arg: PipelineStepContext) => Promise, dependsOn?: string[], requiredBy?: string[], tags?: string[], description?: string): Promise { + const callbackId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as PipelineStepContextHandle; + const arg = new PipelineStepContext(argHandle, this._client); + await callback(arg); + }); + const rpcArgs: Record = { builder: this._handle, stepName, callback: callbackId }; + if (dependsOn !== undefined) rpcArgs.dependsOn = dependsOn; + if (requiredBy !== undefined) rpcArgs.requiredBy = requiredBy; + if (tags !== undefined) rpcArgs.tags = tags; + if (description !== undefined) rpcArgs.description = description; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withPipelineStepFactory', + rpcArgs + ); + return new ExecutableResource(result, this._client); + } + + /** Adds a pipeline step to the resource */ + withPipelineStepFactory(stepName: string, callback: (arg: PipelineStepContext) => Promise, options?: WithPipelineStepFactoryOptions): ExecutableResourcePromise { + const dependsOn = options?.dependsOn; + const requiredBy = options?.requiredBy; + const tags = options?.tags; + const description = options?.description; + return new ExecutableResourcePromise(this._withPipelineStepFactoryInternal(stepName, callback, dependsOn, requiredBy, tags, description)); + } + + /** @internal */ + private async _withPipelineConfigurationAsyncInternal(callback: (arg: PipelineConfigurationContext) => Promise): Promise { + const callbackId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as PipelineConfigurationContextHandle; + const arg = new PipelineConfigurationContext(argHandle, this._client); + await callback(arg); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withPipelineConfigurationAsync', + rpcArgs + ); + return new ExecutableResource(result, this._client); + } + + /** Configures pipeline step dependencies via an async callback */ + withPipelineConfigurationAsync(callback: (arg: PipelineConfigurationContext) => Promise): ExecutableResourcePromise { + return new ExecutableResourcePromise(this._withPipelineConfigurationAsyncInternal(callback)); + } + + /** @internal */ + private async _withPipelineConfigurationInternal(callback: (obj: PipelineConfigurationContext) => Promise): Promise { + const callbackId = registerCallback(async (objData: unknown) => { + const objHandle = wrapIfHandle(objData) as PipelineConfigurationContextHandle; + const obj = new PipelineConfigurationContext(objHandle, this._client); + await callback(obj); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withPipelineConfiguration', + rpcArgs + ); + return new ExecutableResource(result, this._client); + } + + /** Configures pipeline step dependencies via a callback */ + withPipelineConfiguration(callback: (obj: PipelineConfigurationContext) => Promise): ExecutableResourcePromise { + return new ExecutableResourcePromise(this._withPipelineConfigurationInternal(callback)); + } + + /** Gets the resource name */ + async getResourceName(): Promise { + const rpcArgs: Record = { resource: this._handle }; + return await this._client.invokeCapability( + 'Aspire.Hosting/getResourceName', + rpcArgs + ); + } + + /** @internal */ + private async _withStorageRoleAssignmentsInternal(target: AzureStorageResource, roles: AzureStorageRole[]): Promise { + const rpcArgs: Record = { builder: this._handle, target, roles }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure.Storage/withStorageRoleAssignments', + rpcArgs + ); + return new ExecutableResource(result, this._client); + } + + /** Assigns Azure Storage roles to a resource */ + withStorageRoleAssignments(target: AzureStorageResource, roles: AzureStorageRole[]): ExecutableResourcePromise { + return new ExecutableResourcePromise(this._withStorageRoleAssignmentsInternal(target, roles)); + } + + /** @internal */ + private async _withEventHubsRoleAssignmentsInternal(target: AzureEventHubsResource, roles: AzureEventHubsRole[]): Promise { + const rpcArgs: Record = { builder: this._handle, target, roles }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure.EventHubs/withEventHubsRoleAssignments', + rpcArgs + ); + return new ExecutableResource(result, this._client); + } + + /** Assigns Event Hubs roles to a resource */ + withEventHubsRoleAssignments(target: AzureEventHubsResource, roles: AzureEventHubsRole[]): ExecutableResourcePromise { + return new ExecutableResourcePromise(this._withEventHubsRoleAssignmentsInternal(target, roles)); + } + + /** @internal */ + private async _withEnvironmentFromOutputInternal(name: string, bicepOutputReference: BicepOutputReference): Promise { + const rpcArgs: Record = { builder: this._handle, name, bicepOutputReference }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure/withEnvironmentFromOutput', + rpcArgs + ); + return new ExecutableResource(result, this._client); + } + + /** Sets an environment variable from a Bicep output reference */ + withEnvironmentFromOutput(name: string, bicepOutputReference: BicepOutputReference): ExecutableResourcePromise { + return new ExecutableResourcePromise(this._withEnvironmentFromOutputInternal(name, bicepOutputReference)); + } + + /** @internal */ + private async _withEnvironmentFromKeyVaultSecretInternal(name: string, secretReference: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, name, secretReference }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure/withEnvironmentFromKeyVaultSecret', + rpcArgs + ); + return new ExecutableResource(result, this._client); + } + + /** Sets an environment variable from an Azure Key Vault secret reference */ + withEnvironmentFromKeyVaultSecret(name: string, secretReference: ResourceBuilderBase): ExecutableResourcePromise { + return new ExecutableResourcePromise(this._withEnvironmentFromKeyVaultSecretInternal(name, secretReference)); + } + + /** @internal */ + private async _withAzureUserAssignedIdentityInternal(identityResourceBuilder: AzureUserAssignedIdentityResource): Promise { + const rpcArgs: Record = { builder: this._handle, identityResourceBuilder }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure/withUserAssignedIdentityAzureUserAssignedIdentity', + rpcArgs + ); + return new ExecutableResource(result, this._client); + } + + /** Associates an Azure user-assigned identity with a compute resource */ + withAzureUserAssignedIdentity(identityResourceBuilder: AzureUserAssignedIdentityResource): ExecutableResourcePromise { + return new ExecutableResourcePromise(this._withAzureUserAssignedIdentityInternal(identityResourceBuilder)); + } + +} + +/** + * Thenable wrapper for ExecutableResource that enables fluent chaining. + * @example + * await builder.addSomething().withX().withY(); + */ +export class ExecutableResourcePromise implements PromiseLike { + constructor(private _promise: Promise) {} + + then( + onfulfilled?: ((value: ExecutableResource) => TResult1 | PromiseLike) | null, + onrejected?: ((reason: unknown) => TResult2 | PromiseLike) | null + ): PromiseLike { + return this._promise.then(onfulfilled, onrejected); + } + + /** Configures a resource to use a container registry */ + withContainerRegistry(registry: ResourceBuilderBase): ExecutableResourcePromise { + return new ExecutableResourcePromise(this._promise.then(obj => obj.withContainerRegistry(registry))); + } + + /** Sets the base image for a Dockerfile build */ + withDockerfileBaseImage(options?: WithDockerfileBaseImageOptions): ExecutableResourcePromise { + return new ExecutableResourcePromise(this._promise.then(obj => obj.withDockerfileBaseImage(options))); + } + + /** Configures an MCP server endpoint on the resource */ + withMcpServer(options?: WithMcpServerOptions): ExecutableResourcePromise { + return new ExecutableResourcePromise(this._promise.then(obj => obj.withMcpServer(options))); + } + + /** Configures OTLP telemetry export */ + withOtlpExporter(): ExecutableResourcePromise { + return new ExecutableResourcePromise(this._promise.then(obj => obj.withOtlpExporter())); + } + + /** Configures OTLP telemetry export with specific protocol */ + withOtlpExporterProtocol(protocol: OtlpProtocol): ExecutableResourcePromise { + return new ExecutableResourcePromise(this._promise.then(obj => obj.withOtlpExporterProtocol(protocol))); + } + + /** Adds a required command dependency */ + withRequiredCommand(command: string, options?: WithRequiredCommandOptions): ExecutableResourcePromise { + return new ExecutableResourcePromise(this._promise.then(obj => obj.withRequiredCommand(command, options))); + } + + /** Sets an environment variable */ + withEnvironment(name: string, value: string): ExecutableResourcePromise { + return new ExecutableResourcePromise(this._promise.then(obj => obj.withEnvironment(name, value))); + } + + /** Adds an environment variable with a reference expression */ + withEnvironmentExpression(name: string, value: ReferenceExpression): ExecutableResourcePromise { + return new ExecutableResourcePromise(this._promise.then(obj => obj.withEnvironmentExpression(name, value))); + } + + /** Sets environment variables via callback */ + withEnvironmentCallback(callback: (obj: EnvironmentCallbackContext) => Promise): ExecutableResourcePromise { + return new ExecutableResourcePromise(this._promise.then(obj => obj.withEnvironmentCallback(callback))); + } + + /** Sets environment variables via async callback */ + withEnvironmentCallbackAsync(callback: (arg: EnvironmentCallbackContext) => Promise): ExecutableResourcePromise { + return new ExecutableResourcePromise(this._promise.then(obj => obj.withEnvironmentCallbackAsync(callback))); + } + + /** Sets an environment variable from an endpoint reference */ + withEnvironmentEndpoint(name: string, endpointReference: EndpointReference): ExecutableResourcePromise { + return new ExecutableResourcePromise(this._promise.then(obj => obj.withEnvironmentEndpoint(name, endpointReference))); + } + + /** Sets an environment variable from a parameter resource */ + withEnvironmentParameter(name: string, parameter: ParameterResource): ExecutableResourcePromise { + return new ExecutableResourcePromise(this._promise.then(obj => obj.withEnvironmentParameter(name, parameter))); + } + + /** Sets an environment variable from a connection string resource */ + withEnvironmentConnectionString(envVarName: string, resource: ResourceBuilderBase): ExecutableResourcePromise { + return new ExecutableResourcePromise(this._promise.then(obj => obj.withEnvironmentConnectionString(envVarName, resource))); + } + + /** Adds arguments */ + withArgs(args: string[]): ExecutableResourcePromise { + return new ExecutableResourcePromise(this._promise.then(obj => obj.withArgs(args))); + } + + /** Sets command-line arguments via callback */ + withArgsCallback(callback: (obj: CommandLineArgsCallbackContext) => Promise): ExecutableResourcePromise { + return new ExecutableResourcePromise(this._promise.then(obj => obj.withArgsCallback(callback))); + } + + /** Sets command-line arguments via async callback */ + withArgsCallbackAsync(callback: (arg: CommandLineArgsCallbackContext) => Promise): ExecutableResourcePromise { + return new ExecutableResourcePromise(this._promise.then(obj => obj.withArgsCallbackAsync(callback))); + } + + /** Adds a reference to another resource */ + withReference(source: ResourceBuilderBase, options?: WithReferenceOptions): ExecutableResourcePromise { + return new ExecutableResourcePromise(this._promise.then(obj => obj.withReference(source, options))); + } + + /** Adds a service discovery reference to another resource */ + withServiceReference(source: ResourceBuilderBase): ExecutableResourcePromise { + return new ExecutableResourcePromise(this._promise.then(obj => obj.withServiceReference(source))); + } + + /** Adds a named service discovery reference */ + withServiceReferenceNamed(source: ResourceBuilderBase, name: string): ExecutableResourcePromise { + return new ExecutableResourcePromise(this._promise.then(obj => obj.withServiceReferenceNamed(source, name))); + } + + /** Adds a reference to a URI */ + withReferenceUri(name: string, uri: string): ExecutableResourcePromise { + return new ExecutableResourcePromise(this._promise.then(obj => obj.withReferenceUri(name, uri))); + } + + /** Adds a reference to an external service */ + withReferenceExternalService(externalService: ExternalServiceResource): ExecutableResourcePromise { + return new ExecutableResourcePromise(this._promise.then(obj => obj.withReferenceExternalService(externalService))); + } + + /** Adds a reference to an endpoint */ + withReferenceEndpoint(endpointReference: EndpointReference): ExecutableResourcePromise { + return new ExecutableResourcePromise(this._promise.then(obj => obj.withReferenceEndpoint(endpointReference))); + } + + /** Adds a network endpoint */ + withEndpoint(options?: WithEndpointOptions): ExecutableResourcePromise { + return new ExecutableResourcePromise(this._promise.then(obj => obj.withEndpoint(options))); + } + + /** Adds an HTTP endpoint */ + withHttpEndpoint(options?: WithHttpEndpointOptions): ExecutableResourcePromise { + return new ExecutableResourcePromise(this._promise.then(obj => obj.withHttpEndpoint(options))); + } + + /** Adds an HTTPS endpoint */ + withHttpsEndpoint(options?: WithHttpsEndpointOptions): ExecutableResourcePromise { + return new ExecutableResourcePromise(this._promise.then(obj => obj.withHttpsEndpoint(options))); + } + + /** Makes HTTP endpoints externally accessible */ + withExternalHttpEndpoints(): ExecutableResourcePromise { + return new ExecutableResourcePromise(this._promise.then(obj => obj.withExternalHttpEndpoints())); + } + + /** Gets an endpoint reference */ + getEndpoint(name: string): Promise { + return this._promise.then(obj => obj.getEndpoint(name)); + } + + /** Configures resource for HTTP/2 */ + asHttp2Service(): ExecutableResourcePromise { + return new ExecutableResourcePromise(this._promise.then(obj => obj.asHttp2Service())); + } + + /** Customizes displayed URLs via callback */ + withUrlsCallback(callback: (obj: ResourceUrlsCallbackContext) => Promise): ExecutableResourcePromise { + return new ExecutableResourcePromise(this._promise.then(obj => obj.withUrlsCallback(callback))); + } + + /** Customizes displayed URLs via async callback */ + withUrlsCallbackAsync(callback: (arg: ResourceUrlsCallbackContext) => Promise): ExecutableResourcePromise { + return new ExecutableResourcePromise(this._promise.then(obj => obj.withUrlsCallbackAsync(callback))); + } + + /** Adds or modifies displayed URLs */ + withUrl(url: string, options?: WithUrlOptions): ExecutableResourcePromise { + return new ExecutableResourcePromise(this._promise.then(obj => obj.withUrl(url, options))); + } + + /** Adds a URL using a reference expression */ + withUrlExpression(url: ReferenceExpression, options?: WithUrlExpressionOptions): ExecutableResourcePromise { + return new ExecutableResourcePromise(this._promise.then(obj => obj.withUrlExpression(url, options))); + } + + /** Customizes the URL for a specific endpoint via callback */ + withUrlForEndpoint(endpointName: string, callback: (obj: ResourceUrlAnnotation) => Promise): ExecutableResourcePromise { + return new ExecutableResourcePromise(this._promise.then(obj => obj.withUrlForEndpoint(endpointName, callback))); + } + + /** Adds a URL for a specific endpoint via factory callback */ + withUrlForEndpointFactory(endpointName: string, callback: (arg: EndpointReference) => Promise): ExecutableResourcePromise { + return new ExecutableResourcePromise(this._promise.then(obj => obj.withUrlForEndpointFactory(endpointName, callback))); + } + + /** Excludes the resource from the deployment manifest */ + excludeFromManifest(): ExecutableResourcePromise { + return new ExecutableResourcePromise(this._promise.then(obj => obj.excludeFromManifest())); + } + + /** Waits for another resource to be ready */ + waitFor(dependency: ResourceBuilderBase): ExecutableResourcePromise { + return new ExecutableResourcePromise(this._promise.then(obj => obj.waitFor(dependency))); + } + + /** Waits for another resource with specific behavior */ + waitForWithBehavior(dependency: ResourceBuilderBase, waitBehavior: WaitBehavior): ExecutableResourcePromise { + return new ExecutableResourcePromise(this._promise.then(obj => obj.waitForWithBehavior(dependency, waitBehavior))); + } + + /** Waits for another resource to start */ + waitForStart(dependency: ResourceBuilderBase): ExecutableResourcePromise { + return new ExecutableResourcePromise(this._promise.then(obj => obj.waitForStart(dependency))); + } + + /** Waits for another resource to start with specific behavior */ + waitForStartWithBehavior(dependency: ResourceBuilderBase, waitBehavior: WaitBehavior): ExecutableResourcePromise { + return new ExecutableResourcePromise(this._promise.then(obj => obj.waitForStartWithBehavior(dependency, waitBehavior))); + } + + /** Prevents resource from starting automatically */ + withExplicitStart(): ExecutableResourcePromise { + return new ExecutableResourcePromise(this._promise.then(obj => obj.withExplicitStart())); + } + + /** Waits for resource completion */ + waitForCompletion(dependency: ResourceBuilderBase, options?: WaitForCompletionOptions): ExecutableResourcePromise { + return new ExecutableResourcePromise(this._promise.then(obj => obj.waitForCompletion(dependency, options))); + } + + /** Adds a health check by key */ + withHealthCheck(key: string): ExecutableResourcePromise { + return new ExecutableResourcePromise(this._promise.then(obj => obj.withHealthCheck(key))); + } + + /** Adds an HTTP health check */ + withHttpHealthCheck(options?: WithHttpHealthCheckOptions): ExecutableResourcePromise { + return new ExecutableResourcePromise(this._promise.then(obj => obj.withHttpHealthCheck(options))); + } + + /** Adds a resource command */ + withCommand(name: string, displayName: string, executeCommand: (arg: ExecuteCommandContext) => Promise, options?: WithCommandOptions): ExecutableResourcePromise { + return new ExecutableResourcePromise(this._promise.then(obj => obj.withCommand(name, displayName, executeCommand, options))); + } + + /** Configures developer certificate trust */ + withDeveloperCertificateTrust(trust: boolean): ExecutableResourcePromise { + return new ExecutableResourcePromise(this._promise.then(obj => obj.withDeveloperCertificateTrust(trust))); + } + + /** Sets the certificate trust scope */ + withCertificateTrustScope(scope: CertificateTrustScope): ExecutableResourcePromise { + return new ExecutableResourcePromise(this._promise.then(obj => obj.withCertificateTrustScope(scope))); + } + + /** Configures HTTPS with a developer certificate */ + withHttpsDeveloperCertificate(options?: WithHttpsDeveloperCertificateOptions): ExecutableResourcePromise { + return new ExecutableResourcePromise(this._promise.then(obj => obj.withHttpsDeveloperCertificate(options))); + } + + /** Removes HTTPS certificate configuration */ + withoutHttpsCertificate(): ExecutableResourcePromise { + return new ExecutableResourcePromise(this._promise.then(obj => obj.withoutHttpsCertificate())); + } + + /** Sets the parent relationship */ + withParentRelationship(parent: ResourceBuilderBase): ExecutableResourcePromise { + return new ExecutableResourcePromise(this._promise.then(obj => obj.withParentRelationship(parent))); + } + + /** Sets a child relationship */ + withChildRelationship(child: ResourceBuilderBase): ExecutableResourcePromise { + return new ExecutableResourcePromise(this._promise.then(obj => obj.withChildRelationship(child))); + } + + /** Sets the icon for the resource */ + withIconName(iconName: string, options?: WithIconNameOptions): ExecutableResourcePromise { + return new ExecutableResourcePromise(this._promise.then(obj => obj.withIconName(iconName, options))); + } + + /** Adds an HTTP health probe to the resource */ + withHttpProbe(probeType: ProbeType, options?: WithHttpProbeOptions): ExecutableResourcePromise { + return new ExecutableResourcePromise(this._promise.then(obj => obj.withHttpProbe(probeType, options))); + } + + /** Excludes the resource from MCP server exposure */ + excludeFromMcp(): ExecutableResourcePromise { + return new ExecutableResourcePromise(this._promise.then(obj => obj.excludeFromMcp())); + } + + /** Sets the remote image name for publishing */ + withRemoteImageName(remoteImageName: string): ExecutableResourcePromise { + return new ExecutableResourcePromise(this._promise.then(obj => obj.withRemoteImageName(remoteImageName))); + } + + /** Sets the remote image tag for publishing */ + withRemoteImageTag(remoteImageTag: string): ExecutableResourcePromise { + return new ExecutableResourcePromise(this._promise.then(obj => obj.withRemoteImageTag(remoteImageTag))); + } + + /** Adds a pipeline step to the resource */ + withPipelineStepFactory(stepName: string, callback: (arg: PipelineStepContext) => Promise, options?: WithPipelineStepFactoryOptions): ExecutableResourcePromise { + return new ExecutableResourcePromise(this._promise.then(obj => obj.withPipelineStepFactory(stepName, callback, options))); + } + + /** Configures pipeline step dependencies via an async callback */ + withPipelineConfigurationAsync(callback: (arg: PipelineConfigurationContext) => Promise): ExecutableResourcePromise { + return new ExecutableResourcePromise(this._promise.then(obj => obj.withPipelineConfigurationAsync(callback))); + } + + /** Configures pipeline step dependencies via a callback */ + withPipelineConfiguration(callback: (obj: PipelineConfigurationContext) => Promise): ExecutableResourcePromise { + return new ExecutableResourcePromise(this._promise.then(obj => obj.withPipelineConfiguration(callback))); + } + + /** Gets the resource name */ + getResourceName(): Promise { + return this._promise.then(obj => obj.getResourceName()); + } + + /** Assigns Azure Storage roles to a resource */ + withStorageRoleAssignments(target: AzureStorageResource, roles: AzureStorageRole[]): ExecutableResourcePromise { + return new ExecutableResourcePromise(this._promise.then(obj => obj.withStorageRoleAssignments(target, roles))); + } + + /** Assigns Event Hubs roles to a resource */ + withEventHubsRoleAssignments(target: AzureEventHubsResource, roles: AzureEventHubsRole[]): ExecutableResourcePromise { + return new ExecutableResourcePromise(this._promise.then(obj => obj.withEventHubsRoleAssignments(target, roles))); + } + + /** Sets an environment variable from a Bicep output reference */ + withEnvironmentFromOutput(name: string, bicepOutputReference: BicepOutputReference): ExecutableResourcePromise { + return new ExecutableResourcePromise(this._promise.then(obj => obj.withEnvironmentFromOutput(name, bicepOutputReference))); + } + + /** Sets an environment variable from an Azure Key Vault secret reference */ + withEnvironmentFromKeyVaultSecret(name: string, secretReference: ResourceBuilderBase): ExecutableResourcePromise { + return new ExecutableResourcePromise(this._promise.then(obj => obj.withEnvironmentFromKeyVaultSecret(name, secretReference))); + } + + /** Associates an Azure user-assigned identity with a compute resource */ + withAzureUserAssignedIdentity(identityResourceBuilder: AzureUserAssignedIdentityResource): ExecutableResourcePromise { + return new ExecutableResourcePromise(this._promise.then(obj => obj.withAzureUserAssignedIdentity(identityResourceBuilder))); + } + +} + +// ============================================================================ +// ExternalServiceResource +// ============================================================================ + +export class ExternalServiceResource extends ResourceBuilderBase { + constructor(handle: ExternalServiceResourceHandle, client: AspireClientRpc) { + super(handle, client); + } + + /** @internal */ + private async _withContainerRegistryInternal(registry: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, registry }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withContainerRegistry', + rpcArgs + ); + return new ExternalServiceResource(result, this._client); + } + + /** Configures a resource to use a container registry */ + withContainerRegistry(registry: ResourceBuilderBase): ExternalServiceResourcePromise { + return new ExternalServiceResourcePromise(this._withContainerRegistryInternal(registry)); + } + + /** @internal */ + private async _withDockerfileBaseImageInternal(buildImage?: string, runtimeImage?: string): Promise { + const rpcArgs: Record = { builder: this._handle }; + if (buildImage !== undefined) rpcArgs.buildImage = buildImage; + if (runtimeImage !== undefined) rpcArgs.runtimeImage = runtimeImage; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withDockerfileBaseImage', + rpcArgs + ); + return new ExternalServiceResource(result, this._client); + } + + /** Sets the base image for a Dockerfile build */ + withDockerfileBaseImage(options?: WithDockerfileBaseImageOptions): ExternalServiceResourcePromise { + const buildImage = options?.buildImage; + const runtimeImage = options?.runtimeImage; + return new ExternalServiceResourcePromise(this._withDockerfileBaseImageInternal(buildImage, runtimeImage)); + } + + /** @internal */ + private async _withExternalServiceHttpHealthCheckInternal(path?: string, statusCode?: number): Promise { + const rpcArgs: Record = { builder: this._handle }; + if (path !== undefined) rpcArgs.path = path; + if (statusCode !== undefined) rpcArgs.statusCode = statusCode; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withExternalServiceHttpHealthCheck', + rpcArgs + ); + return new ExternalServiceResource(result, this._client); + } + + /** Adds an HTTP health check to an external service */ + withExternalServiceHttpHealthCheck(options?: WithExternalServiceHttpHealthCheckOptions): ExternalServiceResourcePromise { + const path = options?.path; + const statusCode = options?.statusCode; + return new ExternalServiceResourcePromise(this._withExternalServiceHttpHealthCheckInternal(path, statusCode)); + } + + /** @internal */ + private async _withRequiredCommandInternal(command: string, helpLink?: string): Promise { + const rpcArgs: Record = { builder: this._handle, command }; + if (helpLink !== undefined) rpcArgs.helpLink = helpLink; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withRequiredCommand', + rpcArgs + ); + return new ExternalServiceResource(result, this._client); + } + + /** Adds a required command dependency */ + withRequiredCommand(command: string, options?: WithRequiredCommandOptions): ExternalServiceResourcePromise { + const helpLink = options?.helpLink; + return new ExternalServiceResourcePromise(this._withRequiredCommandInternal(command, helpLink)); + } + + /** @internal */ + private async _withUrlsCallbackInternal(callback: (obj: ResourceUrlsCallbackContext) => Promise): Promise { + const callbackId = registerCallback(async (objData: unknown) => { + const objHandle = wrapIfHandle(objData) as ResourceUrlsCallbackContextHandle; + const obj = new ResourceUrlsCallbackContext(objHandle, this._client); + await callback(obj); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrlsCallback', + rpcArgs + ); + return new ExternalServiceResource(result, this._client); + } + + /** Customizes displayed URLs via callback */ + withUrlsCallback(callback: (obj: ResourceUrlsCallbackContext) => Promise): ExternalServiceResourcePromise { + return new ExternalServiceResourcePromise(this._withUrlsCallbackInternal(callback)); + } + + /** @internal */ + private async _withUrlsCallbackAsyncInternal(callback: (arg: ResourceUrlsCallbackContext) => Promise): Promise { + const callbackId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as ResourceUrlsCallbackContextHandle; + const arg = new ResourceUrlsCallbackContext(argHandle, this._client); + await callback(arg); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrlsCallbackAsync', + rpcArgs + ); + return new ExternalServiceResource(result, this._client); + } + + /** Customizes displayed URLs via async callback */ + withUrlsCallbackAsync(callback: (arg: ResourceUrlsCallbackContext) => Promise): ExternalServiceResourcePromise { + return new ExternalServiceResourcePromise(this._withUrlsCallbackAsyncInternal(callback)); + } + + /** @internal */ + private async _withUrlInternal(url: string, displayText?: string): Promise { + const rpcArgs: Record = { builder: this._handle, url }; + if (displayText !== undefined) rpcArgs.displayText = displayText; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrl', + rpcArgs + ); + return new ExternalServiceResource(result, this._client); + } + + /** Adds or modifies displayed URLs */ + withUrl(url: string, options?: WithUrlOptions): ExternalServiceResourcePromise { + const displayText = options?.displayText; + return new ExternalServiceResourcePromise(this._withUrlInternal(url, displayText)); + } + + /** @internal */ + private async _withUrlExpressionInternal(url: ReferenceExpression, displayText?: string): Promise { + const rpcArgs: Record = { builder: this._handle, url }; + if (displayText !== undefined) rpcArgs.displayText = displayText; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrlExpression', + rpcArgs + ); + return new ExternalServiceResource(result, this._client); + } + + /** Adds a URL using a reference expression */ + withUrlExpression(url: ReferenceExpression, options?: WithUrlExpressionOptions): ExternalServiceResourcePromise { + const displayText = options?.displayText; + return new ExternalServiceResourcePromise(this._withUrlExpressionInternal(url, displayText)); + } + + /** @internal */ + private async _withUrlForEndpointInternal(endpointName: string, callback: (obj: ResourceUrlAnnotation) => Promise): Promise { + const callbackId = registerCallback(async (objData: unknown) => { + const obj = wrapIfHandle(objData) as ResourceUrlAnnotation; + await callback(obj); + }); + const rpcArgs: Record = { builder: this._handle, endpointName, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrlForEndpoint', + rpcArgs + ); + return new ExternalServiceResource(result, this._client); + } + + /** Customizes the URL for a specific endpoint via callback */ + withUrlForEndpoint(endpointName: string, callback: (obj: ResourceUrlAnnotation) => Promise): ExternalServiceResourcePromise { + return new ExternalServiceResourcePromise(this._withUrlForEndpointInternal(endpointName, callback)); + } + + /** @internal */ + private async _excludeFromManifestInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/excludeFromManifest', + rpcArgs + ); + return new ExternalServiceResource(result, this._client); + } + + /** Excludes the resource from the deployment manifest */ + excludeFromManifest(): ExternalServiceResourcePromise { + return new ExternalServiceResourcePromise(this._excludeFromManifestInternal()); + } + + /** @internal */ + private async _withExplicitStartInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withExplicitStart', + rpcArgs + ); + return new ExternalServiceResource(result, this._client); + } + + /** Prevents resource from starting automatically */ + withExplicitStart(): ExternalServiceResourcePromise { + return new ExternalServiceResourcePromise(this._withExplicitStartInternal()); + } + + /** @internal */ + private async _withHealthCheckInternal(key: string): Promise { + const rpcArgs: Record = { builder: this._handle, key }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withHealthCheck', + rpcArgs + ); + return new ExternalServiceResource(result, this._client); + } + + /** Adds a health check by key */ + withHealthCheck(key: string): ExternalServiceResourcePromise { + return new ExternalServiceResourcePromise(this._withHealthCheckInternal(key)); + } + + /** @internal */ + private async _withCommandInternal(name: string, displayName: string, executeCommand: (arg: ExecuteCommandContext) => Promise, commandOptions?: CommandOptions): Promise { + const executeCommandId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as ExecuteCommandContextHandle; + const arg = new ExecuteCommandContext(argHandle, this._client); + return await executeCommand(arg); + }); + const rpcArgs: Record = { builder: this._handle, name, displayName, executeCommand: executeCommandId }; + if (commandOptions !== undefined) rpcArgs.commandOptions = commandOptions; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withCommand', + rpcArgs + ); + return new ExternalServiceResource(result, this._client); + } + + /** Adds a resource command */ + withCommand(name: string, displayName: string, executeCommand: (arg: ExecuteCommandContext) => Promise, options?: WithCommandOptions): ExternalServiceResourcePromise { + const commandOptions = options?.commandOptions; + return new ExternalServiceResourcePromise(this._withCommandInternal(name, displayName, executeCommand, commandOptions)); + } + + /** @internal */ + private async _withParentRelationshipInternal(parent: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, parent }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withParentRelationship', + rpcArgs + ); + return new ExternalServiceResource(result, this._client); + } + + /** Sets the parent relationship */ + withParentRelationship(parent: ResourceBuilderBase): ExternalServiceResourcePromise { + return new ExternalServiceResourcePromise(this._withParentRelationshipInternal(parent)); + } + + /** @internal */ + private async _withChildRelationshipInternal(child: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, child }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withChildRelationship', + rpcArgs + ); + return new ExternalServiceResource(result, this._client); + } + + /** Sets a child relationship */ + withChildRelationship(child: ResourceBuilderBase): ExternalServiceResourcePromise { + return new ExternalServiceResourcePromise(this._withChildRelationshipInternal(child)); + } + + /** @internal */ + private async _withIconNameInternal(iconName: string, iconVariant?: IconVariant): Promise { + const rpcArgs: Record = { builder: this._handle, iconName }; + if (iconVariant !== undefined) rpcArgs.iconVariant = iconVariant; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withIconName', + rpcArgs + ); + return new ExternalServiceResource(result, this._client); + } + + /** Sets the icon for the resource */ + withIconName(iconName: string, options?: WithIconNameOptions): ExternalServiceResourcePromise { + const iconVariant = options?.iconVariant; + return new ExternalServiceResourcePromise(this._withIconNameInternal(iconName, iconVariant)); + } + + /** @internal */ + private async _excludeFromMcpInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/excludeFromMcp', + rpcArgs + ); + return new ExternalServiceResource(result, this._client); + } + + /** Excludes the resource from MCP server exposure */ + excludeFromMcp(): ExternalServiceResourcePromise { + return new ExternalServiceResourcePromise(this._excludeFromMcpInternal()); + } + + /** @internal */ + private async _withPipelineStepFactoryInternal(stepName: string, callback: (arg: PipelineStepContext) => Promise, dependsOn?: string[], requiredBy?: string[], tags?: string[], description?: string): Promise { + const callbackId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as PipelineStepContextHandle; + const arg = new PipelineStepContext(argHandle, this._client); + await callback(arg); + }); + const rpcArgs: Record = { builder: this._handle, stepName, callback: callbackId }; + if (dependsOn !== undefined) rpcArgs.dependsOn = dependsOn; + if (requiredBy !== undefined) rpcArgs.requiredBy = requiredBy; + if (tags !== undefined) rpcArgs.tags = tags; + if (description !== undefined) rpcArgs.description = description; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withPipelineStepFactory', + rpcArgs + ); + return new ExternalServiceResource(result, this._client); + } + + /** Adds a pipeline step to the resource */ + withPipelineStepFactory(stepName: string, callback: (arg: PipelineStepContext) => Promise, options?: WithPipelineStepFactoryOptions): ExternalServiceResourcePromise { + const dependsOn = options?.dependsOn; + const requiredBy = options?.requiredBy; + const tags = options?.tags; + const description = options?.description; + return new ExternalServiceResourcePromise(this._withPipelineStepFactoryInternal(stepName, callback, dependsOn, requiredBy, tags, description)); + } + + /** @internal */ + private async _withPipelineConfigurationAsyncInternal(callback: (arg: PipelineConfigurationContext) => Promise): Promise { + const callbackId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as PipelineConfigurationContextHandle; + const arg = new PipelineConfigurationContext(argHandle, this._client); + await callback(arg); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withPipelineConfigurationAsync', + rpcArgs + ); + return new ExternalServiceResource(result, this._client); + } + + /** Configures pipeline step dependencies via an async callback */ + withPipelineConfigurationAsync(callback: (arg: PipelineConfigurationContext) => Promise): ExternalServiceResourcePromise { + return new ExternalServiceResourcePromise(this._withPipelineConfigurationAsyncInternal(callback)); + } + + /** @internal */ + private async _withPipelineConfigurationInternal(callback: (obj: PipelineConfigurationContext) => Promise): Promise { + const callbackId = registerCallback(async (objData: unknown) => { + const objHandle = wrapIfHandle(objData) as PipelineConfigurationContextHandle; + const obj = new PipelineConfigurationContext(objHandle, this._client); + await callback(obj); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withPipelineConfiguration', + rpcArgs + ); + return new ExternalServiceResource(result, this._client); + } + + /** Configures pipeline step dependencies via a callback */ + withPipelineConfiguration(callback: (obj: PipelineConfigurationContext) => Promise): ExternalServiceResourcePromise { + return new ExternalServiceResourcePromise(this._withPipelineConfigurationInternal(callback)); + } + + /** Gets the resource name */ + async getResourceName(): Promise { + const rpcArgs: Record = { resource: this._handle }; + return await this._client.invokeCapability( + 'Aspire.Hosting/getResourceName', + rpcArgs + ); + } + + /** @internal */ + private async _withStorageRoleAssignmentsInternal(target: AzureStorageResource, roles: AzureStorageRole[]): Promise { + const rpcArgs: Record = { builder: this._handle, target, roles }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure.Storage/withStorageRoleAssignments', + rpcArgs + ); + return new ExternalServiceResource(result, this._client); + } + + /** Assigns Azure Storage roles to a resource */ + withStorageRoleAssignments(target: AzureStorageResource, roles: AzureStorageRole[]): ExternalServiceResourcePromise { + return new ExternalServiceResourcePromise(this._withStorageRoleAssignmentsInternal(target, roles)); + } + + /** @internal */ + private async _withEventHubsRoleAssignmentsInternal(target: AzureEventHubsResource, roles: AzureEventHubsRole[]): Promise { + const rpcArgs: Record = { builder: this._handle, target, roles }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure.EventHubs/withEventHubsRoleAssignments', + rpcArgs + ); + return new ExternalServiceResource(result, this._client); + } + + /** Assigns Event Hubs roles to a resource */ + withEventHubsRoleAssignments(target: AzureEventHubsResource, roles: AzureEventHubsRole[]): ExternalServiceResourcePromise { + return new ExternalServiceResourcePromise(this._withEventHubsRoleAssignmentsInternal(target, roles)); + } + +} + +/** + * Thenable wrapper for ExternalServiceResource that enables fluent chaining. + * @example + * await builder.addSomething().withX().withY(); + */ +export class ExternalServiceResourcePromise implements PromiseLike { + constructor(private _promise: Promise) {} + + then( + onfulfilled?: ((value: ExternalServiceResource) => TResult1 | PromiseLike) | null, + onrejected?: ((reason: unknown) => TResult2 | PromiseLike) | null + ): PromiseLike { + return this._promise.then(onfulfilled, onrejected); + } + + /** Configures a resource to use a container registry */ + withContainerRegistry(registry: ResourceBuilderBase): ExternalServiceResourcePromise { + return new ExternalServiceResourcePromise(this._promise.then(obj => obj.withContainerRegistry(registry))); + } + + /** Sets the base image for a Dockerfile build */ + withDockerfileBaseImage(options?: WithDockerfileBaseImageOptions): ExternalServiceResourcePromise { + return new ExternalServiceResourcePromise(this._promise.then(obj => obj.withDockerfileBaseImage(options))); + } + + /** Adds an HTTP health check to an external service */ + withExternalServiceHttpHealthCheck(options?: WithExternalServiceHttpHealthCheckOptions): ExternalServiceResourcePromise { + return new ExternalServiceResourcePromise(this._promise.then(obj => obj.withExternalServiceHttpHealthCheck(options))); + } + + /** Adds a required command dependency */ + withRequiredCommand(command: string, options?: WithRequiredCommandOptions): ExternalServiceResourcePromise { + return new ExternalServiceResourcePromise(this._promise.then(obj => obj.withRequiredCommand(command, options))); + } + + /** Customizes displayed URLs via callback */ + withUrlsCallback(callback: (obj: ResourceUrlsCallbackContext) => Promise): ExternalServiceResourcePromise { + return new ExternalServiceResourcePromise(this._promise.then(obj => obj.withUrlsCallback(callback))); + } + + /** Customizes displayed URLs via async callback */ + withUrlsCallbackAsync(callback: (arg: ResourceUrlsCallbackContext) => Promise): ExternalServiceResourcePromise { + return new ExternalServiceResourcePromise(this._promise.then(obj => obj.withUrlsCallbackAsync(callback))); + } + + /** Adds or modifies displayed URLs */ + withUrl(url: string, options?: WithUrlOptions): ExternalServiceResourcePromise { + return new ExternalServiceResourcePromise(this._promise.then(obj => obj.withUrl(url, options))); + } + + /** Adds a URL using a reference expression */ + withUrlExpression(url: ReferenceExpression, options?: WithUrlExpressionOptions): ExternalServiceResourcePromise { + return new ExternalServiceResourcePromise(this._promise.then(obj => obj.withUrlExpression(url, options))); + } + + /** Customizes the URL for a specific endpoint via callback */ + withUrlForEndpoint(endpointName: string, callback: (obj: ResourceUrlAnnotation) => Promise): ExternalServiceResourcePromise { + return new ExternalServiceResourcePromise(this._promise.then(obj => obj.withUrlForEndpoint(endpointName, callback))); + } + + /** Excludes the resource from the deployment manifest */ + excludeFromManifest(): ExternalServiceResourcePromise { + return new ExternalServiceResourcePromise(this._promise.then(obj => obj.excludeFromManifest())); + } + + /** Prevents resource from starting automatically */ + withExplicitStart(): ExternalServiceResourcePromise { + return new ExternalServiceResourcePromise(this._promise.then(obj => obj.withExplicitStart())); + } + + /** Adds a health check by key */ + withHealthCheck(key: string): ExternalServiceResourcePromise { + return new ExternalServiceResourcePromise(this._promise.then(obj => obj.withHealthCheck(key))); + } + + /** Adds a resource command */ + withCommand(name: string, displayName: string, executeCommand: (arg: ExecuteCommandContext) => Promise, options?: WithCommandOptions): ExternalServiceResourcePromise { + return new ExternalServiceResourcePromise(this._promise.then(obj => obj.withCommand(name, displayName, executeCommand, options))); + } + + /** Sets the parent relationship */ + withParentRelationship(parent: ResourceBuilderBase): ExternalServiceResourcePromise { + return new ExternalServiceResourcePromise(this._promise.then(obj => obj.withParentRelationship(parent))); + } + + /** Sets a child relationship */ + withChildRelationship(child: ResourceBuilderBase): ExternalServiceResourcePromise { + return new ExternalServiceResourcePromise(this._promise.then(obj => obj.withChildRelationship(child))); + } + + /** Sets the icon for the resource */ + withIconName(iconName: string, options?: WithIconNameOptions): ExternalServiceResourcePromise { + return new ExternalServiceResourcePromise(this._promise.then(obj => obj.withIconName(iconName, options))); + } + + /** Excludes the resource from MCP server exposure */ + excludeFromMcp(): ExternalServiceResourcePromise { + return new ExternalServiceResourcePromise(this._promise.then(obj => obj.excludeFromMcp())); + } + + /** Adds a pipeline step to the resource */ + withPipelineStepFactory(stepName: string, callback: (arg: PipelineStepContext) => Promise, options?: WithPipelineStepFactoryOptions): ExternalServiceResourcePromise { + return new ExternalServiceResourcePromise(this._promise.then(obj => obj.withPipelineStepFactory(stepName, callback, options))); + } + + /** Configures pipeline step dependencies via an async callback */ + withPipelineConfigurationAsync(callback: (arg: PipelineConfigurationContext) => Promise): ExternalServiceResourcePromise { + return new ExternalServiceResourcePromise(this._promise.then(obj => obj.withPipelineConfigurationAsync(callback))); + } + + /** Configures pipeline step dependencies via a callback */ + withPipelineConfiguration(callback: (obj: PipelineConfigurationContext) => Promise): ExternalServiceResourcePromise { + return new ExternalServiceResourcePromise(this._promise.then(obj => obj.withPipelineConfiguration(callback))); + } + + /** Gets the resource name */ + getResourceName(): Promise { + return this._promise.then(obj => obj.getResourceName()); + } + + /** Assigns Azure Storage roles to a resource */ + withStorageRoleAssignments(target: AzureStorageResource, roles: AzureStorageRole[]): ExternalServiceResourcePromise { + return new ExternalServiceResourcePromise(this._promise.then(obj => obj.withStorageRoleAssignments(target, roles))); + } + + /** Assigns Event Hubs roles to a resource */ + withEventHubsRoleAssignments(target: AzureEventHubsResource, roles: AzureEventHubsRole[]): ExternalServiceResourcePromise { + return new ExternalServiceResourcePromise(this._promise.then(obj => obj.withEventHubsRoleAssignments(target, roles))); + } + +} + +// ============================================================================ +// JavaScriptAppResource +// ============================================================================ + +export class JavaScriptAppResource extends ResourceBuilderBase { + constructor(handle: JavaScriptAppResourceHandle, client: AspireClientRpc) { + super(handle, client); + } + + /** @internal */ + private async _withContainerRegistryInternal(registry: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, registry }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withContainerRegistry', + rpcArgs + ); + return new JavaScriptAppResource(result, this._client); + } + + /** Configures a resource to use a container registry */ + withContainerRegistry(registry: ResourceBuilderBase): JavaScriptAppResourcePromise { + return new JavaScriptAppResourcePromise(this._withContainerRegistryInternal(registry)); + } + + /** @internal */ + private async _withDockerfileBaseImageInternal(buildImage?: string, runtimeImage?: string): Promise { + const rpcArgs: Record = { builder: this._handle }; + if (buildImage !== undefined) rpcArgs.buildImage = buildImage; + if (runtimeImage !== undefined) rpcArgs.runtimeImage = runtimeImage; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withDockerfileBaseImage', + rpcArgs + ); + return new JavaScriptAppResource(result, this._client); + } + + /** Sets the base image for a Dockerfile build */ + withDockerfileBaseImage(options?: WithDockerfileBaseImageOptions): JavaScriptAppResourcePromise { + const buildImage = options?.buildImage; + const runtimeImage = options?.runtimeImage; + return new JavaScriptAppResourcePromise(this._withDockerfileBaseImageInternal(buildImage, runtimeImage)); + } + + /** @internal */ + private async _publishAsDockerFileInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/publishAsDockerFile', + rpcArgs + ); + return new JavaScriptAppResource(result, this._client); + } + + /** Publishes the executable as a Docker container */ + publishAsDockerFile(): JavaScriptAppResourcePromise { + return new JavaScriptAppResourcePromise(this._publishAsDockerFileInternal()); + } + + /** @internal */ + private async _publishAsDockerFileWithConfigureInternal(configure: (obj: ContainerResource) => Promise): Promise { + const configureId = registerCallback(async (objData: unknown) => { + const objHandle = wrapIfHandle(objData) as ContainerResourceHandle; + const obj = new ContainerResource(objHandle, this._client); + await configure(obj); + }); + const rpcArgs: Record = { builder: this._handle, configure: configureId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/publishAsDockerFileWithConfigure', + rpcArgs + ); + return new JavaScriptAppResource(result, this._client); + } + + /** Publishes an executable as a Docker file with optional container configuration */ + publishAsDockerFileWithConfigure(configure: (obj: ContainerResource) => Promise): JavaScriptAppResourcePromise { + return new JavaScriptAppResourcePromise(this._publishAsDockerFileWithConfigureInternal(configure)); + } + + /** @internal */ + private async _withExecutableCommandInternal(command: string): Promise { + const rpcArgs: Record = { builder: this._handle, command }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withExecutableCommand', + rpcArgs + ); + return new JavaScriptAppResource(result, this._client); + } + + /** Sets the executable command */ + withExecutableCommand(command: string): JavaScriptAppResourcePromise { + return new JavaScriptAppResourcePromise(this._withExecutableCommandInternal(command)); + } + + /** @internal */ + private async _withWorkingDirectoryInternal(workingDirectory: string): Promise { + const rpcArgs: Record = { builder: this._handle, workingDirectory }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withWorkingDirectory', + rpcArgs + ); + return new JavaScriptAppResource(result, this._client); + } + + /** Sets the executable working directory */ + withWorkingDirectory(workingDirectory: string): JavaScriptAppResourcePromise { + return new JavaScriptAppResourcePromise(this._withWorkingDirectoryInternal(workingDirectory)); + } + + /** @internal */ + private async _withMcpServerInternal(path?: string, endpointName?: string): Promise { + const rpcArgs: Record = { builder: this._handle }; + if (path !== undefined) rpcArgs.path = path; + if (endpointName !== undefined) rpcArgs.endpointName = endpointName; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withMcpServer', + rpcArgs + ); + return new JavaScriptAppResource(result, this._client); + } + + /** Configures an MCP server endpoint on the resource */ + withMcpServer(options?: WithMcpServerOptions): JavaScriptAppResourcePromise { + const path = options?.path; + const endpointName = options?.endpointName; + return new JavaScriptAppResourcePromise(this._withMcpServerInternal(path, endpointName)); + } + + /** @internal */ + private async _withOtlpExporterInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withOtlpExporter', + rpcArgs + ); + return new JavaScriptAppResource(result, this._client); + } + + /** Configures OTLP telemetry export */ + withOtlpExporter(): JavaScriptAppResourcePromise { + return new JavaScriptAppResourcePromise(this._withOtlpExporterInternal()); + } + + /** @internal */ + private async _withOtlpExporterProtocolInternal(protocol: OtlpProtocol): Promise { + const rpcArgs: Record = { builder: this._handle, protocol }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withOtlpExporterProtocol', + rpcArgs + ); + return new JavaScriptAppResource(result, this._client); + } + + /** Configures OTLP telemetry export with specific protocol */ + withOtlpExporterProtocol(protocol: OtlpProtocol): JavaScriptAppResourcePromise { + return new JavaScriptAppResourcePromise(this._withOtlpExporterProtocolInternal(protocol)); + } + + /** @internal */ + private async _withRequiredCommandInternal(command: string, helpLink?: string): Promise { + const rpcArgs: Record = { builder: this._handle, command }; + if (helpLink !== undefined) rpcArgs.helpLink = helpLink; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withRequiredCommand', + rpcArgs + ); + return new JavaScriptAppResource(result, this._client); + } + + /** Adds a required command dependency */ + withRequiredCommand(command: string, options?: WithRequiredCommandOptions): JavaScriptAppResourcePromise { + const helpLink = options?.helpLink; + return new JavaScriptAppResourcePromise(this._withRequiredCommandInternal(command, helpLink)); + } + + /** @internal */ + private async _withEnvironmentInternal(name: string, value: string): Promise { + const rpcArgs: Record = { builder: this._handle, name, value }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withEnvironment', + rpcArgs + ); + return new JavaScriptAppResource(result, this._client); + } + + /** Sets an environment variable */ + withEnvironment(name: string, value: string): JavaScriptAppResourcePromise { + return new JavaScriptAppResourcePromise(this._withEnvironmentInternal(name, value)); + } + + /** @internal */ + private async _withEnvironmentExpressionInternal(name: string, value: ReferenceExpression): Promise { + const rpcArgs: Record = { builder: this._handle, name, value }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withEnvironmentExpression', + rpcArgs + ); + return new JavaScriptAppResource(result, this._client); + } + + /** Adds an environment variable with a reference expression */ + withEnvironmentExpression(name: string, value: ReferenceExpression): JavaScriptAppResourcePromise { + return new JavaScriptAppResourcePromise(this._withEnvironmentExpressionInternal(name, value)); + } + + /** @internal */ + private async _withEnvironmentCallbackInternal(callback: (obj: EnvironmentCallbackContext) => Promise): Promise { + const callbackId = registerCallback(async (objData: unknown) => { + const objHandle = wrapIfHandle(objData) as EnvironmentCallbackContextHandle; + const obj = new EnvironmentCallbackContext(objHandle, this._client); + await callback(obj); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withEnvironmentCallback', + rpcArgs + ); + return new JavaScriptAppResource(result, this._client); + } + + /** Sets environment variables via callback */ + withEnvironmentCallback(callback: (obj: EnvironmentCallbackContext) => Promise): JavaScriptAppResourcePromise { + return new JavaScriptAppResourcePromise(this._withEnvironmentCallbackInternal(callback)); + } + + /** @internal */ + private async _withEnvironmentCallbackAsyncInternal(callback: (arg: EnvironmentCallbackContext) => Promise): Promise { + const callbackId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as EnvironmentCallbackContextHandle; + const arg = new EnvironmentCallbackContext(argHandle, this._client); + await callback(arg); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withEnvironmentCallbackAsync', + rpcArgs + ); + return new JavaScriptAppResource(result, this._client); + } + + /** Sets environment variables via async callback */ + withEnvironmentCallbackAsync(callback: (arg: EnvironmentCallbackContext) => Promise): JavaScriptAppResourcePromise { + return new JavaScriptAppResourcePromise(this._withEnvironmentCallbackAsyncInternal(callback)); + } + + /** @internal */ + private async _withEnvironmentEndpointInternal(name: string, endpointReference: EndpointReference): Promise { + const rpcArgs: Record = { builder: this._handle, name, endpointReference }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withEnvironmentEndpoint', + rpcArgs + ); + return new JavaScriptAppResource(result, this._client); + } + + /** Sets an environment variable from an endpoint reference */ + withEnvironmentEndpoint(name: string, endpointReference: EndpointReference): JavaScriptAppResourcePromise { + return new JavaScriptAppResourcePromise(this._withEnvironmentEndpointInternal(name, endpointReference)); + } + + /** @internal */ + private async _withEnvironmentParameterInternal(name: string, parameter: ParameterResource): Promise { + const rpcArgs: Record = { builder: this._handle, name, parameter }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withEnvironmentParameter', + rpcArgs + ); + return new JavaScriptAppResource(result, this._client); + } + + /** Sets an environment variable from a parameter resource */ + withEnvironmentParameter(name: string, parameter: ParameterResource): JavaScriptAppResourcePromise { + return new JavaScriptAppResourcePromise(this._withEnvironmentParameterInternal(name, parameter)); + } + + /** @internal */ + private async _withEnvironmentConnectionStringInternal(envVarName: string, resource: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, envVarName, resource }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withEnvironmentConnectionString', + rpcArgs + ); + return new JavaScriptAppResource(result, this._client); + } + + /** Sets an environment variable from a connection string resource */ + withEnvironmentConnectionString(envVarName: string, resource: ResourceBuilderBase): JavaScriptAppResourcePromise { + return new JavaScriptAppResourcePromise(this._withEnvironmentConnectionStringInternal(envVarName, resource)); + } + + /** @internal */ + private async _withArgsInternal(args: string[]): Promise { + const rpcArgs: Record = { builder: this._handle, args }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withArgs', + rpcArgs + ); + return new JavaScriptAppResource(result, this._client); + } + + /** Adds arguments */ + withArgs(args: string[]): JavaScriptAppResourcePromise { + return new JavaScriptAppResourcePromise(this._withArgsInternal(args)); + } + + /** @internal */ + private async _withArgsCallbackInternal(callback: (obj: CommandLineArgsCallbackContext) => Promise): Promise { + const callbackId = registerCallback(async (objData: unknown) => { + const objHandle = wrapIfHandle(objData) as CommandLineArgsCallbackContextHandle; + const obj = new CommandLineArgsCallbackContext(objHandle, this._client); + await callback(obj); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withArgsCallback', + rpcArgs + ); + return new JavaScriptAppResource(result, this._client); + } + + /** Sets command-line arguments via callback */ + withArgsCallback(callback: (obj: CommandLineArgsCallbackContext) => Promise): JavaScriptAppResourcePromise { + return new JavaScriptAppResourcePromise(this._withArgsCallbackInternal(callback)); + } + + /** @internal */ + private async _withArgsCallbackAsyncInternal(callback: (arg: CommandLineArgsCallbackContext) => Promise): Promise { + const callbackId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as CommandLineArgsCallbackContextHandle; + const arg = new CommandLineArgsCallbackContext(argHandle, this._client); + await callback(arg); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withArgsCallbackAsync', + rpcArgs + ); + return new JavaScriptAppResource(result, this._client); + } + + /** Sets command-line arguments via async callback */ + withArgsCallbackAsync(callback: (arg: CommandLineArgsCallbackContext) => Promise): JavaScriptAppResourcePromise { + return new JavaScriptAppResourcePromise(this._withArgsCallbackAsyncInternal(callback)); + } + + /** @internal */ + private async _withReferenceInternal(source: ResourceBuilderBase, connectionName?: string, optional?: boolean): Promise { + const rpcArgs: Record = { builder: this._handle, source }; + if (connectionName !== undefined) rpcArgs.connectionName = connectionName; + if (optional !== undefined) rpcArgs.optional = optional; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withReference', + rpcArgs + ); + return new JavaScriptAppResource(result, this._client); + } + + /** Adds a reference to another resource */ + withReference(source: ResourceBuilderBase, options?: WithReferenceOptions): JavaScriptAppResourcePromise { + const connectionName = options?.connectionName; + const optional = options?.optional; + return new JavaScriptAppResourcePromise(this._withReferenceInternal(source, connectionName, optional)); + } + + /** @internal */ + private async _withServiceReferenceInternal(source: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, source }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withServiceReference', + rpcArgs + ); + return new JavaScriptAppResource(result, this._client); + } + + /** Adds a service discovery reference to another resource */ + withServiceReference(source: ResourceBuilderBase): JavaScriptAppResourcePromise { + return new JavaScriptAppResourcePromise(this._withServiceReferenceInternal(source)); + } + + /** @internal */ + private async _withServiceReferenceNamedInternal(source: ResourceBuilderBase, name: string): Promise { + const rpcArgs: Record = { builder: this._handle, source, name }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withServiceReferenceNamed', + rpcArgs + ); + return new JavaScriptAppResource(result, this._client); + } + + /** Adds a named service discovery reference */ + withServiceReferenceNamed(source: ResourceBuilderBase, name: string): JavaScriptAppResourcePromise { + return new JavaScriptAppResourcePromise(this._withServiceReferenceNamedInternal(source, name)); + } + + /** @internal */ + private async _withReferenceUriInternal(name: string, uri: string): Promise { + const rpcArgs: Record = { builder: this._handle, name, uri }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withReferenceUri', + rpcArgs + ); + return new JavaScriptAppResource(result, this._client); + } + + /** Adds a reference to a URI */ + withReferenceUri(name: string, uri: string): JavaScriptAppResourcePromise { + return new JavaScriptAppResourcePromise(this._withReferenceUriInternal(name, uri)); + } + + /** @internal */ + private async _withReferenceExternalServiceInternal(externalService: ExternalServiceResource): Promise { + const rpcArgs: Record = { builder: this._handle, externalService }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withReferenceExternalService', + rpcArgs + ); + return new JavaScriptAppResource(result, this._client); + } + + /** Adds a reference to an external service */ + withReferenceExternalService(externalService: ExternalServiceResource): JavaScriptAppResourcePromise { + return new JavaScriptAppResourcePromise(this._withReferenceExternalServiceInternal(externalService)); + } + + /** @internal */ + private async _withReferenceEndpointInternal(endpointReference: EndpointReference): Promise { + const rpcArgs: Record = { builder: this._handle, endpointReference }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withReferenceEndpoint', + rpcArgs + ); + return new JavaScriptAppResource(result, this._client); + } + + /** Adds a reference to an endpoint */ + withReferenceEndpoint(endpointReference: EndpointReference): JavaScriptAppResourcePromise { + return new JavaScriptAppResourcePromise(this._withReferenceEndpointInternal(endpointReference)); + } + + /** @internal */ + private async _withEndpointInternal(port?: number, targetPort?: number, scheme?: string, name?: string, env?: string, isProxied?: boolean, isExternal?: boolean, protocol?: ProtocolType): Promise { + const rpcArgs: Record = { builder: this._handle }; + if (port !== undefined) rpcArgs.port = port; + if (targetPort !== undefined) rpcArgs.targetPort = targetPort; + if (scheme !== undefined) rpcArgs.scheme = scheme; + if (name !== undefined) rpcArgs.name = name; + if (env !== undefined) rpcArgs.env = env; + if (isProxied !== undefined) rpcArgs.isProxied = isProxied; + if (isExternal !== undefined) rpcArgs.isExternal = isExternal; + if (protocol !== undefined) rpcArgs.protocol = protocol; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withEndpoint', + rpcArgs + ); + return new JavaScriptAppResource(result, this._client); + } + + /** Adds a network endpoint */ + withEndpoint(options?: WithEndpointOptions): JavaScriptAppResourcePromise { + const port = options?.port; + const targetPort = options?.targetPort; + const scheme = options?.scheme; + const name = options?.name; + const env = options?.env; + const isProxied = options?.isProxied; + const isExternal = options?.isExternal; + const protocol = options?.protocol; + return new JavaScriptAppResourcePromise(this._withEndpointInternal(port, targetPort, scheme, name, env, isProxied, isExternal, protocol)); + } + + /** @internal */ + private async _withHttpEndpointInternal(port?: number, targetPort?: number, name?: string, env?: string, isProxied?: boolean): Promise { + const rpcArgs: Record = { builder: this._handle }; + if (port !== undefined) rpcArgs.port = port; + if (targetPort !== undefined) rpcArgs.targetPort = targetPort; + if (name !== undefined) rpcArgs.name = name; + if (env !== undefined) rpcArgs.env = env; + if (isProxied !== undefined) rpcArgs.isProxied = isProxied; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withHttpEndpoint', + rpcArgs + ); + return new JavaScriptAppResource(result, this._client); + } + + /** Adds an HTTP endpoint */ + withHttpEndpoint(options?: WithHttpEndpointOptions): JavaScriptAppResourcePromise { + const port = options?.port; + const targetPort = options?.targetPort; + const name = options?.name; + const env = options?.env; + const isProxied = options?.isProxied; + return new JavaScriptAppResourcePromise(this._withHttpEndpointInternal(port, targetPort, name, env, isProxied)); + } + + /** @internal */ + private async _withHttpsEndpointInternal(port?: number, targetPort?: number, name?: string, env?: string, isProxied?: boolean): Promise { + const rpcArgs: Record = { builder: this._handle }; + if (port !== undefined) rpcArgs.port = port; + if (targetPort !== undefined) rpcArgs.targetPort = targetPort; + if (name !== undefined) rpcArgs.name = name; + if (env !== undefined) rpcArgs.env = env; + if (isProxied !== undefined) rpcArgs.isProxied = isProxied; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withHttpsEndpoint', + rpcArgs + ); + return new JavaScriptAppResource(result, this._client); + } + + /** Adds an HTTPS endpoint */ + withHttpsEndpoint(options?: WithHttpsEndpointOptions): JavaScriptAppResourcePromise { + const port = options?.port; + const targetPort = options?.targetPort; + const name = options?.name; + const env = options?.env; + const isProxied = options?.isProxied; + return new JavaScriptAppResourcePromise(this._withHttpsEndpointInternal(port, targetPort, name, env, isProxied)); + } + + /** @internal */ + private async _withExternalHttpEndpointsInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withExternalHttpEndpoints', + rpcArgs + ); + return new JavaScriptAppResource(result, this._client); + } + + /** Makes HTTP endpoints externally accessible */ + withExternalHttpEndpoints(): JavaScriptAppResourcePromise { + return new JavaScriptAppResourcePromise(this._withExternalHttpEndpointsInternal()); + } + + /** Gets an endpoint reference */ + async getEndpoint(name: string): Promise { + const rpcArgs: Record = { builder: this._handle, name }; + return await this._client.invokeCapability( + 'Aspire.Hosting/getEndpoint', + rpcArgs + ); + } + + /** @internal */ + private async _asHttp2ServiceInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/asHttp2Service', + rpcArgs + ); + return new JavaScriptAppResource(result, this._client); + } + + /** Configures resource for HTTP/2 */ + asHttp2Service(): JavaScriptAppResourcePromise { + return new JavaScriptAppResourcePromise(this._asHttp2ServiceInternal()); + } + + /** @internal */ + private async _withUrlsCallbackInternal(callback: (obj: ResourceUrlsCallbackContext) => Promise): Promise { + const callbackId = registerCallback(async (objData: unknown) => { + const objHandle = wrapIfHandle(objData) as ResourceUrlsCallbackContextHandle; + const obj = new ResourceUrlsCallbackContext(objHandle, this._client); + await callback(obj); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrlsCallback', + rpcArgs + ); + return new JavaScriptAppResource(result, this._client); + } + + /** Customizes displayed URLs via callback */ + withUrlsCallback(callback: (obj: ResourceUrlsCallbackContext) => Promise): JavaScriptAppResourcePromise { + return new JavaScriptAppResourcePromise(this._withUrlsCallbackInternal(callback)); + } + + /** @internal */ + private async _withUrlsCallbackAsyncInternal(callback: (arg: ResourceUrlsCallbackContext) => Promise): Promise { + const callbackId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as ResourceUrlsCallbackContextHandle; + const arg = new ResourceUrlsCallbackContext(argHandle, this._client); + await callback(arg); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrlsCallbackAsync', + rpcArgs + ); + return new JavaScriptAppResource(result, this._client); + } + + /** Customizes displayed URLs via async callback */ + withUrlsCallbackAsync(callback: (arg: ResourceUrlsCallbackContext) => Promise): JavaScriptAppResourcePromise { + return new JavaScriptAppResourcePromise(this._withUrlsCallbackAsyncInternal(callback)); + } + + /** @internal */ + private async _withUrlInternal(url: string, displayText?: string): Promise { + const rpcArgs: Record = { builder: this._handle, url }; + if (displayText !== undefined) rpcArgs.displayText = displayText; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrl', + rpcArgs + ); + return new JavaScriptAppResource(result, this._client); + } + + /** Adds or modifies displayed URLs */ + withUrl(url: string, options?: WithUrlOptions): JavaScriptAppResourcePromise { + const displayText = options?.displayText; + return new JavaScriptAppResourcePromise(this._withUrlInternal(url, displayText)); + } + + /** @internal */ + private async _withUrlExpressionInternal(url: ReferenceExpression, displayText?: string): Promise { + const rpcArgs: Record = { builder: this._handle, url }; + if (displayText !== undefined) rpcArgs.displayText = displayText; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrlExpression', + rpcArgs + ); + return new JavaScriptAppResource(result, this._client); + } + + /** Adds a URL using a reference expression */ + withUrlExpression(url: ReferenceExpression, options?: WithUrlExpressionOptions): JavaScriptAppResourcePromise { + const displayText = options?.displayText; + return new JavaScriptAppResourcePromise(this._withUrlExpressionInternal(url, displayText)); + } + + /** @internal */ + private async _withUrlForEndpointInternal(endpointName: string, callback: (obj: ResourceUrlAnnotation) => Promise): Promise { + const callbackId = registerCallback(async (objData: unknown) => { + const obj = wrapIfHandle(objData) as ResourceUrlAnnotation; + await callback(obj); + }); + const rpcArgs: Record = { builder: this._handle, endpointName, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrlForEndpoint', + rpcArgs + ); + return new JavaScriptAppResource(result, this._client); + } + + /** Customizes the URL for a specific endpoint via callback */ + withUrlForEndpoint(endpointName: string, callback: (obj: ResourceUrlAnnotation) => Promise): JavaScriptAppResourcePromise { + return new JavaScriptAppResourcePromise(this._withUrlForEndpointInternal(endpointName, callback)); + } + + /** @internal */ + private async _withUrlForEndpointFactoryInternal(endpointName: string, callback: (arg: EndpointReference) => Promise): Promise { + const callbackId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as EndpointReferenceHandle; + const arg = new EndpointReference(argHandle, this._client); + return await callback(arg); + }); + const rpcArgs: Record = { builder: this._handle, endpointName, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrlForEndpointFactory', + rpcArgs + ); + return new JavaScriptAppResource(result, this._client); + } + + /** Adds a URL for a specific endpoint via factory callback */ + withUrlForEndpointFactory(endpointName: string, callback: (arg: EndpointReference) => Promise): JavaScriptAppResourcePromise { + return new JavaScriptAppResourcePromise(this._withUrlForEndpointFactoryInternal(endpointName, callback)); + } + + /** @internal */ + private async _withContainerFilesSourceInternal(sourcePath: string): Promise { + const rpcArgs: Record = { builder: this._handle, sourcePath }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withContainerFilesSource', + rpcArgs + ); + return new JavaScriptAppResource(result, this._client); + } + + /** Sets the source directory for container files */ + withContainerFilesSource(sourcePath: string): JavaScriptAppResourcePromise { + return new JavaScriptAppResourcePromise(this._withContainerFilesSourceInternal(sourcePath)); + } + + /** @internal */ + private async _clearContainerFilesSourcesInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/clearContainerFilesSources', + rpcArgs + ); + return new JavaScriptAppResource(result, this._client); + } + + /** Clears all container file sources */ + clearContainerFilesSources(): JavaScriptAppResourcePromise { + return new JavaScriptAppResourcePromise(this._clearContainerFilesSourcesInternal()); + } + + /** @internal */ + private async _excludeFromManifestInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/excludeFromManifest', + rpcArgs + ); + return new JavaScriptAppResource(result, this._client); + } + + /** Excludes the resource from the deployment manifest */ + excludeFromManifest(): JavaScriptAppResourcePromise { + return new JavaScriptAppResourcePromise(this._excludeFromManifestInternal()); + } + + /** @internal */ + private async _waitForInternal(dependency: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, dependency }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/waitFor', + rpcArgs + ); + return new JavaScriptAppResource(result, this._client); + } + + /** Waits for another resource to be ready */ + waitFor(dependency: ResourceBuilderBase): JavaScriptAppResourcePromise { + return new JavaScriptAppResourcePromise(this._waitForInternal(dependency)); + } + + /** @internal */ + private async _waitForWithBehaviorInternal(dependency: ResourceBuilderBase, waitBehavior: WaitBehavior): Promise { + const rpcArgs: Record = { builder: this._handle, dependency, waitBehavior }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/waitForWithBehavior', + rpcArgs + ); + return new JavaScriptAppResource(result, this._client); + } + + /** Waits for another resource with specific behavior */ + waitForWithBehavior(dependency: ResourceBuilderBase, waitBehavior: WaitBehavior): JavaScriptAppResourcePromise { + return new JavaScriptAppResourcePromise(this._waitForWithBehaviorInternal(dependency, waitBehavior)); + } + + /** @internal */ + private async _waitForStartInternal(dependency: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, dependency }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/waitForStart', + rpcArgs + ); + return new JavaScriptAppResource(result, this._client); + } + + /** Waits for another resource to start */ + waitForStart(dependency: ResourceBuilderBase): JavaScriptAppResourcePromise { + return new JavaScriptAppResourcePromise(this._waitForStartInternal(dependency)); + } + + /** @internal */ + private async _waitForStartWithBehaviorInternal(dependency: ResourceBuilderBase, waitBehavior: WaitBehavior): Promise { + const rpcArgs: Record = { builder: this._handle, dependency, waitBehavior }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/waitForStartWithBehavior', + rpcArgs + ); + return new JavaScriptAppResource(result, this._client); + } + + /** Waits for another resource to start with specific behavior */ + waitForStartWithBehavior(dependency: ResourceBuilderBase, waitBehavior: WaitBehavior): JavaScriptAppResourcePromise { + return new JavaScriptAppResourcePromise(this._waitForStartWithBehaviorInternal(dependency, waitBehavior)); + } + + /** @internal */ + private async _withExplicitStartInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withExplicitStart', + rpcArgs + ); + return new JavaScriptAppResource(result, this._client); + } + + /** Prevents resource from starting automatically */ + withExplicitStart(): JavaScriptAppResourcePromise { + return new JavaScriptAppResourcePromise(this._withExplicitStartInternal()); + } + + /** @internal */ + private async _waitForCompletionInternal(dependency: ResourceBuilderBase, exitCode?: number): Promise { + const rpcArgs: Record = { builder: this._handle, dependency }; + if (exitCode !== undefined) rpcArgs.exitCode = exitCode; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/waitForCompletion', + rpcArgs + ); + return new JavaScriptAppResource(result, this._client); + } + + /** Waits for resource completion */ + waitForCompletion(dependency: ResourceBuilderBase, options?: WaitForCompletionOptions): JavaScriptAppResourcePromise { + const exitCode = options?.exitCode; + return new JavaScriptAppResourcePromise(this._waitForCompletionInternal(dependency, exitCode)); + } + + /** @internal */ + private async _withHealthCheckInternal(key: string): Promise { + const rpcArgs: Record = { builder: this._handle, key }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withHealthCheck', + rpcArgs + ); + return new JavaScriptAppResource(result, this._client); + } + + /** Adds a health check by key */ + withHealthCheck(key: string): JavaScriptAppResourcePromise { + return new JavaScriptAppResourcePromise(this._withHealthCheckInternal(key)); + } + + /** @internal */ + private async _withHttpHealthCheckInternal(path?: string, statusCode?: number, endpointName?: string): Promise { + const rpcArgs: Record = { builder: this._handle }; + if (path !== undefined) rpcArgs.path = path; + if (statusCode !== undefined) rpcArgs.statusCode = statusCode; + if (endpointName !== undefined) rpcArgs.endpointName = endpointName; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withHttpHealthCheck', + rpcArgs + ); + return new JavaScriptAppResource(result, this._client); + } + + /** Adds an HTTP health check */ + withHttpHealthCheck(options?: WithHttpHealthCheckOptions): JavaScriptAppResourcePromise { + const path = options?.path; + const statusCode = options?.statusCode; + const endpointName = options?.endpointName; + return new JavaScriptAppResourcePromise(this._withHttpHealthCheckInternal(path, statusCode, endpointName)); + } + + /** @internal */ + private async _withCommandInternal(name: string, displayName: string, executeCommand: (arg: ExecuteCommandContext) => Promise, commandOptions?: CommandOptions): Promise { + const executeCommandId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as ExecuteCommandContextHandle; + const arg = new ExecuteCommandContext(argHandle, this._client); + return await executeCommand(arg); + }); + const rpcArgs: Record = { builder: this._handle, name, displayName, executeCommand: executeCommandId }; + if (commandOptions !== undefined) rpcArgs.commandOptions = commandOptions; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withCommand', + rpcArgs + ); + return new JavaScriptAppResource(result, this._client); + } + + /** Adds a resource command */ + withCommand(name: string, displayName: string, executeCommand: (arg: ExecuteCommandContext) => Promise, options?: WithCommandOptions): JavaScriptAppResourcePromise { + const commandOptions = options?.commandOptions; + return new JavaScriptAppResourcePromise(this._withCommandInternal(name, displayName, executeCommand, commandOptions)); + } + + /** @internal */ + private async _withDeveloperCertificateTrustInternal(trust: boolean): Promise { + const rpcArgs: Record = { builder: this._handle, trust }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withDeveloperCertificateTrust', + rpcArgs + ); + return new JavaScriptAppResource(result, this._client); + } + + /** Configures developer certificate trust */ + withDeveloperCertificateTrust(trust: boolean): JavaScriptAppResourcePromise { + return new JavaScriptAppResourcePromise(this._withDeveloperCertificateTrustInternal(trust)); + } + + /** @internal */ + private async _withCertificateTrustScopeInternal(scope: CertificateTrustScope): Promise { + const rpcArgs: Record = { builder: this._handle, scope }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withCertificateTrustScope', + rpcArgs + ); + return new JavaScriptAppResource(result, this._client); + } + + /** Sets the certificate trust scope */ + withCertificateTrustScope(scope: CertificateTrustScope): JavaScriptAppResourcePromise { + return new JavaScriptAppResourcePromise(this._withCertificateTrustScopeInternal(scope)); + } + + /** @internal */ + private async _withHttpsDeveloperCertificateInternal(password?: ParameterResource): Promise { + const rpcArgs: Record = { builder: this._handle }; + if (password !== undefined) rpcArgs.password = password; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withHttpsDeveloperCertificate', + rpcArgs + ); + return new JavaScriptAppResource(result, this._client); + } + + /** Configures HTTPS with a developer certificate */ + withHttpsDeveloperCertificate(options?: WithHttpsDeveloperCertificateOptions): JavaScriptAppResourcePromise { + const password = options?.password; + return new JavaScriptAppResourcePromise(this._withHttpsDeveloperCertificateInternal(password)); + } + + /** @internal */ + private async _withoutHttpsCertificateInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withoutHttpsCertificate', + rpcArgs + ); + return new JavaScriptAppResource(result, this._client); + } + + /** Removes HTTPS certificate configuration */ + withoutHttpsCertificate(): JavaScriptAppResourcePromise { + return new JavaScriptAppResourcePromise(this._withoutHttpsCertificateInternal()); + } + + /** @internal */ + private async _withParentRelationshipInternal(parent: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, parent }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withParentRelationship', + rpcArgs + ); + return new JavaScriptAppResource(result, this._client); + } + + /** Sets the parent relationship */ + withParentRelationship(parent: ResourceBuilderBase): JavaScriptAppResourcePromise { + return new JavaScriptAppResourcePromise(this._withParentRelationshipInternal(parent)); + } + + /** @internal */ + private async _withChildRelationshipInternal(child: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, child }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withChildRelationship', + rpcArgs + ); + return new JavaScriptAppResource(result, this._client); + } + + /** Sets a child relationship */ + withChildRelationship(child: ResourceBuilderBase): JavaScriptAppResourcePromise { + return new JavaScriptAppResourcePromise(this._withChildRelationshipInternal(child)); + } + + /** @internal */ + private async _withIconNameInternal(iconName: string, iconVariant?: IconVariant): Promise { + const rpcArgs: Record = { builder: this._handle, iconName }; + if (iconVariant !== undefined) rpcArgs.iconVariant = iconVariant; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withIconName', + rpcArgs + ); + return new JavaScriptAppResource(result, this._client); + } + + /** Sets the icon for the resource */ + withIconName(iconName: string, options?: WithIconNameOptions): JavaScriptAppResourcePromise { + const iconVariant = options?.iconVariant; + return new JavaScriptAppResourcePromise(this._withIconNameInternal(iconName, iconVariant)); + } + + /** @internal */ + private async _withHttpProbeInternal(probeType: ProbeType, path?: string, initialDelaySeconds?: number, periodSeconds?: number, timeoutSeconds?: number, failureThreshold?: number, successThreshold?: number, endpointName?: string): Promise { + const rpcArgs: Record = { builder: this._handle, probeType }; + if (path !== undefined) rpcArgs.path = path; + if (initialDelaySeconds !== undefined) rpcArgs.initialDelaySeconds = initialDelaySeconds; + if (periodSeconds !== undefined) rpcArgs.periodSeconds = periodSeconds; + if (timeoutSeconds !== undefined) rpcArgs.timeoutSeconds = timeoutSeconds; + if (failureThreshold !== undefined) rpcArgs.failureThreshold = failureThreshold; + if (successThreshold !== undefined) rpcArgs.successThreshold = successThreshold; + if (endpointName !== undefined) rpcArgs.endpointName = endpointName; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withHttpProbe', + rpcArgs + ); + return new JavaScriptAppResource(result, this._client); + } + + /** Adds an HTTP health probe to the resource */ + withHttpProbe(probeType: ProbeType, options?: WithHttpProbeOptions): JavaScriptAppResourcePromise { + const path = options?.path; + const initialDelaySeconds = options?.initialDelaySeconds; + const periodSeconds = options?.periodSeconds; + const timeoutSeconds = options?.timeoutSeconds; + const failureThreshold = options?.failureThreshold; + const successThreshold = options?.successThreshold; + const endpointName = options?.endpointName; + return new JavaScriptAppResourcePromise(this._withHttpProbeInternal(probeType, path, initialDelaySeconds, periodSeconds, timeoutSeconds, failureThreshold, successThreshold, endpointName)); + } + + /** @internal */ + private async _excludeFromMcpInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/excludeFromMcp', + rpcArgs + ); + return new JavaScriptAppResource(result, this._client); + } + + /** Excludes the resource from MCP server exposure */ + excludeFromMcp(): JavaScriptAppResourcePromise { + return new JavaScriptAppResourcePromise(this._excludeFromMcpInternal()); + } + + /** @internal */ + private async _withRemoteImageNameInternal(remoteImageName: string): Promise { + const rpcArgs: Record = { builder: this._handle, remoteImageName }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withRemoteImageName', + rpcArgs + ); + return new JavaScriptAppResource(result, this._client); + } + + /** Sets the remote image name for publishing */ + withRemoteImageName(remoteImageName: string): JavaScriptAppResourcePromise { + return new JavaScriptAppResourcePromise(this._withRemoteImageNameInternal(remoteImageName)); + } + + /** @internal */ + private async _withRemoteImageTagInternal(remoteImageTag: string): Promise { + const rpcArgs: Record = { builder: this._handle, remoteImageTag }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withRemoteImageTag', + rpcArgs + ); + return new JavaScriptAppResource(result, this._client); + } + + /** Sets the remote image tag for publishing */ + withRemoteImageTag(remoteImageTag: string): JavaScriptAppResourcePromise { + return new JavaScriptAppResourcePromise(this._withRemoteImageTagInternal(remoteImageTag)); + } + + /** @internal */ + private async _withPipelineStepFactoryInternal(stepName: string, callback: (arg: PipelineStepContext) => Promise, dependsOn?: string[], requiredBy?: string[], tags?: string[], description?: string): Promise { + const callbackId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as PipelineStepContextHandle; + const arg = new PipelineStepContext(argHandle, this._client); + await callback(arg); + }); + const rpcArgs: Record = { builder: this._handle, stepName, callback: callbackId }; + if (dependsOn !== undefined) rpcArgs.dependsOn = dependsOn; + if (requiredBy !== undefined) rpcArgs.requiredBy = requiredBy; + if (tags !== undefined) rpcArgs.tags = tags; + if (description !== undefined) rpcArgs.description = description; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withPipelineStepFactory', + rpcArgs + ); + return new JavaScriptAppResource(result, this._client); + } + + /** Adds a pipeline step to the resource */ + withPipelineStepFactory(stepName: string, callback: (arg: PipelineStepContext) => Promise, options?: WithPipelineStepFactoryOptions): JavaScriptAppResourcePromise { + const dependsOn = options?.dependsOn; + const requiredBy = options?.requiredBy; + const tags = options?.tags; + const description = options?.description; + return new JavaScriptAppResourcePromise(this._withPipelineStepFactoryInternal(stepName, callback, dependsOn, requiredBy, tags, description)); + } + + /** @internal */ + private async _withPipelineConfigurationAsyncInternal(callback: (arg: PipelineConfigurationContext) => Promise): Promise { + const callbackId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as PipelineConfigurationContextHandle; + const arg = new PipelineConfigurationContext(argHandle, this._client); + await callback(arg); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withPipelineConfigurationAsync', + rpcArgs + ); + return new JavaScriptAppResource(result, this._client); + } + + /** Configures pipeline step dependencies via an async callback */ + withPipelineConfigurationAsync(callback: (arg: PipelineConfigurationContext) => Promise): JavaScriptAppResourcePromise { + return new JavaScriptAppResourcePromise(this._withPipelineConfigurationAsyncInternal(callback)); + } + + /** @internal */ + private async _withPipelineConfigurationInternal(callback: (obj: PipelineConfigurationContext) => Promise): Promise { + const callbackId = registerCallback(async (objData: unknown) => { + const objHandle = wrapIfHandle(objData) as PipelineConfigurationContextHandle; + const obj = new PipelineConfigurationContext(objHandle, this._client); + await callback(obj); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withPipelineConfiguration', + rpcArgs + ); + return new JavaScriptAppResource(result, this._client); + } + + /** Configures pipeline step dependencies via a callback */ + withPipelineConfiguration(callback: (obj: PipelineConfigurationContext) => Promise): JavaScriptAppResourcePromise { + return new JavaScriptAppResourcePromise(this._withPipelineConfigurationInternal(callback)); + } + + /** Gets the resource name */ + async getResourceName(): Promise { + const rpcArgs: Record = { resource: this._handle }; + return await this._client.invokeCapability( + 'Aspire.Hosting/getResourceName', + rpcArgs + ); + } + + /** @internal */ + private async _withStorageRoleAssignmentsInternal(target: AzureStorageResource, roles: AzureStorageRole[]): Promise { + const rpcArgs: Record = { builder: this._handle, target, roles }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure.Storage/withStorageRoleAssignments', + rpcArgs + ); + return new JavaScriptAppResource(result, this._client); + } + + /** Assigns Azure Storage roles to a resource */ + withStorageRoleAssignments(target: AzureStorageResource, roles: AzureStorageRole[]): JavaScriptAppResourcePromise { + return new JavaScriptAppResourcePromise(this._withStorageRoleAssignmentsInternal(target, roles)); + } + + /** @internal */ + private async _withEventHubsRoleAssignmentsInternal(target: AzureEventHubsResource, roles: AzureEventHubsRole[]): Promise { + const rpcArgs: Record = { builder: this._handle, target, roles }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure.EventHubs/withEventHubsRoleAssignments', + rpcArgs + ); + return new JavaScriptAppResource(result, this._client); + } + + /** Assigns Event Hubs roles to a resource */ + withEventHubsRoleAssignments(target: AzureEventHubsResource, roles: AzureEventHubsRole[]): JavaScriptAppResourcePromise { + return new JavaScriptAppResourcePromise(this._withEventHubsRoleAssignmentsInternal(target, roles)); + } + + /** @internal */ + private async _withEnvironmentFromOutputInternal(name: string, bicepOutputReference: BicepOutputReference): Promise { + const rpcArgs: Record = { builder: this._handle, name, bicepOutputReference }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure/withEnvironmentFromOutput', + rpcArgs + ); + return new JavaScriptAppResource(result, this._client); + } + + /** Sets an environment variable from a Bicep output reference */ + withEnvironmentFromOutput(name: string, bicepOutputReference: BicepOutputReference): JavaScriptAppResourcePromise { + return new JavaScriptAppResourcePromise(this._withEnvironmentFromOutputInternal(name, bicepOutputReference)); + } + + /** @internal */ + private async _withEnvironmentFromKeyVaultSecretInternal(name: string, secretReference: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, name, secretReference }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure/withEnvironmentFromKeyVaultSecret', + rpcArgs + ); + return new JavaScriptAppResource(result, this._client); + } + + /** Sets an environment variable from an Azure Key Vault secret reference */ + withEnvironmentFromKeyVaultSecret(name: string, secretReference: ResourceBuilderBase): JavaScriptAppResourcePromise { + return new JavaScriptAppResourcePromise(this._withEnvironmentFromKeyVaultSecretInternal(name, secretReference)); + } + + /** @internal */ + private async _withAzureUserAssignedIdentityInternal(identityResourceBuilder: AzureUserAssignedIdentityResource): Promise { + const rpcArgs: Record = { builder: this._handle, identityResourceBuilder }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure/withUserAssignedIdentityAzureUserAssignedIdentity', + rpcArgs + ); + return new JavaScriptAppResource(result, this._client); + } + + /** Associates an Azure user-assigned identity with a compute resource */ + withAzureUserAssignedIdentity(identityResourceBuilder: AzureUserAssignedIdentityResource): JavaScriptAppResourcePromise { + return new JavaScriptAppResourcePromise(this._withAzureUserAssignedIdentityInternal(identityResourceBuilder)); + } + +} + +/** + * Thenable wrapper for JavaScriptAppResource that enables fluent chaining. + * @example + * await builder.addSomething().withX().withY(); + */ +export class JavaScriptAppResourcePromise implements PromiseLike { + constructor(private _promise: Promise) {} + + then( + onfulfilled?: ((value: JavaScriptAppResource) => TResult1 | PromiseLike) | null, + onrejected?: ((reason: unknown) => TResult2 | PromiseLike) | null + ): PromiseLike { + return this._promise.then(onfulfilled, onrejected); + } + + /** Configures a resource to use a container registry */ + withContainerRegistry(registry: ResourceBuilderBase): JavaScriptAppResourcePromise { + return new JavaScriptAppResourcePromise(this._promise.then(obj => obj.withContainerRegistry(registry))); + } + + /** Sets the base image for a Dockerfile build */ + withDockerfileBaseImage(options?: WithDockerfileBaseImageOptions): JavaScriptAppResourcePromise { + return new JavaScriptAppResourcePromise(this._promise.then(obj => obj.withDockerfileBaseImage(options))); + } + + /** Publishes the executable as a Docker container */ + publishAsDockerFile(): JavaScriptAppResourcePromise { + return new JavaScriptAppResourcePromise(this._promise.then(obj => obj.publishAsDockerFile())); + } + + /** Publishes an executable as a Docker file with optional container configuration */ + publishAsDockerFileWithConfigure(configure: (obj: ContainerResource) => Promise): JavaScriptAppResourcePromise { + return new JavaScriptAppResourcePromise(this._promise.then(obj => obj.publishAsDockerFileWithConfigure(configure))); + } + + /** Sets the executable command */ + withExecutableCommand(command: string): JavaScriptAppResourcePromise { + return new JavaScriptAppResourcePromise(this._promise.then(obj => obj.withExecutableCommand(command))); + } + + /** Sets the executable working directory */ + withWorkingDirectory(workingDirectory: string): JavaScriptAppResourcePromise { + return new JavaScriptAppResourcePromise(this._promise.then(obj => obj.withWorkingDirectory(workingDirectory))); + } + + /** Configures an MCP server endpoint on the resource */ + withMcpServer(options?: WithMcpServerOptions): JavaScriptAppResourcePromise { + return new JavaScriptAppResourcePromise(this._promise.then(obj => obj.withMcpServer(options))); + } + + /** Configures OTLP telemetry export */ + withOtlpExporter(): JavaScriptAppResourcePromise { + return new JavaScriptAppResourcePromise(this._promise.then(obj => obj.withOtlpExporter())); + } + + /** Configures OTLP telemetry export with specific protocol */ + withOtlpExporterProtocol(protocol: OtlpProtocol): JavaScriptAppResourcePromise { + return new JavaScriptAppResourcePromise(this._promise.then(obj => obj.withOtlpExporterProtocol(protocol))); + } + + /** Adds a required command dependency */ + withRequiredCommand(command: string, options?: WithRequiredCommandOptions): JavaScriptAppResourcePromise { + return new JavaScriptAppResourcePromise(this._promise.then(obj => obj.withRequiredCommand(command, options))); + } + + /** Sets an environment variable */ + withEnvironment(name: string, value: string): JavaScriptAppResourcePromise { + return new JavaScriptAppResourcePromise(this._promise.then(obj => obj.withEnvironment(name, value))); + } + + /** Adds an environment variable with a reference expression */ + withEnvironmentExpression(name: string, value: ReferenceExpression): JavaScriptAppResourcePromise { + return new JavaScriptAppResourcePromise(this._promise.then(obj => obj.withEnvironmentExpression(name, value))); + } + + /** Sets environment variables via callback */ + withEnvironmentCallback(callback: (obj: EnvironmentCallbackContext) => Promise): JavaScriptAppResourcePromise { + return new JavaScriptAppResourcePromise(this._promise.then(obj => obj.withEnvironmentCallback(callback))); + } + + /** Sets environment variables via async callback */ + withEnvironmentCallbackAsync(callback: (arg: EnvironmentCallbackContext) => Promise): JavaScriptAppResourcePromise { + return new JavaScriptAppResourcePromise(this._promise.then(obj => obj.withEnvironmentCallbackAsync(callback))); + } + + /** Sets an environment variable from an endpoint reference */ + withEnvironmentEndpoint(name: string, endpointReference: EndpointReference): JavaScriptAppResourcePromise { + return new JavaScriptAppResourcePromise(this._promise.then(obj => obj.withEnvironmentEndpoint(name, endpointReference))); + } + + /** Sets an environment variable from a parameter resource */ + withEnvironmentParameter(name: string, parameter: ParameterResource): JavaScriptAppResourcePromise { + return new JavaScriptAppResourcePromise(this._promise.then(obj => obj.withEnvironmentParameter(name, parameter))); + } + + /** Sets an environment variable from a connection string resource */ + withEnvironmentConnectionString(envVarName: string, resource: ResourceBuilderBase): JavaScriptAppResourcePromise { + return new JavaScriptAppResourcePromise(this._promise.then(obj => obj.withEnvironmentConnectionString(envVarName, resource))); + } + + /** Adds arguments */ + withArgs(args: string[]): JavaScriptAppResourcePromise { + return new JavaScriptAppResourcePromise(this._promise.then(obj => obj.withArgs(args))); + } + + /** Sets command-line arguments via callback */ + withArgsCallback(callback: (obj: CommandLineArgsCallbackContext) => Promise): JavaScriptAppResourcePromise { + return new JavaScriptAppResourcePromise(this._promise.then(obj => obj.withArgsCallback(callback))); + } + + /** Sets command-line arguments via async callback */ + withArgsCallbackAsync(callback: (arg: CommandLineArgsCallbackContext) => Promise): JavaScriptAppResourcePromise { + return new JavaScriptAppResourcePromise(this._promise.then(obj => obj.withArgsCallbackAsync(callback))); + } + + /** Adds a reference to another resource */ + withReference(source: ResourceBuilderBase, options?: WithReferenceOptions): JavaScriptAppResourcePromise { + return new JavaScriptAppResourcePromise(this._promise.then(obj => obj.withReference(source, options))); + } + + /** Adds a service discovery reference to another resource */ + withServiceReference(source: ResourceBuilderBase): JavaScriptAppResourcePromise { + return new JavaScriptAppResourcePromise(this._promise.then(obj => obj.withServiceReference(source))); + } + + /** Adds a named service discovery reference */ + withServiceReferenceNamed(source: ResourceBuilderBase, name: string): JavaScriptAppResourcePromise { + return new JavaScriptAppResourcePromise(this._promise.then(obj => obj.withServiceReferenceNamed(source, name))); + } + + /** Adds a reference to a URI */ + withReferenceUri(name: string, uri: string): JavaScriptAppResourcePromise { + return new JavaScriptAppResourcePromise(this._promise.then(obj => obj.withReferenceUri(name, uri))); + } + + /** Adds a reference to an external service */ + withReferenceExternalService(externalService: ExternalServiceResource): JavaScriptAppResourcePromise { + return new JavaScriptAppResourcePromise(this._promise.then(obj => obj.withReferenceExternalService(externalService))); + } + + /** Adds a reference to an endpoint */ + withReferenceEndpoint(endpointReference: EndpointReference): JavaScriptAppResourcePromise { + return new JavaScriptAppResourcePromise(this._promise.then(obj => obj.withReferenceEndpoint(endpointReference))); + } + + /** Adds a network endpoint */ + withEndpoint(options?: WithEndpointOptions): JavaScriptAppResourcePromise { + return new JavaScriptAppResourcePromise(this._promise.then(obj => obj.withEndpoint(options))); + } + + /** Adds an HTTP endpoint */ + withHttpEndpoint(options?: WithHttpEndpointOptions): JavaScriptAppResourcePromise { + return new JavaScriptAppResourcePromise(this._promise.then(obj => obj.withHttpEndpoint(options))); + } + + /** Adds an HTTPS endpoint */ + withHttpsEndpoint(options?: WithHttpsEndpointOptions): JavaScriptAppResourcePromise { + return new JavaScriptAppResourcePromise(this._promise.then(obj => obj.withHttpsEndpoint(options))); + } + + /** Makes HTTP endpoints externally accessible */ + withExternalHttpEndpoints(): JavaScriptAppResourcePromise { + return new JavaScriptAppResourcePromise(this._promise.then(obj => obj.withExternalHttpEndpoints())); + } + + /** Gets an endpoint reference */ + getEndpoint(name: string): Promise { + return this._promise.then(obj => obj.getEndpoint(name)); + } + + /** Configures resource for HTTP/2 */ + asHttp2Service(): JavaScriptAppResourcePromise { + return new JavaScriptAppResourcePromise(this._promise.then(obj => obj.asHttp2Service())); + } + + /** Customizes displayed URLs via callback */ + withUrlsCallback(callback: (obj: ResourceUrlsCallbackContext) => Promise): JavaScriptAppResourcePromise { + return new JavaScriptAppResourcePromise(this._promise.then(obj => obj.withUrlsCallback(callback))); + } + + /** Customizes displayed URLs via async callback */ + withUrlsCallbackAsync(callback: (arg: ResourceUrlsCallbackContext) => Promise): JavaScriptAppResourcePromise { + return new JavaScriptAppResourcePromise(this._promise.then(obj => obj.withUrlsCallbackAsync(callback))); + } + + /** Adds or modifies displayed URLs */ + withUrl(url: string, options?: WithUrlOptions): JavaScriptAppResourcePromise { + return new JavaScriptAppResourcePromise(this._promise.then(obj => obj.withUrl(url, options))); + } + + /** Adds a URL using a reference expression */ + withUrlExpression(url: ReferenceExpression, options?: WithUrlExpressionOptions): JavaScriptAppResourcePromise { + return new JavaScriptAppResourcePromise(this._promise.then(obj => obj.withUrlExpression(url, options))); + } + + /** Customizes the URL for a specific endpoint via callback */ + withUrlForEndpoint(endpointName: string, callback: (obj: ResourceUrlAnnotation) => Promise): JavaScriptAppResourcePromise { + return new JavaScriptAppResourcePromise(this._promise.then(obj => obj.withUrlForEndpoint(endpointName, callback))); + } + + /** Adds a URL for a specific endpoint via factory callback */ + withUrlForEndpointFactory(endpointName: string, callback: (arg: EndpointReference) => Promise): JavaScriptAppResourcePromise { + return new JavaScriptAppResourcePromise(this._promise.then(obj => obj.withUrlForEndpointFactory(endpointName, callback))); + } + + /** Sets the source directory for container files */ + withContainerFilesSource(sourcePath: string): JavaScriptAppResourcePromise { + return new JavaScriptAppResourcePromise(this._promise.then(obj => obj.withContainerFilesSource(sourcePath))); + } + + /** Clears all container file sources */ + clearContainerFilesSources(): JavaScriptAppResourcePromise { + return new JavaScriptAppResourcePromise(this._promise.then(obj => obj.clearContainerFilesSources())); + } + + /** Excludes the resource from the deployment manifest */ + excludeFromManifest(): JavaScriptAppResourcePromise { + return new JavaScriptAppResourcePromise(this._promise.then(obj => obj.excludeFromManifest())); + } + + /** Waits for another resource to be ready */ + waitFor(dependency: ResourceBuilderBase): JavaScriptAppResourcePromise { + return new JavaScriptAppResourcePromise(this._promise.then(obj => obj.waitFor(dependency))); + } + + /** Waits for another resource with specific behavior */ + waitForWithBehavior(dependency: ResourceBuilderBase, waitBehavior: WaitBehavior): JavaScriptAppResourcePromise { + return new JavaScriptAppResourcePromise(this._promise.then(obj => obj.waitForWithBehavior(dependency, waitBehavior))); + } + + /** Waits for another resource to start */ + waitForStart(dependency: ResourceBuilderBase): JavaScriptAppResourcePromise { + return new JavaScriptAppResourcePromise(this._promise.then(obj => obj.waitForStart(dependency))); + } + + /** Waits for another resource to start with specific behavior */ + waitForStartWithBehavior(dependency: ResourceBuilderBase, waitBehavior: WaitBehavior): JavaScriptAppResourcePromise { + return new JavaScriptAppResourcePromise(this._promise.then(obj => obj.waitForStartWithBehavior(dependency, waitBehavior))); + } + + /** Prevents resource from starting automatically */ + withExplicitStart(): JavaScriptAppResourcePromise { + return new JavaScriptAppResourcePromise(this._promise.then(obj => obj.withExplicitStart())); + } + + /** Waits for resource completion */ + waitForCompletion(dependency: ResourceBuilderBase, options?: WaitForCompletionOptions): JavaScriptAppResourcePromise { + return new JavaScriptAppResourcePromise(this._promise.then(obj => obj.waitForCompletion(dependency, options))); + } + + /** Adds a health check by key */ + withHealthCheck(key: string): JavaScriptAppResourcePromise { + return new JavaScriptAppResourcePromise(this._promise.then(obj => obj.withHealthCheck(key))); + } + + /** Adds an HTTP health check */ + withHttpHealthCheck(options?: WithHttpHealthCheckOptions): JavaScriptAppResourcePromise { + return new JavaScriptAppResourcePromise(this._promise.then(obj => obj.withHttpHealthCheck(options))); + } + + /** Adds a resource command */ + withCommand(name: string, displayName: string, executeCommand: (arg: ExecuteCommandContext) => Promise, options?: WithCommandOptions): JavaScriptAppResourcePromise { + return new JavaScriptAppResourcePromise(this._promise.then(obj => obj.withCommand(name, displayName, executeCommand, options))); + } + + /** Configures developer certificate trust */ + withDeveloperCertificateTrust(trust: boolean): JavaScriptAppResourcePromise { + return new JavaScriptAppResourcePromise(this._promise.then(obj => obj.withDeveloperCertificateTrust(trust))); + } + + /** Sets the certificate trust scope */ + withCertificateTrustScope(scope: CertificateTrustScope): JavaScriptAppResourcePromise { + return new JavaScriptAppResourcePromise(this._promise.then(obj => obj.withCertificateTrustScope(scope))); + } + + /** Configures HTTPS with a developer certificate */ + withHttpsDeveloperCertificate(options?: WithHttpsDeveloperCertificateOptions): JavaScriptAppResourcePromise { + return new JavaScriptAppResourcePromise(this._promise.then(obj => obj.withHttpsDeveloperCertificate(options))); + } + + /** Removes HTTPS certificate configuration */ + withoutHttpsCertificate(): JavaScriptAppResourcePromise { + return new JavaScriptAppResourcePromise(this._promise.then(obj => obj.withoutHttpsCertificate())); + } + + /** Sets the parent relationship */ + withParentRelationship(parent: ResourceBuilderBase): JavaScriptAppResourcePromise { + return new JavaScriptAppResourcePromise(this._promise.then(obj => obj.withParentRelationship(parent))); + } + + /** Sets a child relationship */ + withChildRelationship(child: ResourceBuilderBase): JavaScriptAppResourcePromise { + return new JavaScriptAppResourcePromise(this._promise.then(obj => obj.withChildRelationship(child))); + } + + /** Sets the icon for the resource */ + withIconName(iconName: string, options?: WithIconNameOptions): JavaScriptAppResourcePromise { + return new JavaScriptAppResourcePromise(this._promise.then(obj => obj.withIconName(iconName, options))); + } + + /** Adds an HTTP health probe to the resource */ + withHttpProbe(probeType: ProbeType, options?: WithHttpProbeOptions): JavaScriptAppResourcePromise { + return new JavaScriptAppResourcePromise(this._promise.then(obj => obj.withHttpProbe(probeType, options))); + } + + /** Excludes the resource from MCP server exposure */ + excludeFromMcp(): JavaScriptAppResourcePromise { + return new JavaScriptAppResourcePromise(this._promise.then(obj => obj.excludeFromMcp())); + } + + /** Sets the remote image name for publishing */ + withRemoteImageName(remoteImageName: string): JavaScriptAppResourcePromise { + return new JavaScriptAppResourcePromise(this._promise.then(obj => obj.withRemoteImageName(remoteImageName))); + } + + /** Sets the remote image tag for publishing */ + withRemoteImageTag(remoteImageTag: string): JavaScriptAppResourcePromise { + return new JavaScriptAppResourcePromise(this._promise.then(obj => obj.withRemoteImageTag(remoteImageTag))); + } + + /** Adds a pipeline step to the resource */ + withPipelineStepFactory(stepName: string, callback: (arg: PipelineStepContext) => Promise, options?: WithPipelineStepFactoryOptions): JavaScriptAppResourcePromise { + return new JavaScriptAppResourcePromise(this._promise.then(obj => obj.withPipelineStepFactory(stepName, callback, options))); + } + + /** Configures pipeline step dependencies via an async callback */ + withPipelineConfigurationAsync(callback: (arg: PipelineConfigurationContext) => Promise): JavaScriptAppResourcePromise { + return new JavaScriptAppResourcePromise(this._promise.then(obj => obj.withPipelineConfigurationAsync(callback))); + } + + /** Configures pipeline step dependencies via a callback */ + withPipelineConfiguration(callback: (obj: PipelineConfigurationContext) => Promise): JavaScriptAppResourcePromise { + return new JavaScriptAppResourcePromise(this._promise.then(obj => obj.withPipelineConfiguration(callback))); + } + + /** Gets the resource name */ + getResourceName(): Promise { + return this._promise.then(obj => obj.getResourceName()); + } + + /** Assigns Azure Storage roles to a resource */ + withStorageRoleAssignments(target: AzureStorageResource, roles: AzureStorageRole[]): JavaScriptAppResourcePromise { + return new JavaScriptAppResourcePromise(this._promise.then(obj => obj.withStorageRoleAssignments(target, roles))); + } + + /** Assigns Event Hubs roles to a resource */ + withEventHubsRoleAssignments(target: AzureEventHubsResource, roles: AzureEventHubsRole[]): JavaScriptAppResourcePromise { + return new JavaScriptAppResourcePromise(this._promise.then(obj => obj.withEventHubsRoleAssignments(target, roles))); + } + + /** Sets an environment variable from a Bicep output reference */ + withEnvironmentFromOutput(name: string, bicepOutputReference: BicepOutputReference): JavaScriptAppResourcePromise { + return new JavaScriptAppResourcePromise(this._promise.then(obj => obj.withEnvironmentFromOutput(name, bicepOutputReference))); + } + + /** Sets an environment variable from an Azure Key Vault secret reference */ + withEnvironmentFromKeyVaultSecret(name: string, secretReference: ResourceBuilderBase): JavaScriptAppResourcePromise { + return new JavaScriptAppResourcePromise(this._promise.then(obj => obj.withEnvironmentFromKeyVaultSecret(name, secretReference))); + } + + /** Associates an Azure user-assigned identity with a compute resource */ + withAzureUserAssignedIdentity(identityResourceBuilder: AzureUserAssignedIdentityResource): JavaScriptAppResourcePromise { + return new JavaScriptAppResourcePromise(this._promise.then(obj => obj.withAzureUserAssignedIdentity(identityResourceBuilder))); + } + +} + +// ============================================================================ +// NodeAppResource +// ============================================================================ + +export class NodeAppResource extends ResourceBuilderBase { + constructor(handle: NodeAppResourceHandle, client: AspireClientRpc) { + super(handle, client); + } + + /** Gets the Command property */ + command = { + get: async (): Promise => { + return await this._client.invokeCapability( + 'Aspire.Hosting.JavaScript/JavaScriptAppResource.command', + { context: this._handle } + ); + }, + }; + + /** Gets the WorkingDirectory property */ + workingDirectory = { + get: async (): Promise => { + return await this._client.invokeCapability( + 'Aspire.Hosting.JavaScript/JavaScriptAppResource.workingDirectory', + { context: this._handle } + ); + }, + }; + + /** Gets the Name property */ + name = { + get: async (): Promise => { + return await this._client.invokeCapability( + 'Aspire.Hosting.JavaScript/JavaScriptAppResource.name', + { context: this._handle } + ); + }, + }; + + /** @internal */ + private async _withContainerRegistryInternal(registry: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, registry }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withContainerRegistry', + rpcArgs + ); + return new NodeAppResource(result, this._client); + } + + /** Configures a resource to use a container registry */ + withContainerRegistry(registry: ResourceBuilderBase): NodeAppResourcePromise { + return new NodeAppResourcePromise(this._withContainerRegistryInternal(registry)); + } + + /** @internal */ + private async _withDockerfileBaseImageInternal(buildImage?: string, runtimeImage?: string): Promise { + const rpcArgs: Record = { builder: this._handle }; + if (buildImage !== undefined) rpcArgs.buildImage = buildImage; + if (runtimeImage !== undefined) rpcArgs.runtimeImage = runtimeImage; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withDockerfileBaseImage', + rpcArgs + ); + return new NodeAppResource(result, this._client); + } + + /** Sets the base image for a Dockerfile build */ + withDockerfileBaseImage(options?: WithDockerfileBaseImageOptions): NodeAppResourcePromise { + const buildImage = options?.buildImage; + const runtimeImage = options?.runtimeImage; + return new NodeAppResourcePromise(this._withDockerfileBaseImageInternal(buildImage, runtimeImage)); + } + + /** @internal */ + private async _publishAsDockerFileInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/publishAsDockerFile', + rpcArgs + ); + return new NodeAppResource(result, this._client); + } + + /** Publishes the executable as a Docker container */ + publishAsDockerFile(): NodeAppResourcePromise { + return new NodeAppResourcePromise(this._publishAsDockerFileInternal()); + } + + /** @internal */ + private async _publishAsDockerFileWithConfigureInternal(configure: (obj: ContainerResource) => Promise): Promise { + const configureId = registerCallback(async (objData: unknown) => { + const objHandle = wrapIfHandle(objData) as ContainerResourceHandle; + const obj = new ContainerResource(objHandle, this._client); + await configure(obj); + }); + const rpcArgs: Record = { builder: this._handle, configure: configureId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/publishAsDockerFileWithConfigure', + rpcArgs + ); + return new NodeAppResource(result, this._client); + } + + /** Publishes an executable as a Docker file with optional container configuration */ + publishAsDockerFileWithConfigure(configure: (obj: ContainerResource) => Promise): NodeAppResourcePromise { + return new NodeAppResourcePromise(this._publishAsDockerFileWithConfigureInternal(configure)); + } + + /** @internal */ + private async _withExecutableCommandInternal(command: string): Promise { + const rpcArgs: Record = { builder: this._handle, command }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withExecutableCommand', + rpcArgs + ); + return new NodeAppResource(result, this._client); + } + + /** Sets the executable command */ + withExecutableCommand(command: string): NodeAppResourcePromise { + return new NodeAppResourcePromise(this._withExecutableCommandInternal(command)); + } + + /** @internal */ + private async _withWorkingDirectoryInternal(workingDirectory: string): Promise { + const rpcArgs: Record = { builder: this._handle, workingDirectory }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withWorkingDirectory', + rpcArgs + ); + return new NodeAppResource(result, this._client); + } + + /** Sets the executable working directory */ + withWorkingDirectory(workingDirectory: string): NodeAppResourcePromise { + return new NodeAppResourcePromise(this._withWorkingDirectoryInternal(workingDirectory)); + } + + /** @internal */ + private async _withMcpServerInternal(path?: string, endpointName?: string): Promise { + const rpcArgs: Record = { builder: this._handle }; + if (path !== undefined) rpcArgs.path = path; + if (endpointName !== undefined) rpcArgs.endpointName = endpointName; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withMcpServer', + rpcArgs + ); + return new NodeAppResource(result, this._client); + } + + /** Configures an MCP server endpoint on the resource */ + withMcpServer(options?: WithMcpServerOptions): NodeAppResourcePromise { + const path = options?.path; + const endpointName = options?.endpointName; + return new NodeAppResourcePromise(this._withMcpServerInternal(path, endpointName)); + } + + /** @internal */ + private async _withOtlpExporterInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withOtlpExporter', + rpcArgs + ); + return new NodeAppResource(result, this._client); + } + + /** Configures OTLP telemetry export */ + withOtlpExporter(): NodeAppResourcePromise { + return new NodeAppResourcePromise(this._withOtlpExporterInternal()); + } + + /** @internal */ + private async _withOtlpExporterProtocolInternal(protocol: OtlpProtocol): Promise { + const rpcArgs: Record = { builder: this._handle, protocol }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withOtlpExporterProtocol', + rpcArgs + ); + return new NodeAppResource(result, this._client); + } + + /** Configures OTLP telemetry export with specific protocol */ + withOtlpExporterProtocol(protocol: OtlpProtocol): NodeAppResourcePromise { + return new NodeAppResourcePromise(this._withOtlpExporterProtocolInternal(protocol)); + } + + /** @internal */ + private async _withRequiredCommandInternal(command: string, helpLink?: string): Promise { + const rpcArgs: Record = { builder: this._handle, command }; + if (helpLink !== undefined) rpcArgs.helpLink = helpLink; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withRequiredCommand', + rpcArgs + ); + return new NodeAppResource(result, this._client); + } + + /** Adds a required command dependency */ + withRequiredCommand(command: string, options?: WithRequiredCommandOptions): NodeAppResourcePromise { + const helpLink = options?.helpLink; + return new NodeAppResourcePromise(this._withRequiredCommandInternal(command, helpLink)); + } + + /** @internal */ + private async _withEnvironmentInternal(name: string, value: string): Promise { + const rpcArgs: Record = { builder: this._handle, name, value }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withEnvironment', + rpcArgs + ); + return new NodeAppResource(result, this._client); + } + + /** Sets an environment variable */ + withEnvironment(name: string, value: string): NodeAppResourcePromise { + return new NodeAppResourcePromise(this._withEnvironmentInternal(name, value)); + } + + /** @internal */ + private async _withEnvironmentExpressionInternal(name: string, value: ReferenceExpression): Promise { + const rpcArgs: Record = { builder: this._handle, name, value }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withEnvironmentExpression', + rpcArgs + ); + return new NodeAppResource(result, this._client); + } + + /** Adds an environment variable with a reference expression */ + withEnvironmentExpression(name: string, value: ReferenceExpression): NodeAppResourcePromise { + return new NodeAppResourcePromise(this._withEnvironmentExpressionInternal(name, value)); + } + + /** @internal */ + private async _withEnvironmentCallbackInternal(callback: (obj: EnvironmentCallbackContext) => Promise): Promise { + const callbackId = registerCallback(async (objData: unknown) => { + const objHandle = wrapIfHandle(objData) as EnvironmentCallbackContextHandle; + const obj = new EnvironmentCallbackContext(objHandle, this._client); + await callback(obj); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withEnvironmentCallback', + rpcArgs + ); + return new NodeAppResource(result, this._client); + } + + /** Sets environment variables via callback */ + withEnvironmentCallback(callback: (obj: EnvironmentCallbackContext) => Promise): NodeAppResourcePromise { + return new NodeAppResourcePromise(this._withEnvironmentCallbackInternal(callback)); + } + + /** @internal */ + private async _withEnvironmentCallbackAsyncInternal(callback: (arg: EnvironmentCallbackContext) => Promise): Promise { + const callbackId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as EnvironmentCallbackContextHandle; + const arg = new EnvironmentCallbackContext(argHandle, this._client); + await callback(arg); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withEnvironmentCallbackAsync', + rpcArgs + ); + return new NodeAppResource(result, this._client); + } + + /** Sets environment variables via async callback */ + withEnvironmentCallbackAsync(callback: (arg: EnvironmentCallbackContext) => Promise): NodeAppResourcePromise { + return new NodeAppResourcePromise(this._withEnvironmentCallbackAsyncInternal(callback)); + } + + /** @internal */ + private async _withEnvironmentEndpointInternal(name: string, endpointReference: EndpointReference): Promise { + const rpcArgs: Record = { builder: this._handle, name, endpointReference }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withEnvironmentEndpoint', + rpcArgs + ); + return new NodeAppResource(result, this._client); + } + + /** Sets an environment variable from an endpoint reference */ + withEnvironmentEndpoint(name: string, endpointReference: EndpointReference): NodeAppResourcePromise { + return new NodeAppResourcePromise(this._withEnvironmentEndpointInternal(name, endpointReference)); + } + + /** @internal */ + private async _withEnvironmentParameterInternal(name: string, parameter: ParameterResource): Promise { + const rpcArgs: Record = { builder: this._handle, name, parameter }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withEnvironmentParameter', + rpcArgs + ); + return new NodeAppResource(result, this._client); + } + + /** Sets an environment variable from a parameter resource */ + withEnvironmentParameter(name: string, parameter: ParameterResource): NodeAppResourcePromise { + return new NodeAppResourcePromise(this._withEnvironmentParameterInternal(name, parameter)); + } + + /** @internal */ + private async _withEnvironmentConnectionStringInternal(envVarName: string, resource: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, envVarName, resource }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withEnvironmentConnectionString', + rpcArgs + ); + return new NodeAppResource(result, this._client); + } + + /** Sets an environment variable from a connection string resource */ + withEnvironmentConnectionString(envVarName: string, resource: ResourceBuilderBase): NodeAppResourcePromise { + return new NodeAppResourcePromise(this._withEnvironmentConnectionStringInternal(envVarName, resource)); + } + + /** @internal */ + private async _withArgsInternal(args: string[]): Promise { + const rpcArgs: Record = { builder: this._handle, args }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withArgs', + rpcArgs + ); + return new NodeAppResource(result, this._client); + } + + /** Adds arguments */ + withArgs(args: string[]): NodeAppResourcePromise { + return new NodeAppResourcePromise(this._withArgsInternal(args)); + } + + /** @internal */ + private async _withArgsCallbackInternal(callback: (obj: CommandLineArgsCallbackContext) => Promise): Promise { + const callbackId = registerCallback(async (objData: unknown) => { + const objHandle = wrapIfHandle(objData) as CommandLineArgsCallbackContextHandle; + const obj = new CommandLineArgsCallbackContext(objHandle, this._client); + await callback(obj); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withArgsCallback', + rpcArgs + ); + return new NodeAppResource(result, this._client); + } + + /** Sets command-line arguments via callback */ + withArgsCallback(callback: (obj: CommandLineArgsCallbackContext) => Promise): NodeAppResourcePromise { + return new NodeAppResourcePromise(this._withArgsCallbackInternal(callback)); + } + + /** @internal */ + private async _withArgsCallbackAsyncInternal(callback: (arg: CommandLineArgsCallbackContext) => Promise): Promise { + const callbackId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as CommandLineArgsCallbackContextHandle; + const arg = new CommandLineArgsCallbackContext(argHandle, this._client); + await callback(arg); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withArgsCallbackAsync', + rpcArgs + ); + return new NodeAppResource(result, this._client); + } + + /** Sets command-line arguments via async callback */ + withArgsCallbackAsync(callback: (arg: CommandLineArgsCallbackContext) => Promise): NodeAppResourcePromise { + return new NodeAppResourcePromise(this._withArgsCallbackAsyncInternal(callback)); + } + + /** @internal */ + private async _withReferenceInternal(source: ResourceBuilderBase, connectionName?: string, optional?: boolean): Promise { + const rpcArgs: Record = { builder: this._handle, source }; + if (connectionName !== undefined) rpcArgs.connectionName = connectionName; + if (optional !== undefined) rpcArgs.optional = optional; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withReference', + rpcArgs + ); + return new NodeAppResource(result, this._client); + } + + /** Adds a reference to another resource */ + withReference(source: ResourceBuilderBase, options?: WithReferenceOptions): NodeAppResourcePromise { + const connectionName = options?.connectionName; + const optional = options?.optional; + return new NodeAppResourcePromise(this._withReferenceInternal(source, connectionName, optional)); + } + + /** @internal */ + private async _withServiceReferenceInternal(source: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, source }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withServiceReference', + rpcArgs + ); + return new NodeAppResource(result, this._client); + } + + /** Adds a service discovery reference to another resource */ + withServiceReference(source: ResourceBuilderBase): NodeAppResourcePromise { + return new NodeAppResourcePromise(this._withServiceReferenceInternal(source)); + } + + /** @internal */ + private async _withServiceReferenceNamedInternal(source: ResourceBuilderBase, name: string): Promise { + const rpcArgs: Record = { builder: this._handle, source, name }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withServiceReferenceNamed', + rpcArgs + ); + return new NodeAppResource(result, this._client); + } + + /** Adds a named service discovery reference */ + withServiceReferenceNamed(source: ResourceBuilderBase, name: string): NodeAppResourcePromise { + return new NodeAppResourcePromise(this._withServiceReferenceNamedInternal(source, name)); + } + + /** @internal */ + private async _withReferenceUriInternal(name: string, uri: string): Promise { + const rpcArgs: Record = { builder: this._handle, name, uri }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withReferenceUri', + rpcArgs + ); + return new NodeAppResource(result, this._client); + } + + /** Adds a reference to a URI */ + withReferenceUri(name: string, uri: string): NodeAppResourcePromise { + return new NodeAppResourcePromise(this._withReferenceUriInternal(name, uri)); + } + + /** @internal */ + private async _withReferenceExternalServiceInternal(externalService: ExternalServiceResource): Promise { + const rpcArgs: Record = { builder: this._handle, externalService }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withReferenceExternalService', + rpcArgs + ); + return new NodeAppResource(result, this._client); + } + + /** Adds a reference to an external service */ + withReferenceExternalService(externalService: ExternalServiceResource): NodeAppResourcePromise { + return new NodeAppResourcePromise(this._withReferenceExternalServiceInternal(externalService)); + } + + /** @internal */ + private async _withReferenceEndpointInternal(endpointReference: EndpointReference): Promise { + const rpcArgs: Record = { builder: this._handle, endpointReference }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withReferenceEndpoint', + rpcArgs + ); + return new NodeAppResource(result, this._client); + } + + /** Adds a reference to an endpoint */ + withReferenceEndpoint(endpointReference: EndpointReference): NodeAppResourcePromise { + return new NodeAppResourcePromise(this._withReferenceEndpointInternal(endpointReference)); + } + + /** @internal */ + private async _withEndpointInternal(port?: number, targetPort?: number, scheme?: string, name?: string, env?: string, isProxied?: boolean, isExternal?: boolean, protocol?: ProtocolType): Promise { + const rpcArgs: Record = { builder: this._handle }; + if (port !== undefined) rpcArgs.port = port; + if (targetPort !== undefined) rpcArgs.targetPort = targetPort; + if (scheme !== undefined) rpcArgs.scheme = scheme; + if (name !== undefined) rpcArgs.name = name; + if (env !== undefined) rpcArgs.env = env; + if (isProxied !== undefined) rpcArgs.isProxied = isProxied; + if (isExternal !== undefined) rpcArgs.isExternal = isExternal; + if (protocol !== undefined) rpcArgs.protocol = protocol; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withEndpoint', + rpcArgs + ); + return new NodeAppResource(result, this._client); + } + + /** Adds a network endpoint */ + withEndpoint(options?: WithEndpointOptions): NodeAppResourcePromise { + const port = options?.port; + const targetPort = options?.targetPort; + const scheme = options?.scheme; + const name = options?.name; + const env = options?.env; + const isProxied = options?.isProxied; + const isExternal = options?.isExternal; + const protocol = options?.protocol; + return new NodeAppResourcePromise(this._withEndpointInternal(port, targetPort, scheme, name, env, isProxied, isExternal, protocol)); + } + + /** @internal */ + private async _withHttpEndpointInternal(port?: number, targetPort?: number, name?: string, env?: string, isProxied?: boolean): Promise { + const rpcArgs: Record = { builder: this._handle }; + if (port !== undefined) rpcArgs.port = port; + if (targetPort !== undefined) rpcArgs.targetPort = targetPort; + if (name !== undefined) rpcArgs.name = name; + if (env !== undefined) rpcArgs.env = env; + if (isProxied !== undefined) rpcArgs.isProxied = isProxied; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withHttpEndpoint', + rpcArgs + ); + return new NodeAppResource(result, this._client); + } + + /** Adds an HTTP endpoint */ + withHttpEndpoint(options?: WithHttpEndpointOptions): NodeAppResourcePromise { + const port = options?.port; + const targetPort = options?.targetPort; + const name = options?.name; + const env = options?.env; + const isProxied = options?.isProxied; + return new NodeAppResourcePromise(this._withHttpEndpointInternal(port, targetPort, name, env, isProxied)); + } + + /** @internal */ + private async _withHttpsEndpointInternal(port?: number, targetPort?: number, name?: string, env?: string, isProxied?: boolean): Promise { + const rpcArgs: Record = { builder: this._handle }; + if (port !== undefined) rpcArgs.port = port; + if (targetPort !== undefined) rpcArgs.targetPort = targetPort; + if (name !== undefined) rpcArgs.name = name; + if (env !== undefined) rpcArgs.env = env; + if (isProxied !== undefined) rpcArgs.isProxied = isProxied; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withHttpsEndpoint', + rpcArgs + ); + return new NodeAppResource(result, this._client); + } + + /** Adds an HTTPS endpoint */ + withHttpsEndpoint(options?: WithHttpsEndpointOptions): NodeAppResourcePromise { + const port = options?.port; + const targetPort = options?.targetPort; + const name = options?.name; + const env = options?.env; + const isProxied = options?.isProxied; + return new NodeAppResourcePromise(this._withHttpsEndpointInternal(port, targetPort, name, env, isProxied)); + } + + /** @internal */ + private async _withExternalHttpEndpointsInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withExternalHttpEndpoints', + rpcArgs + ); + return new NodeAppResource(result, this._client); + } + + /** Makes HTTP endpoints externally accessible */ + withExternalHttpEndpoints(): NodeAppResourcePromise { + return new NodeAppResourcePromise(this._withExternalHttpEndpointsInternal()); + } + + /** Gets an endpoint reference */ + async getEndpoint(name: string): Promise { + const rpcArgs: Record = { builder: this._handle, name }; + return await this._client.invokeCapability( + 'Aspire.Hosting/getEndpoint', + rpcArgs + ); + } + + /** @internal */ + private async _asHttp2ServiceInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/asHttp2Service', + rpcArgs + ); + return new NodeAppResource(result, this._client); + } + + /** Configures resource for HTTP/2 */ + asHttp2Service(): NodeAppResourcePromise { + return new NodeAppResourcePromise(this._asHttp2ServiceInternal()); + } + + /** @internal */ + private async _withUrlsCallbackInternal(callback: (obj: ResourceUrlsCallbackContext) => Promise): Promise { + const callbackId = registerCallback(async (objData: unknown) => { + const objHandle = wrapIfHandle(objData) as ResourceUrlsCallbackContextHandle; + const obj = new ResourceUrlsCallbackContext(objHandle, this._client); + await callback(obj); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrlsCallback', + rpcArgs + ); + return new NodeAppResource(result, this._client); + } + + /** Customizes displayed URLs via callback */ + withUrlsCallback(callback: (obj: ResourceUrlsCallbackContext) => Promise): NodeAppResourcePromise { + return new NodeAppResourcePromise(this._withUrlsCallbackInternal(callback)); + } + + /** @internal */ + private async _withUrlsCallbackAsyncInternal(callback: (arg: ResourceUrlsCallbackContext) => Promise): Promise { + const callbackId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as ResourceUrlsCallbackContextHandle; + const arg = new ResourceUrlsCallbackContext(argHandle, this._client); + await callback(arg); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrlsCallbackAsync', + rpcArgs + ); + return new NodeAppResource(result, this._client); + } + + /** Customizes displayed URLs via async callback */ + withUrlsCallbackAsync(callback: (arg: ResourceUrlsCallbackContext) => Promise): NodeAppResourcePromise { + return new NodeAppResourcePromise(this._withUrlsCallbackAsyncInternal(callback)); + } + + /** @internal */ + private async _withUrlInternal(url: string, displayText?: string): Promise { + const rpcArgs: Record = { builder: this._handle, url }; + if (displayText !== undefined) rpcArgs.displayText = displayText; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrl', + rpcArgs + ); + return new NodeAppResource(result, this._client); + } + + /** Adds or modifies displayed URLs */ + withUrl(url: string, options?: WithUrlOptions): NodeAppResourcePromise { + const displayText = options?.displayText; + return new NodeAppResourcePromise(this._withUrlInternal(url, displayText)); + } + + /** @internal */ + private async _withUrlExpressionInternal(url: ReferenceExpression, displayText?: string): Promise { + const rpcArgs: Record = { builder: this._handle, url }; + if (displayText !== undefined) rpcArgs.displayText = displayText; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrlExpression', + rpcArgs + ); + return new NodeAppResource(result, this._client); + } + + /** Adds a URL using a reference expression */ + withUrlExpression(url: ReferenceExpression, options?: WithUrlExpressionOptions): NodeAppResourcePromise { + const displayText = options?.displayText; + return new NodeAppResourcePromise(this._withUrlExpressionInternal(url, displayText)); + } + + /** @internal */ + private async _withUrlForEndpointInternal(endpointName: string, callback: (obj: ResourceUrlAnnotation) => Promise): Promise { + const callbackId = registerCallback(async (objData: unknown) => { + const obj = wrapIfHandle(objData) as ResourceUrlAnnotation; + await callback(obj); + }); + const rpcArgs: Record = { builder: this._handle, endpointName, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrlForEndpoint', + rpcArgs + ); + return new NodeAppResource(result, this._client); + } + + /** Customizes the URL for a specific endpoint via callback */ + withUrlForEndpoint(endpointName: string, callback: (obj: ResourceUrlAnnotation) => Promise): NodeAppResourcePromise { + return new NodeAppResourcePromise(this._withUrlForEndpointInternal(endpointName, callback)); + } + + /** @internal */ + private async _withUrlForEndpointFactoryInternal(endpointName: string, callback: (arg: EndpointReference) => Promise): Promise { + const callbackId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as EndpointReferenceHandle; + const arg = new EndpointReference(argHandle, this._client); + return await callback(arg); + }); + const rpcArgs: Record = { builder: this._handle, endpointName, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrlForEndpointFactory', + rpcArgs + ); + return new NodeAppResource(result, this._client); + } + + /** Adds a URL for a specific endpoint via factory callback */ + withUrlForEndpointFactory(endpointName: string, callback: (arg: EndpointReference) => Promise): NodeAppResourcePromise { + return new NodeAppResourcePromise(this._withUrlForEndpointFactoryInternal(endpointName, callback)); + } + + /** @internal */ + private async _publishWithContainerFilesInternal(source: ResourceBuilderBase, destinationPath: string): Promise { + const rpcArgs: Record = { builder: this._handle, source, destinationPath }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/publishWithContainerFiles', + rpcArgs + ); + return new NodeAppResource(result, this._client); + } + + /** Configures the resource to copy container files from the specified source during publishing */ + publishWithContainerFiles(source: ResourceBuilderBase, destinationPath: string): NodeAppResourcePromise { + return new NodeAppResourcePromise(this._publishWithContainerFilesInternal(source, destinationPath)); + } + + /** @internal */ + private async _withContainerFilesSourceInternal(sourcePath: string): Promise { + const rpcArgs: Record = { builder: this._handle, sourcePath }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withContainerFilesSource', + rpcArgs + ); + return new NodeAppResource(result, this._client); + } + + /** Sets the source directory for container files */ + withContainerFilesSource(sourcePath: string): NodeAppResourcePromise { + return new NodeAppResourcePromise(this._withContainerFilesSourceInternal(sourcePath)); + } + + /** @internal */ + private async _clearContainerFilesSourcesInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/clearContainerFilesSources', + rpcArgs + ); + return new NodeAppResource(result, this._client); + } + + /** Clears all container file sources */ + clearContainerFilesSources(): NodeAppResourcePromise { + return new NodeAppResourcePromise(this._clearContainerFilesSourcesInternal()); + } + + /** @internal */ + private async _excludeFromManifestInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/excludeFromManifest', + rpcArgs + ); + return new NodeAppResource(result, this._client); + } + + /** Excludes the resource from the deployment manifest */ + excludeFromManifest(): NodeAppResourcePromise { + return new NodeAppResourcePromise(this._excludeFromManifestInternal()); + } + + /** @internal */ + private async _waitForInternal(dependency: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, dependency }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/waitFor', + rpcArgs + ); + return new NodeAppResource(result, this._client); + } + + /** Waits for another resource to be ready */ + waitFor(dependency: ResourceBuilderBase): NodeAppResourcePromise { + return new NodeAppResourcePromise(this._waitForInternal(dependency)); + } + + /** @internal */ + private async _waitForWithBehaviorInternal(dependency: ResourceBuilderBase, waitBehavior: WaitBehavior): Promise { + const rpcArgs: Record = { builder: this._handle, dependency, waitBehavior }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/waitForWithBehavior', + rpcArgs + ); + return new NodeAppResource(result, this._client); + } + + /** Waits for another resource with specific behavior */ + waitForWithBehavior(dependency: ResourceBuilderBase, waitBehavior: WaitBehavior): NodeAppResourcePromise { + return new NodeAppResourcePromise(this._waitForWithBehaviorInternal(dependency, waitBehavior)); + } + + /** @internal */ + private async _waitForStartInternal(dependency: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, dependency }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/waitForStart', + rpcArgs + ); + return new NodeAppResource(result, this._client); + } + + /** Waits for another resource to start */ + waitForStart(dependency: ResourceBuilderBase): NodeAppResourcePromise { + return new NodeAppResourcePromise(this._waitForStartInternal(dependency)); + } + + /** @internal */ + private async _waitForStartWithBehaviorInternal(dependency: ResourceBuilderBase, waitBehavior: WaitBehavior): Promise { + const rpcArgs: Record = { builder: this._handle, dependency, waitBehavior }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/waitForStartWithBehavior', + rpcArgs + ); + return new NodeAppResource(result, this._client); + } + + /** Waits for another resource to start with specific behavior */ + waitForStartWithBehavior(dependency: ResourceBuilderBase, waitBehavior: WaitBehavior): NodeAppResourcePromise { + return new NodeAppResourcePromise(this._waitForStartWithBehaviorInternal(dependency, waitBehavior)); + } + + /** @internal */ + private async _withExplicitStartInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withExplicitStart', + rpcArgs + ); + return new NodeAppResource(result, this._client); + } + + /** Prevents resource from starting automatically */ + withExplicitStart(): NodeAppResourcePromise { + return new NodeAppResourcePromise(this._withExplicitStartInternal()); + } + + /** @internal */ + private async _waitForCompletionInternal(dependency: ResourceBuilderBase, exitCode?: number): Promise { + const rpcArgs: Record = { builder: this._handle, dependency }; + if (exitCode !== undefined) rpcArgs.exitCode = exitCode; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/waitForCompletion', + rpcArgs + ); + return new NodeAppResource(result, this._client); + } + + /** Waits for resource completion */ + waitForCompletion(dependency: ResourceBuilderBase, options?: WaitForCompletionOptions): NodeAppResourcePromise { + const exitCode = options?.exitCode; + return new NodeAppResourcePromise(this._waitForCompletionInternal(dependency, exitCode)); + } + + /** @internal */ + private async _withHealthCheckInternal(key: string): Promise { + const rpcArgs: Record = { builder: this._handle, key }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withHealthCheck', + rpcArgs + ); + return new NodeAppResource(result, this._client); + } + + /** Adds a health check by key */ + withHealthCheck(key: string): NodeAppResourcePromise { + return new NodeAppResourcePromise(this._withHealthCheckInternal(key)); + } + + /** @internal */ + private async _withHttpHealthCheckInternal(path?: string, statusCode?: number, endpointName?: string): Promise { + const rpcArgs: Record = { builder: this._handle }; + if (path !== undefined) rpcArgs.path = path; + if (statusCode !== undefined) rpcArgs.statusCode = statusCode; + if (endpointName !== undefined) rpcArgs.endpointName = endpointName; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withHttpHealthCheck', + rpcArgs + ); + return new NodeAppResource(result, this._client); + } + + /** Adds an HTTP health check */ + withHttpHealthCheck(options?: WithHttpHealthCheckOptions): NodeAppResourcePromise { + const path = options?.path; + const statusCode = options?.statusCode; + const endpointName = options?.endpointName; + return new NodeAppResourcePromise(this._withHttpHealthCheckInternal(path, statusCode, endpointName)); + } + + /** @internal */ + private async _withCommandInternal(name: string, displayName: string, executeCommand: (arg: ExecuteCommandContext) => Promise, commandOptions?: CommandOptions): Promise { + const executeCommandId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as ExecuteCommandContextHandle; + const arg = new ExecuteCommandContext(argHandle, this._client); + return await executeCommand(arg); + }); + const rpcArgs: Record = { builder: this._handle, name, displayName, executeCommand: executeCommandId }; + if (commandOptions !== undefined) rpcArgs.commandOptions = commandOptions; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withCommand', + rpcArgs + ); + return new NodeAppResource(result, this._client); + } + + /** Adds a resource command */ + withCommand(name: string, displayName: string, executeCommand: (arg: ExecuteCommandContext) => Promise, options?: WithCommandOptions): NodeAppResourcePromise { + const commandOptions = options?.commandOptions; + return new NodeAppResourcePromise(this._withCommandInternal(name, displayName, executeCommand, commandOptions)); + } + + /** @internal */ + private async _withDeveloperCertificateTrustInternal(trust: boolean): Promise { + const rpcArgs: Record = { builder: this._handle, trust }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withDeveloperCertificateTrust', + rpcArgs + ); + return new NodeAppResource(result, this._client); + } + + /** Configures developer certificate trust */ + withDeveloperCertificateTrust(trust: boolean): NodeAppResourcePromise { + return new NodeAppResourcePromise(this._withDeveloperCertificateTrustInternal(trust)); + } + + /** @internal */ + private async _withCertificateTrustScopeInternal(scope: CertificateTrustScope): Promise { + const rpcArgs: Record = { builder: this._handle, scope }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withCertificateTrustScope', + rpcArgs + ); + return new NodeAppResource(result, this._client); + } + + /** Sets the certificate trust scope */ + withCertificateTrustScope(scope: CertificateTrustScope): NodeAppResourcePromise { + return new NodeAppResourcePromise(this._withCertificateTrustScopeInternal(scope)); + } + + /** @internal */ + private async _withHttpsDeveloperCertificateInternal(password?: ParameterResource): Promise { + const rpcArgs: Record = { builder: this._handle }; + if (password !== undefined) rpcArgs.password = password; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withHttpsDeveloperCertificate', + rpcArgs + ); + return new NodeAppResource(result, this._client); + } + + /** Configures HTTPS with a developer certificate */ + withHttpsDeveloperCertificate(options?: WithHttpsDeveloperCertificateOptions): NodeAppResourcePromise { + const password = options?.password; + return new NodeAppResourcePromise(this._withHttpsDeveloperCertificateInternal(password)); + } + + /** @internal */ + private async _withoutHttpsCertificateInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withoutHttpsCertificate', + rpcArgs + ); + return new NodeAppResource(result, this._client); + } + + /** Removes HTTPS certificate configuration */ + withoutHttpsCertificate(): NodeAppResourcePromise { + return new NodeAppResourcePromise(this._withoutHttpsCertificateInternal()); + } + + /** @internal */ + private async _withParentRelationshipInternal(parent: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, parent }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withParentRelationship', + rpcArgs + ); + return new NodeAppResource(result, this._client); + } + + /** Sets the parent relationship */ + withParentRelationship(parent: ResourceBuilderBase): NodeAppResourcePromise { + return new NodeAppResourcePromise(this._withParentRelationshipInternal(parent)); + } + + /** @internal */ + private async _withChildRelationshipInternal(child: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, child }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withChildRelationship', + rpcArgs + ); + return new NodeAppResource(result, this._client); + } + + /** Sets a child relationship */ + withChildRelationship(child: ResourceBuilderBase): NodeAppResourcePromise { + return new NodeAppResourcePromise(this._withChildRelationshipInternal(child)); + } + + /** @internal */ + private async _withIconNameInternal(iconName: string, iconVariant?: IconVariant): Promise { + const rpcArgs: Record = { builder: this._handle, iconName }; + if (iconVariant !== undefined) rpcArgs.iconVariant = iconVariant; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withIconName', + rpcArgs + ); + return new NodeAppResource(result, this._client); + } + + /** Sets the icon for the resource */ + withIconName(iconName: string, options?: WithIconNameOptions): NodeAppResourcePromise { + const iconVariant = options?.iconVariant; + return new NodeAppResourcePromise(this._withIconNameInternal(iconName, iconVariant)); + } + + /** @internal */ + private async _withHttpProbeInternal(probeType: ProbeType, path?: string, initialDelaySeconds?: number, periodSeconds?: number, timeoutSeconds?: number, failureThreshold?: number, successThreshold?: number, endpointName?: string): Promise { + const rpcArgs: Record = { builder: this._handle, probeType }; + if (path !== undefined) rpcArgs.path = path; + if (initialDelaySeconds !== undefined) rpcArgs.initialDelaySeconds = initialDelaySeconds; + if (periodSeconds !== undefined) rpcArgs.periodSeconds = periodSeconds; + if (timeoutSeconds !== undefined) rpcArgs.timeoutSeconds = timeoutSeconds; + if (failureThreshold !== undefined) rpcArgs.failureThreshold = failureThreshold; + if (successThreshold !== undefined) rpcArgs.successThreshold = successThreshold; + if (endpointName !== undefined) rpcArgs.endpointName = endpointName; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withHttpProbe', + rpcArgs + ); + return new NodeAppResource(result, this._client); + } + + /** Adds an HTTP health probe to the resource */ + withHttpProbe(probeType: ProbeType, options?: WithHttpProbeOptions): NodeAppResourcePromise { + const path = options?.path; + const initialDelaySeconds = options?.initialDelaySeconds; + const periodSeconds = options?.periodSeconds; + const timeoutSeconds = options?.timeoutSeconds; + const failureThreshold = options?.failureThreshold; + const successThreshold = options?.successThreshold; + const endpointName = options?.endpointName; + return new NodeAppResourcePromise(this._withHttpProbeInternal(probeType, path, initialDelaySeconds, periodSeconds, timeoutSeconds, failureThreshold, successThreshold, endpointName)); + } + + /** @internal */ + private async _excludeFromMcpInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/excludeFromMcp', + rpcArgs + ); + return new NodeAppResource(result, this._client); + } + + /** Excludes the resource from MCP server exposure */ + excludeFromMcp(): NodeAppResourcePromise { + return new NodeAppResourcePromise(this._excludeFromMcpInternal()); + } + + /** @internal */ + private async _withRemoteImageNameInternal(remoteImageName: string): Promise { + const rpcArgs: Record = { builder: this._handle, remoteImageName }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withRemoteImageName', + rpcArgs + ); + return new NodeAppResource(result, this._client); + } + + /** Sets the remote image name for publishing */ + withRemoteImageName(remoteImageName: string): NodeAppResourcePromise { + return new NodeAppResourcePromise(this._withRemoteImageNameInternal(remoteImageName)); + } + + /** @internal */ + private async _withRemoteImageTagInternal(remoteImageTag: string): Promise { + const rpcArgs: Record = { builder: this._handle, remoteImageTag }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withRemoteImageTag', + rpcArgs + ); + return new NodeAppResource(result, this._client); + } + + /** Sets the remote image tag for publishing */ + withRemoteImageTag(remoteImageTag: string): NodeAppResourcePromise { + return new NodeAppResourcePromise(this._withRemoteImageTagInternal(remoteImageTag)); + } + + /** @internal */ + private async _withPipelineStepFactoryInternal(stepName: string, callback: (arg: PipelineStepContext) => Promise, dependsOn?: string[], requiredBy?: string[], tags?: string[], description?: string): Promise { + const callbackId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as PipelineStepContextHandle; + const arg = new PipelineStepContext(argHandle, this._client); + await callback(arg); + }); + const rpcArgs: Record = { builder: this._handle, stepName, callback: callbackId }; + if (dependsOn !== undefined) rpcArgs.dependsOn = dependsOn; + if (requiredBy !== undefined) rpcArgs.requiredBy = requiredBy; + if (tags !== undefined) rpcArgs.tags = tags; + if (description !== undefined) rpcArgs.description = description; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withPipelineStepFactory', + rpcArgs + ); + return new NodeAppResource(result, this._client); + } + + /** Adds a pipeline step to the resource */ + withPipelineStepFactory(stepName: string, callback: (arg: PipelineStepContext) => Promise, options?: WithPipelineStepFactoryOptions): NodeAppResourcePromise { + const dependsOn = options?.dependsOn; + const requiredBy = options?.requiredBy; + const tags = options?.tags; + const description = options?.description; + return new NodeAppResourcePromise(this._withPipelineStepFactoryInternal(stepName, callback, dependsOn, requiredBy, tags, description)); + } + + /** @internal */ + private async _withPipelineConfigurationAsyncInternal(callback: (arg: PipelineConfigurationContext) => Promise): Promise { + const callbackId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as PipelineConfigurationContextHandle; + const arg = new PipelineConfigurationContext(argHandle, this._client); + await callback(arg); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withPipelineConfigurationAsync', + rpcArgs + ); + return new NodeAppResource(result, this._client); + } + + /** Configures pipeline step dependencies via an async callback */ + withPipelineConfigurationAsync(callback: (arg: PipelineConfigurationContext) => Promise): NodeAppResourcePromise { + return new NodeAppResourcePromise(this._withPipelineConfigurationAsyncInternal(callback)); + } + + /** @internal */ + private async _withPipelineConfigurationInternal(callback: (obj: PipelineConfigurationContext) => Promise): Promise { + const callbackId = registerCallback(async (objData: unknown) => { + const objHandle = wrapIfHandle(objData) as PipelineConfigurationContextHandle; + const obj = new PipelineConfigurationContext(objHandle, this._client); + await callback(obj); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withPipelineConfiguration', + rpcArgs + ); + return new NodeAppResource(result, this._client); + } + + /** Configures pipeline step dependencies via a callback */ + withPipelineConfiguration(callback: (obj: PipelineConfigurationContext) => Promise): NodeAppResourcePromise { + return new NodeAppResourcePromise(this._withPipelineConfigurationInternal(callback)); + } + + /** Gets the resource name */ + async getResourceName(): Promise { + const rpcArgs: Record = { resource: this._handle }; + return await this._client.invokeCapability( + 'Aspire.Hosting/getResourceName', + rpcArgs + ); + } + + /** @internal */ + private async _withStorageRoleAssignmentsInternal(target: AzureStorageResource, roles: AzureStorageRole[]): Promise { + const rpcArgs: Record = { builder: this._handle, target, roles }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure.Storage/withStorageRoleAssignments', + rpcArgs + ); + return new NodeAppResource(result, this._client); + } + + /** Assigns Azure Storage roles to a resource */ + withStorageRoleAssignments(target: AzureStorageResource, roles: AzureStorageRole[]): NodeAppResourcePromise { + return new NodeAppResourcePromise(this._withStorageRoleAssignmentsInternal(target, roles)); + } + + /** @internal */ + private async _withEventHubsRoleAssignmentsInternal(target: AzureEventHubsResource, roles: AzureEventHubsRole[]): Promise { + const rpcArgs: Record = { builder: this._handle, target, roles }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure.EventHubs/withEventHubsRoleAssignments', + rpcArgs + ); + return new NodeAppResource(result, this._client); + } + + /** Assigns Event Hubs roles to a resource */ + withEventHubsRoleAssignments(target: AzureEventHubsResource, roles: AzureEventHubsRole[]): NodeAppResourcePromise { + return new NodeAppResourcePromise(this._withEventHubsRoleAssignmentsInternal(target, roles)); + } + + /** @internal */ + private async _withNpmInternal(install?: boolean, installCommand?: string, installArgs?: string[]): Promise { + const rpcArgs: Record = { resource: this._handle }; + if (install !== undefined) rpcArgs.install = install; + if (installCommand !== undefined) rpcArgs.installCommand = installCommand; + if (installArgs !== undefined) rpcArgs.installArgs = installArgs; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.JavaScript/withNpm', + rpcArgs + ); + return new NodeAppResource(result, this._client); + } + + /** Configures npm as the package manager */ + withNpm(options?: WithNpmOptions): NodeAppResourcePromise { + const install = options?.install; + const installCommand = options?.installCommand; + const installArgs = options?.installArgs; + return new NodeAppResourcePromise(this._withNpmInternal(install, installCommand, installArgs)); + } + + /** @internal */ + private async _withBunInternal(install?: boolean, installArgs?: string[]): Promise { + const rpcArgs: Record = { resource: this._handle }; + if (install !== undefined) rpcArgs.install = install; + if (installArgs !== undefined) rpcArgs.installArgs = installArgs; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.JavaScript/withBun', + rpcArgs + ); + return new NodeAppResource(result, this._client); + } + + /** Configures Bun as the package manager */ + withBun(options?: WithBunOptions): NodeAppResourcePromise { + const install = options?.install; + const installArgs = options?.installArgs; + return new NodeAppResourcePromise(this._withBunInternal(install, installArgs)); + } + + /** @internal */ + private async _withYarnInternal(install?: boolean, installArgs?: string[]): Promise { + const rpcArgs: Record = { resource: this._handle }; + if (install !== undefined) rpcArgs.install = install; + if (installArgs !== undefined) rpcArgs.installArgs = installArgs; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.JavaScript/withYarn', + rpcArgs + ); + return new NodeAppResource(result, this._client); + } + + /** Configures yarn as the package manager */ + withYarn(options?: WithYarnOptions): NodeAppResourcePromise { + const install = options?.install; + const installArgs = options?.installArgs; + return new NodeAppResourcePromise(this._withYarnInternal(install, installArgs)); + } + + /** @internal */ + private async _withPnpmInternal(install?: boolean, installArgs?: string[]): Promise { + const rpcArgs: Record = { resource: this._handle }; + if (install !== undefined) rpcArgs.install = install; + if (installArgs !== undefined) rpcArgs.installArgs = installArgs; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.JavaScript/withPnpm', + rpcArgs + ); + return new NodeAppResource(result, this._client); + } + + /** Configures pnpm as the package manager */ + withPnpm(options?: WithPnpmOptions): NodeAppResourcePromise { + const install = options?.install; + const installArgs = options?.installArgs; + return new NodeAppResourcePromise(this._withPnpmInternal(install, installArgs)); + } + + /** @internal */ + private async _withBuildScriptInternal(scriptName: string, args?: string[]): Promise { + const rpcArgs: Record = { resource: this._handle, scriptName }; + if (args !== undefined) rpcArgs.args = args; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.JavaScript/withBuildScript', + rpcArgs + ); + return new NodeAppResource(result, this._client); + } + + /** Specifies an npm script to run before starting the application */ + withBuildScript(scriptName: string, options?: WithBuildScriptOptions): NodeAppResourcePromise { + const args = options?.args; + return new NodeAppResourcePromise(this._withBuildScriptInternal(scriptName, args)); + } + + /** @internal */ + private async _withRunScriptInternal(scriptName: string, args?: string[]): Promise { + const rpcArgs: Record = { resource: this._handle, scriptName }; + if (args !== undefined) rpcArgs.args = args; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.JavaScript/withRunScript', + rpcArgs + ); + return new NodeAppResource(result, this._client); + } + + /** Specifies an npm script to run during development */ + withRunScript(scriptName: string, options?: WithRunScriptOptions): NodeAppResourcePromise { + const args = options?.args; + return new NodeAppResourcePromise(this._withRunScriptInternal(scriptName, args)); + } + + /** @internal */ + private async _withBrowserDebuggerInternal(browser?: string): Promise { + const rpcArgs: Record = { builder: this._handle }; + if (browser !== undefined) rpcArgs.browser = browser; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.JavaScript/withBrowserDebugger', + rpcArgs + ); + return new NodeAppResource(result, this._client); + } + + /** Configures a browser debugger for the JavaScript application */ + withBrowserDebugger(options?: WithBrowserDebuggerOptions): NodeAppResourcePromise { + const browser = options?.browser; + return new NodeAppResourcePromise(this._withBrowserDebuggerInternal(browser)); + } + + /** @internal */ + private async _withEnvironmentFromOutputInternal(name: string, bicepOutputReference: BicepOutputReference): Promise { + const rpcArgs: Record = { builder: this._handle, name, bicepOutputReference }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure/withEnvironmentFromOutput', + rpcArgs + ); + return new NodeAppResource(result, this._client); + } + + /** Sets an environment variable from a Bicep output reference */ + withEnvironmentFromOutput(name: string, bicepOutputReference: BicepOutputReference): NodeAppResourcePromise { + return new NodeAppResourcePromise(this._withEnvironmentFromOutputInternal(name, bicepOutputReference)); + } + + /** @internal */ + private async _withEnvironmentFromKeyVaultSecretInternal(name: string, secretReference: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, name, secretReference }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure/withEnvironmentFromKeyVaultSecret', + rpcArgs + ); + return new NodeAppResource(result, this._client); + } + + /** Sets an environment variable from an Azure Key Vault secret reference */ + withEnvironmentFromKeyVaultSecret(name: string, secretReference: ResourceBuilderBase): NodeAppResourcePromise { + return new NodeAppResourcePromise(this._withEnvironmentFromKeyVaultSecretInternal(name, secretReference)); + } + + /** @internal */ + private async _withAzureUserAssignedIdentityInternal(identityResourceBuilder: AzureUserAssignedIdentityResource): Promise { + const rpcArgs: Record = { builder: this._handle, identityResourceBuilder }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure/withUserAssignedIdentityAzureUserAssignedIdentity', + rpcArgs + ); + return new NodeAppResource(result, this._client); + } + + /** Associates an Azure user-assigned identity with a compute resource */ + withAzureUserAssignedIdentity(identityResourceBuilder: AzureUserAssignedIdentityResource): NodeAppResourcePromise { + return new NodeAppResourcePromise(this._withAzureUserAssignedIdentityInternal(identityResourceBuilder)); + } + +} + +/** + * Thenable wrapper for NodeAppResource that enables fluent chaining. + * @example + * await builder.addSomething().withX().withY(); + */ +export class NodeAppResourcePromise implements PromiseLike { + constructor(private _promise: Promise) {} + + then( + onfulfilled?: ((value: NodeAppResource) => TResult1 | PromiseLike) | null, + onrejected?: ((reason: unknown) => TResult2 | PromiseLike) | null + ): PromiseLike { + return this._promise.then(onfulfilled, onrejected); + } + + /** Configures a resource to use a container registry */ + withContainerRegistry(registry: ResourceBuilderBase): NodeAppResourcePromise { + return new NodeAppResourcePromise(this._promise.then(obj => obj.withContainerRegistry(registry))); + } + + /** Sets the base image for a Dockerfile build */ + withDockerfileBaseImage(options?: WithDockerfileBaseImageOptions): NodeAppResourcePromise { + return new NodeAppResourcePromise(this._promise.then(obj => obj.withDockerfileBaseImage(options))); + } + + /** Publishes the executable as a Docker container */ + publishAsDockerFile(): NodeAppResourcePromise { + return new NodeAppResourcePromise(this._promise.then(obj => obj.publishAsDockerFile())); + } + + /** Publishes an executable as a Docker file with optional container configuration */ + publishAsDockerFileWithConfigure(configure: (obj: ContainerResource) => Promise): NodeAppResourcePromise { + return new NodeAppResourcePromise(this._promise.then(obj => obj.publishAsDockerFileWithConfigure(configure))); + } + + /** Sets the executable command */ + withExecutableCommand(command: string): NodeAppResourcePromise { + return new NodeAppResourcePromise(this._promise.then(obj => obj.withExecutableCommand(command))); + } + + /** Sets the executable working directory */ + withWorkingDirectory(workingDirectory: string): NodeAppResourcePromise { + return new NodeAppResourcePromise(this._promise.then(obj => obj.withWorkingDirectory(workingDirectory))); + } + + /** Configures an MCP server endpoint on the resource */ + withMcpServer(options?: WithMcpServerOptions): NodeAppResourcePromise { + return new NodeAppResourcePromise(this._promise.then(obj => obj.withMcpServer(options))); + } + + /** Configures OTLP telemetry export */ + withOtlpExporter(): NodeAppResourcePromise { + return new NodeAppResourcePromise(this._promise.then(obj => obj.withOtlpExporter())); + } + + /** Configures OTLP telemetry export with specific protocol */ + withOtlpExporterProtocol(protocol: OtlpProtocol): NodeAppResourcePromise { + return new NodeAppResourcePromise(this._promise.then(obj => obj.withOtlpExporterProtocol(protocol))); + } + + /** Adds a required command dependency */ + withRequiredCommand(command: string, options?: WithRequiredCommandOptions): NodeAppResourcePromise { + return new NodeAppResourcePromise(this._promise.then(obj => obj.withRequiredCommand(command, options))); + } + + /** Sets an environment variable */ + withEnvironment(name: string, value: string): NodeAppResourcePromise { + return new NodeAppResourcePromise(this._promise.then(obj => obj.withEnvironment(name, value))); + } + + /** Adds an environment variable with a reference expression */ + withEnvironmentExpression(name: string, value: ReferenceExpression): NodeAppResourcePromise { + return new NodeAppResourcePromise(this._promise.then(obj => obj.withEnvironmentExpression(name, value))); + } + + /** Sets environment variables via callback */ + withEnvironmentCallback(callback: (obj: EnvironmentCallbackContext) => Promise): NodeAppResourcePromise { + return new NodeAppResourcePromise(this._promise.then(obj => obj.withEnvironmentCallback(callback))); + } + + /** Sets environment variables via async callback */ + withEnvironmentCallbackAsync(callback: (arg: EnvironmentCallbackContext) => Promise): NodeAppResourcePromise { + return new NodeAppResourcePromise(this._promise.then(obj => obj.withEnvironmentCallbackAsync(callback))); + } + + /** Sets an environment variable from an endpoint reference */ + withEnvironmentEndpoint(name: string, endpointReference: EndpointReference): NodeAppResourcePromise { + return new NodeAppResourcePromise(this._promise.then(obj => obj.withEnvironmentEndpoint(name, endpointReference))); + } + + /** Sets an environment variable from a parameter resource */ + withEnvironmentParameter(name: string, parameter: ParameterResource): NodeAppResourcePromise { + return new NodeAppResourcePromise(this._promise.then(obj => obj.withEnvironmentParameter(name, parameter))); + } + + /** Sets an environment variable from a connection string resource */ + withEnvironmentConnectionString(envVarName: string, resource: ResourceBuilderBase): NodeAppResourcePromise { + return new NodeAppResourcePromise(this._promise.then(obj => obj.withEnvironmentConnectionString(envVarName, resource))); + } + + /** Adds arguments */ + withArgs(args: string[]): NodeAppResourcePromise { + return new NodeAppResourcePromise(this._promise.then(obj => obj.withArgs(args))); + } + + /** Sets command-line arguments via callback */ + withArgsCallback(callback: (obj: CommandLineArgsCallbackContext) => Promise): NodeAppResourcePromise { + return new NodeAppResourcePromise(this._promise.then(obj => obj.withArgsCallback(callback))); + } + + /** Sets command-line arguments via async callback */ + withArgsCallbackAsync(callback: (arg: CommandLineArgsCallbackContext) => Promise): NodeAppResourcePromise { + return new NodeAppResourcePromise(this._promise.then(obj => obj.withArgsCallbackAsync(callback))); + } + + /** Adds a reference to another resource */ + withReference(source: ResourceBuilderBase, options?: WithReferenceOptions): NodeAppResourcePromise { + return new NodeAppResourcePromise(this._promise.then(obj => obj.withReference(source, options))); + } + + /** Adds a service discovery reference to another resource */ + withServiceReference(source: ResourceBuilderBase): NodeAppResourcePromise { + return new NodeAppResourcePromise(this._promise.then(obj => obj.withServiceReference(source))); + } + + /** Adds a named service discovery reference */ + withServiceReferenceNamed(source: ResourceBuilderBase, name: string): NodeAppResourcePromise { + return new NodeAppResourcePromise(this._promise.then(obj => obj.withServiceReferenceNamed(source, name))); + } + + /** Adds a reference to a URI */ + withReferenceUri(name: string, uri: string): NodeAppResourcePromise { + return new NodeAppResourcePromise(this._promise.then(obj => obj.withReferenceUri(name, uri))); + } + + /** Adds a reference to an external service */ + withReferenceExternalService(externalService: ExternalServiceResource): NodeAppResourcePromise { + return new NodeAppResourcePromise(this._promise.then(obj => obj.withReferenceExternalService(externalService))); + } + + /** Adds a reference to an endpoint */ + withReferenceEndpoint(endpointReference: EndpointReference): NodeAppResourcePromise { + return new NodeAppResourcePromise(this._promise.then(obj => obj.withReferenceEndpoint(endpointReference))); + } + + /** Adds a network endpoint */ + withEndpoint(options?: WithEndpointOptions): NodeAppResourcePromise { + return new NodeAppResourcePromise(this._promise.then(obj => obj.withEndpoint(options))); + } + + /** Adds an HTTP endpoint */ + withHttpEndpoint(options?: WithHttpEndpointOptions): NodeAppResourcePromise { + return new NodeAppResourcePromise(this._promise.then(obj => obj.withHttpEndpoint(options))); + } + + /** Adds an HTTPS endpoint */ + withHttpsEndpoint(options?: WithHttpsEndpointOptions): NodeAppResourcePromise { + return new NodeAppResourcePromise(this._promise.then(obj => obj.withHttpsEndpoint(options))); + } + + /** Makes HTTP endpoints externally accessible */ + withExternalHttpEndpoints(): NodeAppResourcePromise { + return new NodeAppResourcePromise(this._promise.then(obj => obj.withExternalHttpEndpoints())); + } + + /** Gets an endpoint reference */ + getEndpoint(name: string): Promise { + return this._promise.then(obj => obj.getEndpoint(name)); + } + + /** Configures resource for HTTP/2 */ + asHttp2Service(): NodeAppResourcePromise { + return new NodeAppResourcePromise(this._promise.then(obj => obj.asHttp2Service())); + } + + /** Customizes displayed URLs via callback */ + withUrlsCallback(callback: (obj: ResourceUrlsCallbackContext) => Promise): NodeAppResourcePromise { + return new NodeAppResourcePromise(this._promise.then(obj => obj.withUrlsCallback(callback))); + } + + /** Customizes displayed URLs via async callback */ + withUrlsCallbackAsync(callback: (arg: ResourceUrlsCallbackContext) => Promise): NodeAppResourcePromise { + return new NodeAppResourcePromise(this._promise.then(obj => obj.withUrlsCallbackAsync(callback))); + } + + /** Adds or modifies displayed URLs */ + withUrl(url: string, options?: WithUrlOptions): NodeAppResourcePromise { + return new NodeAppResourcePromise(this._promise.then(obj => obj.withUrl(url, options))); + } + + /** Adds a URL using a reference expression */ + withUrlExpression(url: ReferenceExpression, options?: WithUrlExpressionOptions): NodeAppResourcePromise { + return new NodeAppResourcePromise(this._promise.then(obj => obj.withUrlExpression(url, options))); + } + + /** Customizes the URL for a specific endpoint via callback */ + withUrlForEndpoint(endpointName: string, callback: (obj: ResourceUrlAnnotation) => Promise): NodeAppResourcePromise { + return new NodeAppResourcePromise(this._promise.then(obj => obj.withUrlForEndpoint(endpointName, callback))); + } + + /** Adds a URL for a specific endpoint via factory callback */ + withUrlForEndpointFactory(endpointName: string, callback: (arg: EndpointReference) => Promise): NodeAppResourcePromise { + return new NodeAppResourcePromise(this._promise.then(obj => obj.withUrlForEndpointFactory(endpointName, callback))); + } + + /** Configures the resource to copy container files from the specified source during publishing */ + publishWithContainerFiles(source: ResourceBuilderBase, destinationPath: string): NodeAppResourcePromise { + return new NodeAppResourcePromise(this._promise.then(obj => obj.publishWithContainerFiles(source, destinationPath))); + } + + /** Sets the source directory for container files */ + withContainerFilesSource(sourcePath: string): NodeAppResourcePromise { + return new NodeAppResourcePromise(this._promise.then(obj => obj.withContainerFilesSource(sourcePath))); + } + + /** Clears all container file sources */ + clearContainerFilesSources(): NodeAppResourcePromise { + return new NodeAppResourcePromise(this._promise.then(obj => obj.clearContainerFilesSources())); + } + + /** Excludes the resource from the deployment manifest */ + excludeFromManifest(): NodeAppResourcePromise { + return new NodeAppResourcePromise(this._promise.then(obj => obj.excludeFromManifest())); + } + + /** Waits for another resource to be ready */ + waitFor(dependency: ResourceBuilderBase): NodeAppResourcePromise { + return new NodeAppResourcePromise(this._promise.then(obj => obj.waitFor(dependency))); + } + + /** Waits for another resource with specific behavior */ + waitForWithBehavior(dependency: ResourceBuilderBase, waitBehavior: WaitBehavior): NodeAppResourcePromise { + return new NodeAppResourcePromise(this._promise.then(obj => obj.waitForWithBehavior(dependency, waitBehavior))); + } + + /** Waits for another resource to start */ + waitForStart(dependency: ResourceBuilderBase): NodeAppResourcePromise { + return new NodeAppResourcePromise(this._promise.then(obj => obj.waitForStart(dependency))); + } + + /** Waits for another resource to start with specific behavior */ + waitForStartWithBehavior(dependency: ResourceBuilderBase, waitBehavior: WaitBehavior): NodeAppResourcePromise { + return new NodeAppResourcePromise(this._promise.then(obj => obj.waitForStartWithBehavior(dependency, waitBehavior))); + } + + /** Prevents resource from starting automatically */ + withExplicitStart(): NodeAppResourcePromise { + return new NodeAppResourcePromise(this._promise.then(obj => obj.withExplicitStart())); + } + + /** Waits for resource completion */ + waitForCompletion(dependency: ResourceBuilderBase, options?: WaitForCompletionOptions): NodeAppResourcePromise { + return new NodeAppResourcePromise(this._promise.then(obj => obj.waitForCompletion(dependency, options))); + } + + /** Adds a health check by key */ + withHealthCheck(key: string): NodeAppResourcePromise { + return new NodeAppResourcePromise(this._promise.then(obj => obj.withHealthCheck(key))); + } + + /** Adds an HTTP health check */ + withHttpHealthCheck(options?: WithHttpHealthCheckOptions): NodeAppResourcePromise { + return new NodeAppResourcePromise(this._promise.then(obj => obj.withHttpHealthCheck(options))); + } + + /** Adds a resource command */ + withCommand(name: string, displayName: string, executeCommand: (arg: ExecuteCommandContext) => Promise, options?: WithCommandOptions): NodeAppResourcePromise { + return new NodeAppResourcePromise(this._promise.then(obj => obj.withCommand(name, displayName, executeCommand, options))); + } + + /** Configures developer certificate trust */ + withDeveloperCertificateTrust(trust: boolean): NodeAppResourcePromise { + return new NodeAppResourcePromise(this._promise.then(obj => obj.withDeveloperCertificateTrust(trust))); + } + + /** Sets the certificate trust scope */ + withCertificateTrustScope(scope: CertificateTrustScope): NodeAppResourcePromise { + return new NodeAppResourcePromise(this._promise.then(obj => obj.withCertificateTrustScope(scope))); + } + + /** Configures HTTPS with a developer certificate */ + withHttpsDeveloperCertificate(options?: WithHttpsDeveloperCertificateOptions): NodeAppResourcePromise { + return new NodeAppResourcePromise(this._promise.then(obj => obj.withHttpsDeveloperCertificate(options))); + } + + /** Removes HTTPS certificate configuration */ + withoutHttpsCertificate(): NodeAppResourcePromise { + return new NodeAppResourcePromise(this._promise.then(obj => obj.withoutHttpsCertificate())); + } + + /** Sets the parent relationship */ + withParentRelationship(parent: ResourceBuilderBase): NodeAppResourcePromise { + return new NodeAppResourcePromise(this._promise.then(obj => obj.withParentRelationship(parent))); + } + + /** Sets a child relationship */ + withChildRelationship(child: ResourceBuilderBase): NodeAppResourcePromise { + return new NodeAppResourcePromise(this._promise.then(obj => obj.withChildRelationship(child))); + } + + /** Sets the icon for the resource */ + withIconName(iconName: string, options?: WithIconNameOptions): NodeAppResourcePromise { + return new NodeAppResourcePromise(this._promise.then(obj => obj.withIconName(iconName, options))); + } + + /** Adds an HTTP health probe to the resource */ + withHttpProbe(probeType: ProbeType, options?: WithHttpProbeOptions): NodeAppResourcePromise { + return new NodeAppResourcePromise(this._promise.then(obj => obj.withHttpProbe(probeType, options))); + } + + /** Excludes the resource from MCP server exposure */ + excludeFromMcp(): NodeAppResourcePromise { + return new NodeAppResourcePromise(this._promise.then(obj => obj.excludeFromMcp())); + } + + /** Sets the remote image name for publishing */ + withRemoteImageName(remoteImageName: string): NodeAppResourcePromise { + return new NodeAppResourcePromise(this._promise.then(obj => obj.withRemoteImageName(remoteImageName))); + } + + /** Sets the remote image tag for publishing */ + withRemoteImageTag(remoteImageTag: string): NodeAppResourcePromise { + return new NodeAppResourcePromise(this._promise.then(obj => obj.withRemoteImageTag(remoteImageTag))); + } + + /** Adds a pipeline step to the resource */ + withPipelineStepFactory(stepName: string, callback: (arg: PipelineStepContext) => Promise, options?: WithPipelineStepFactoryOptions): NodeAppResourcePromise { + return new NodeAppResourcePromise(this._promise.then(obj => obj.withPipelineStepFactory(stepName, callback, options))); + } + + /** Configures pipeline step dependencies via an async callback */ + withPipelineConfigurationAsync(callback: (arg: PipelineConfigurationContext) => Promise): NodeAppResourcePromise { + return new NodeAppResourcePromise(this._promise.then(obj => obj.withPipelineConfigurationAsync(callback))); + } + + /** Configures pipeline step dependencies via a callback */ + withPipelineConfiguration(callback: (obj: PipelineConfigurationContext) => Promise): NodeAppResourcePromise { + return new NodeAppResourcePromise(this._promise.then(obj => obj.withPipelineConfiguration(callback))); + } + + /** Gets the resource name */ + getResourceName(): Promise { + return this._promise.then(obj => obj.getResourceName()); + } + + /** Assigns Azure Storage roles to a resource */ + withStorageRoleAssignments(target: AzureStorageResource, roles: AzureStorageRole[]): NodeAppResourcePromise { + return new NodeAppResourcePromise(this._promise.then(obj => obj.withStorageRoleAssignments(target, roles))); + } + + /** Assigns Event Hubs roles to a resource */ + withEventHubsRoleAssignments(target: AzureEventHubsResource, roles: AzureEventHubsRole[]): NodeAppResourcePromise { + return new NodeAppResourcePromise(this._promise.then(obj => obj.withEventHubsRoleAssignments(target, roles))); + } + + /** Configures npm as the package manager */ + withNpm(options?: WithNpmOptions): NodeAppResourcePromise { + return new NodeAppResourcePromise(this._promise.then(obj => obj.withNpm(options))); + } + + /** Configures Bun as the package manager */ + withBun(options?: WithBunOptions): NodeAppResourcePromise { + return new NodeAppResourcePromise(this._promise.then(obj => obj.withBun(options))); + } + + /** Configures yarn as the package manager */ + withYarn(options?: WithYarnOptions): NodeAppResourcePromise { + return new NodeAppResourcePromise(this._promise.then(obj => obj.withYarn(options))); + } + + /** Configures pnpm as the package manager */ + withPnpm(options?: WithPnpmOptions): NodeAppResourcePromise { + return new NodeAppResourcePromise(this._promise.then(obj => obj.withPnpm(options))); + } + + /** Specifies an npm script to run before starting the application */ + withBuildScript(scriptName: string, options?: WithBuildScriptOptions): NodeAppResourcePromise { + return new NodeAppResourcePromise(this._promise.then(obj => obj.withBuildScript(scriptName, options))); + } + + /** Specifies an npm script to run during development */ + withRunScript(scriptName: string, options?: WithRunScriptOptions): NodeAppResourcePromise { + return new NodeAppResourcePromise(this._promise.then(obj => obj.withRunScript(scriptName, options))); + } + + /** Configures a browser debugger for the JavaScript application */ + withBrowserDebugger(options?: WithBrowserDebuggerOptions): NodeAppResourcePromise { + return new NodeAppResourcePromise(this._promise.then(obj => obj.withBrowserDebugger(options))); + } + + /** Sets an environment variable from a Bicep output reference */ + withEnvironmentFromOutput(name: string, bicepOutputReference: BicepOutputReference): NodeAppResourcePromise { + return new NodeAppResourcePromise(this._promise.then(obj => obj.withEnvironmentFromOutput(name, bicepOutputReference))); + } + + /** Sets an environment variable from an Azure Key Vault secret reference */ + withEnvironmentFromKeyVaultSecret(name: string, secretReference: ResourceBuilderBase): NodeAppResourcePromise { + return new NodeAppResourcePromise(this._promise.then(obj => obj.withEnvironmentFromKeyVaultSecret(name, secretReference))); + } + + /** Associates an Azure user-assigned identity with a compute resource */ + withAzureUserAssignedIdentity(identityResourceBuilder: AzureUserAssignedIdentityResource): NodeAppResourcePromise { + return new NodeAppResourcePromise(this._promise.then(obj => obj.withAzureUserAssignedIdentity(identityResourceBuilder))); + } + +} + +// ============================================================================ +// ParameterResource +// ============================================================================ + +export class ParameterResource extends ResourceBuilderBase { + constructor(handle: ParameterResourceHandle, client: AspireClientRpc) { + super(handle, client); + } + + /** @internal */ + private async _withContainerRegistryInternal(registry: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, registry }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withContainerRegistry', + rpcArgs + ); + return new ParameterResource(result, this._client); + } + + /** Configures a resource to use a container registry */ + withContainerRegistry(registry: ResourceBuilderBase): ParameterResourcePromise { + return new ParameterResourcePromise(this._withContainerRegistryInternal(registry)); + } + + /** @internal */ + private async _withDockerfileBaseImageInternal(buildImage?: string, runtimeImage?: string): Promise { + const rpcArgs: Record = { builder: this._handle }; + if (buildImage !== undefined) rpcArgs.buildImage = buildImage; + if (runtimeImage !== undefined) rpcArgs.runtimeImage = runtimeImage; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withDockerfileBaseImage', + rpcArgs + ); + return new ParameterResource(result, this._client); + } + + /** Sets the base image for a Dockerfile build */ + withDockerfileBaseImage(options?: WithDockerfileBaseImageOptions): ParameterResourcePromise { + const buildImage = options?.buildImage; + const runtimeImage = options?.runtimeImage; + return new ParameterResourcePromise(this._withDockerfileBaseImageInternal(buildImage, runtimeImage)); + } + + /** @internal */ + private async _withDescriptionInternal(description: string, enableMarkdown?: boolean): Promise { + const rpcArgs: Record = { builder: this._handle, description }; + if (enableMarkdown !== undefined) rpcArgs.enableMarkdown = enableMarkdown; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withDescription', + rpcArgs + ); + return new ParameterResource(result, this._client); + } + + /** Sets a parameter description */ + withDescription(description: string, options?: WithDescriptionOptions): ParameterResourcePromise { + const enableMarkdown = options?.enableMarkdown; + return new ParameterResourcePromise(this._withDescriptionInternal(description, enableMarkdown)); + } + + /** @internal */ + private async _withRequiredCommandInternal(command: string, helpLink?: string): Promise { + const rpcArgs: Record = { builder: this._handle, command }; + if (helpLink !== undefined) rpcArgs.helpLink = helpLink; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withRequiredCommand', + rpcArgs + ); + return new ParameterResource(result, this._client); + } + + /** Adds a required command dependency */ + withRequiredCommand(command: string, options?: WithRequiredCommandOptions): ParameterResourcePromise { + const helpLink = options?.helpLink; + return new ParameterResourcePromise(this._withRequiredCommandInternal(command, helpLink)); + } + + /** @internal */ + private async _withUrlsCallbackInternal(callback: (obj: ResourceUrlsCallbackContext) => Promise): Promise { + const callbackId = registerCallback(async (objData: unknown) => { + const objHandle = wrapIfHandle(objData) as ResourceUrlsCallbackContextHandle; + const obj = new ResourceUrlsCallbackContext(objHandle, this._client); + await callback(obj); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrlsCallback', + rpcArgs + ); + return new ParameterResource(result, this._client); + } + + /** Customizes displayed URLs via callback */ + withUrlsCallback(callback: (obj: ResourceUrlsCallbackContext) => Promise): ParameterResourcePromise { + return new ParameterResourcePromise(this._withUrlsCallbackInternal(callback)); + } + + /** @internal */ + private async _withUrlsCallbackAsyncInternal(callback: (arg: ResourceUrlsCallbackContext) => Promise): Promise { + const callbackId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as ResourceUrlsCallbackContextHandle; + const arg = new ResourceUrlsCallbackContext(argHandle, this._client); + await callback(arg); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrlsCallbackAsync', + rpcArgs + ); + return new ParameterResource(result, this._client); + } + + /** Customizes displayed URLs via async callback */ + withUrlsCallbackAsync(callback: (arg: ResourceUrlsCallbackContext) => Promise): ParameterResourcePromise { + return new ParameterResourcePromise(this._withUrlsCallbackAsyncInternal(callback)); + } + + /** @internal */ + private async _withUrlInternal(url: string, displayText?: string): Promise { + const rpcArgs: Record = { builder: this._handle, url }; + if (displayText !== undefined) rpcArgs.displayText = displayText; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrl', + rpcArgs + ); + return new ParameterResource(result, this._client); + } + + /** Adds or modifies displayed URLs */ + withUrl(url: string, options?: WithUrlOptions): ParameterResourcePromise { + const displayText = options?.displayText; + return new ParameterResourcePromise(this._withUrlInternal(url, displayText)); + } + + /** @internal */ + private async _withUrlExpressionInternal(url: ReferenceExpression, displayText?: string): Promise { + const rpcArgs: Record = { builder: this._handle, url }; + if (displayText !== undefined) rpcArgs.displayText = displayText; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrlExpression', + rpcArgs + ); + return new ParameterResource(result, this._client); + } + + /** Adds a URL using a reference expression */ + withUrlExpression(url: ReferenceExpression, options?: WithUrlExpressionOptions): ParameterResourcePromise { + const displayText = options?.displayText; + return new ParameterResourcePromise(this._withUrlExpressionInternal(url, displayText)); + } + + /** @internal */ + private async _withUrlForEndpointInternal(endpointName: string, callback: (obj: ResourceUrlAnnotation) => Promise): Promise { + const callbackId = registerCallback(async (objData: unknown) => { + const obj = wrapIfHandle(objData) as ResourceUrlAnnotation; + await callback(obj); + }); + const rpcArgs: Record = { builder: this._handle, endpointName, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrlForEndpoint', + rpcArgs + ); + return new ParameterResource(result, this._client); + } + + /** Customizes the URL for a specific endpoint via callback */ + withUrlForEndpoint(endpointName: string, callback: (obj: ResourceUrlAnnotation) => Promise): ParameterResourcePromise { + return new ParameterResourcePromise(this._withUrlForEndpointInternal(endpointName, callback)); + } + + /** @internal */ + private async _excludeFromManifestInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/excludeFromManifest', + rpcArgs + ); + return new ParameterResource(result, this._client); + } + + /** Excludes the resource from the deployment manifest */ + excludeFromManifest(): ParameterResourcePromise { + return new ParameterResourcePromise(this._excludeFromManifestInternal()); + } + + /** @internal */ + private async _withExplicitStartInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withExplicitStart', + rpcArgs + ); + return new ParameterResource(result, this._client); + } + + /** Prevents resource from starting automatically */ + withExplicitStart(): ParameterResourcePromise { + return new ParameterResourcePromise(this._withExplicitStartInternal()); + } + + /** @internal */ + private async _withHealthCheckInternal(key: string): Promise { + const rpcArgs: Record = { builder: this._handle, key }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withHealthCheck', + rpcArgs + ); + return new ParameterResource(result, this._client); + } + + /** Adds a health check by key */ + withHealthCheck(key: string): ParameterResourcePromise { + return new ParameterResourcePromise(this._withHealthCheckInternal(key)); + } + + /** @internal */ + private async _withCommandInternal(name: string, displayName: string, executeCommand: (arg: ExecuteCommandContext) => Promise, commandOptions?: CommandOptions): Promise { + const executeCommandId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as ExecuteCommandContextHandle; + const arg = new ExecuteCommandContext(argHandle, this._client); + return await executeCommand(arg); + }); + const rpcArgs: Record = { builder: this._handle, name, displayName, executeCommand: executeCommandId }; + if (commandOptions !== undefined) rpcArgs.commandOptions = commandOptions; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withCommand', + rpcArgs + ); + return new ParameterResource(result, this._client); + } + + /** Adds a resource command */ + withCommand(name: string, displayName: string, executeCommand: (arg: ExecuteCommandContext) => Promise, options?: WithCommandOptions): ParameterResourcePromise { + const commandOptions = options?.commandOptions; + return new ParameterResourcePromise(this._withCommandInternal(name, displayName, executeCommand, commandOptions)); + } + + /** @internal */ + private async _withParentRelationshipInternal(parent: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, parent }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withParentRelationship', + rpcArgs + ); + return new ParameterResource(result, this._client); + } + + /** Sets the parent relationship */ + withParentRelationship(parent: ResourceBuilderBase): ParameterResourcePromise { + return new ParameterResourcePromise(this._withParentRelationshipInternal(parent)); + } + + /** @internal */ + private async _withChildRelationshipInternal(child: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, child }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withChildRelationship', + rpcArgs + ); + return new ParameterResource(result, this._client); + } + + /** Sets a child relationship */ + withChildRelationship(child: ResourceBuilderBase): ParameterResourcePromise { + return new ParameterResourcePromise(this._withChildRelationshipInternal(child)); + } + + /** @internal */ + private async _withIconNameInternal(iconName: string, iconVariant?: IconVariant): Promise { + const rpcArgs: Record = { builder: this._handle, iconName }; + if (iconVariant !== undefined) rpcArgs.iconVariant = iconVariant; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withIconName', + rpcArgs + ); + return new ParameterResource(result, this._client); + } + + /** Sets the icon for the resource */ + withIconName(iconName: string, options?: WithIconNameOptions): ParameterResourcePromise { + const iconVariant = options?.iconVariant; + return new ParameterResourcePromise(this._withIconNameInternal(iconName, iconVariant)); + } + + /** @internal */ + private async _excludeFromMcpInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/excludeFromMcp', + rpcArgs + ); + return new ParameterResource(result, this._client); + } + + /** Excludes the resource from MCP server exposure */ + excludeFromMcp(): ParameterResourcePromise { + return new ParameterResourcePromise(this._excludeFromMcpInternal()); + } + + /** @internal */ + private async _withPipelineStepFactoryInternal(stepName: string, callback: (arg: PipelineStepContext) => Promise, dependsOn?: string[], requiredBy?: string[], tags?: string[], description?: string): Promise { + const callbackId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as PipelineStepContextHandle; + const arg = new PipelineStepContext(argHandle, this._client); + await callback(arg); + }); + const rpcArgs: Record = { builder: this._handle, stepName, callback: callbackId }; + if (dependsOn !== undefined) rpcArgs.dependsOn = dependsOn; + if (requiredBy !== undefined) rpcArgs.requiredBy = requiredBy; + if (tags !== undefined) rpcArgs.tags = tags; + if (description !== undefined) rpcArgs.description = description; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withPipelineStepFactory', + rpcArgs + ); + return new ParameterResource(result, this._client); + } + + /** Adds a pipeline step to the resource */ + withPipelineStepFactory(stepName: string, callback: (arg: PipelineStepContext) => Promise, options?: WithPipelineStepFactoryOptions): ParameterResourcePromise { + const dependsOn = options?.dependsOn; + const requiredBy = options?.requiredBy; + const tags = options?.tags; + const description = options?.description; + return new ParameterResourcePromise(this._withPipelineStepFactoryInternal(stepName, callback, dependsOn, requiredBy, tags, description)); + } + + /** @internal */ + private async _withPipelineConfigurationAsyncInternal(callback: (arg: PipelineConfigurationContext) => Promise): Promise { + const callbackId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as PipelineConfigurationContextHandle; + const arg = new PipelineConfigurationContext(argHandle, this._client); + await callback(arg); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withPipelineConfigurationAsync', + rpcArgs + ); + return new ParameterResource(result, this._client); + } + + /** Configures pipeline step dependencies via an async callback */ + withPipelineConfigurationAsync(callback: (arg: PipelineConfigurationContext) => Promise): ParameterResourcePromise { + return new ParameterResourcePromise(this._withPipelineConfigurationAsyncInternal(callback)); + } + + /** @internal */ + private async _withPipelineConfigurationInternal(callback: (obj: PipelineConfigurationContext) => Promise): Promise { + const callbackId = registerCallback(async (objData: unknown) => { + const objHandle = wrapIfHandle(objData) as PipelineConfigurationContextHandle; + const obj = new PipelineConfigurationContext(objHandle, this._client); + await callback(obj); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withPipelineConfiguration', + rpcArgs + ); + return new ParameterResource(result, this._client); + } + + /** Configures pipeline step dependencies via a callback */ + withPipelineConfiguration(callback: (obj: PipelineConfigurationContext) => Promise): ParameterResourcePromise { + return new ParameterResourcePromise(this._withPipelineConfigurationInternal(callback)); + } + + /** Gets the resource name */ + async getResourceName(): Promise { + const rpcArgs: Record = { resource: this._handle }; + return await this._client.invokeCapability( + 'Aspire.Hosting/getResourceName', + rpcArgs + ); + } + + /** @internal */ + private async _withStorageRoleAssignmentsInternal(target: AzureStorageResource, roles: AzureStorageRole[]): Promise { + const rpcArgs: Record = { builder: this._handle, target, roles }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure.Storage/withStorageRoleAssignments', + rpcArgs + ); + return new ParameterResource(result, this._client); + } + + /** Assigns Azure Storage roles to a resource */ + withStorageRoleAssignments(target: AzureStorageResource, roles: AzureStorageRole[]): ParameterResourcePromise { + return new ParameterResourcePromise(this._withStorageRoleAssignmentsInternal(target, roles)); + } + + /** @internal */ + private async _withEventHubsRoleAssignmentsInternal(target: AzureEventHubsResource, roles: AzureEventHubsRole[]): Promise { + const rpcArgs: Record = { builder: this._handle, target, roles }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure.EventHubs/withEventHubsRoleAssignments', + rpcArgs + ); + return new ParameterResource(result, this._client); + } + + /** Assigns Event Hubs roles to a resource */ + withEventHubsRoleAssignments(target: AzureEventHubsResource, roles: AzureEventHubsRole[]): ParameterResourcePromise { + return new ParameterResourcePromise(this._withEventHubsRoleAssignmentsInternal(target, roles)); + } + +} + +/** + * Thenable wrapper for ParameterResource that enables fluent chaining. + * @example + * await builder.addSomething().withX().withY(); + */ +export class ParameterResourcePromise implements PromiseLike { + constructor(private _promise: Promise) {} + + then( + onfulfilled?: ((value: ParameterResource) => TResult1 | PromiseLike) | null, + onrejected?: ((reason: unknown) => TResult2 | PromiseLike) | null + ): PromiseLike { + return this._promise.then(onfulfilled, onrejected); + } + + /** Configures a resource to use a container registry */ + withContainerRegistry(registry: ResourceBuilderBase): ParameterResourcePromise { + return new ParameterResourcePromise(this._promise.then(obj => obj.withContainerRegistry(registry))); + } + + /** Sets the base image for a Dockerfile build */ + withDockerfileBaseImage(options?: WithDockerfileBaseImageOptions): ParameterResourcePromise { + return new ParameterResourcePromise(this._promise.then(obj => obj.withDockerfileBaseImage(options))); + } + + /** Sets a parameter description */ + withDescription(description: string, options?: WithDescriptionOptions): ParameterResourcePromise { + return new ParameterResourcePromise(this._promise.then(obj => obj.withDescription(description, options))); + } + + /** Adds a required command dependency */ + withRequiredCommand(command: string, options?: WithRequiredCommandOptions): ParameterResourcePromise { + return new ParameterResourcePromise(this._promise.then(obj => obj.withRequiredCommand(command, options))); + } + + /** Customizes displayed URLs via callback */ + withUrlsCallback(callback: (obj: ResourceUrlsCallbackContext) => Promise): ParameterResourcePromise { + return new ParameterResourcePromise(this._promise.then(obj => obj.withUrlsCallback(callback))); + } + + /** Customizes displayed URLs via async callback */ + withUrlsCallbackAsync(callback: (arg: ResourceUrlsCallbackContext) => Promise): ParameterResourcePromise { + return new ParameterResourcePromise(this._promise.then(obj => obj.withUrlsCallbackAsync(callback))); + } + + /** Adds or modifies displayed URLs */ + withUrl(url: string, options?: WithUrlOptions): ParameterResourcePromise { + return new ParameterResourcePromise(this._promise.then(obj => obj.withUrl(url, options))); + } + + /** Adds a URL using a reference expression */ + withUrlExpression(url: ReferenceExpression, options?: WithUrlExpressionOptions): ParameterResourcePromise { + return new ParameterResourcePromise(this._promise.then(obj => obj.withUrlExpression(url, options))); + } + + /** Customizes the URL for a specific endpoint via callback */ + withUrlForEndpoint(endpointName: string, callback: (obj: ResourceUrlAnnotation) => Promise): ParameterResourcePromise { + return new ParameterResourcePromise(this._promise.then(obj => obj.withUrlForEndpoint(endpointName, callback))); + } + + /** Excludes the resource from the deployment manifest */ + excludeFromManifest(): ParameterResourcePromise { + return new ParameterResourcePromise(this._promise.then(obj => obj.excludeFromManifest())); + } + + /** Prevents resource from starting automatically */ + withExplicitStart(): ParameterResourcePromise { + return new ParameterResourcePromise(this._promise.then(obj => obj.withExplicitStart())); + } + + /** Adds a health check by key */ + withHealthCheck(key: string): ParameterResourcePromise { + return new ParameterResourcePromise(this._promise.then(obj => obj.withHealthCheck(key))); + } + + /** Adds a resource command */ + withCommand(name: string, displayName: string, executeCommand: (arg: ExecuteCommandContext) => Promise, options?: WithCommandOptions): ParameterResourcePromise { + return new ParameterResourcePromise(this._promise.then(obj => obj.withCommand(name, displayName, executeCommand, options))); + } + + /** Sets the parent relationship */ + withParentRelationship(parent: ResourceBuilderBase): ParameterResourcePromise { + return new ParameterResourcePromise(this._promise.then(obj => obj.withParentRelationship(parent))); + } + + /** Sets a child relationship */ + withChildRelationship(child: ResourceBuilderBase): ParameterResourcePromise { + return new ParameterResourcePromise(this._promise.then(obj => obj.withChildRelationship(child))); + } + + /** Sets the icon for the resource */ + withIconName(iconName: string, options?: WithIconNameOptions): ParameterResourcePromise { + return new ParameterResourcePromise(this._promise.then(obj => obj.withIconName(iconName, options))); + } + + /** Excludes the resource from MCP server exposure */ + excludeFromMcp(): ParameterResourcePromise { + return new ParameterResourcePromise(this._promise.then(obj => obj.excludeFromMcp())); + } + + /** Adds a pipeline step to the resource */ + withPipelineStepFactory(stepName: string, callback: (arg: PipelineStepContext) => Promise, options?: WithPipelineStepFactoryOptions): ParameterResourcePromise { + return new ParameterResourcePromise(this._promise.then(obj => obj.withPipelineStepFactory(stepName, callback, options))); + } + + /** Configures pipeline step dependencies via an async callback */ + withPipelineConfigurationAsync(callback: (arg: PipelineConfigurationContext) => Promise): ParameterResourcePromise { + return new ParameterResourcePromise(this._promise.then(obj => obj.withPipelineConfigurationAsync(callback))); + } + + /** Configures pipeline step dependencies via a callback */ + withPipelineConfiguration(callback: (obj: PipelineConfigurationContext) => Promise): ParameterResourcePromise { + return new ParameterResourcePromise(this._promise.then(obj => obj.withPipelineConfiguration(callback))); + } + + /** Gets the resource name */ + getResourceName(): Promise { + return this._promise.then(obj => obj.getResourceName()); + } + + /** Assigns Azure Storage roles to a resource */ + withStorageRoleAssignments(target: AzureStorageResource, roles: AzureStorageRole[]): ParameterResourcePromise { + return new ParameterResourcePromise(this._promise.then(obj => obj.withStorageRoleAssignments(target, roles))); + } + + /** Assigns Event Hubs roles to a resource */ + withEventHubsRoleAssignments(target: AzureEventHubsResource, roles: AzureEventHubsRole[]): ParameterResourcePromise { + return new ParameterResourcePromise(this._promise.then(obj => obj.withEventHubsRoleAssignments(target, roles))); + } + +} + +// ============================================================================ +// ProjectResource +// ============================================================================ + +export class ProjectResource extends ResourceBuilderBase { + constructor(handle: ProjectResourceHandle, client: AspireClientRpc) { + super(handle, client); + } + + /** @internal */ + private async _withContainerRegistryInternal(registry: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, registry }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withContainerRegistry', + rpcArgs + ); + return new ProjectResource(result, this._client); + } + + /** Configures a resource to use a container registry */ + withContainerRegistry(registry: ResourceBuilderBase): ProjectResourcePromise { + return new ProjectResourcePromise(this._withContainerRegistryInternal(registry)); + } + + /** @internal */ + private async _withDockerfileBaseImageInternal(buildImage?: string, runtimeImage?: string): Promise { + const rpcArgs: Record = { builder: this._handle }; + if (buildImage !== undefined) rpcArgs.buildImage = buildImage; + if (runtimeImage !== undefined) rpcArgs.runtimeImage = runtimeImage; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withDockerfileBaseImage', + rpcArgs + ); + return new ProjectResource(result, this._client); + } + + /** Sets the base image for a Dockerfile build */ + withDockerfileBaseImage(options?: WithDockerfileBaseImageOptions): ProjectResourcePromise { + const buildImage = options?.buildImage; + const runtimeImage = options?.runtimeImage; + return new ProjectResourcePromise(this._withDockerfileBaseImageInternal(buildImage, runtimeImage)); + } + + /** @internal */ + private async _withMcpServerInternal(path?: string, endpointName?: string): Promise { + const rpcArgs: Record = { builder: this._handle }; + if (path !== undefined) rpcArgs.path = path; + if (endpointName !== undefined) rpcArgs.endpointName = endpointName; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withMcpServer', + rpcArgs + ); + return new ProjectResource(result, this._client); + } + + /** Configures an MCP server endpoint on the resource */ + withMcpServer(options?: WithMcpServerOptions): ProjectResourcePromise { + const path = options?.path; + const endpointName = options?.endpointName; + return new ProjectResourcePromise(this._withMcpServerInternal(path, endpointName)); + } + + /** @internal */ + private async _withOtlpExporterInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withOtlpExporter', + rpcArgs + ); + return new ProjectResource(result, this._client); + } + + /** Configures OTLP telemetry export */ + withOtlpExporter(): ProjectResourcePromise { + return new ProjectResourcePromise(this._withOtlpExporterInternal()); + } + + /** @internal */ + private async _withOtlpExporterProtocolInternal(protocol: OtlpProtocol): Promise { + const rpcArgs: Record = { builder: this._handle, protocol }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withOtlpExporterProtocol', + rpcArgs + ); + return new ProjectResource(result, this._client); + } + + /** Configures OTLP telemetry export with specific protocol */ + withOtlpExporterProtocol(protocol: OtlpProtocol): ProjectResourcePromise { + return new ProjectResourcePromise(this._withOtlpExporterProtocolInternal(protocol)); + } + + /** @internal */ + private async _withRequiredCommandInternal(command: string, helpLink?: string): Promise { + const rpcArgs: Record = { builder: this._handle, command }; + if (helpLink !== undefined) rpcArgs.helpLink = helpLink; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withRequiredCommand', + rpcArgs + ); + return new ProjectResource(result, this._client); + } + + /** Adds a required command dependency */ + withRequiredCommand(command: string, options?: WithRequiredCommandOptions): ProjectResourcePromise { + const helpLink = options?.helpLink; + return new ProjectResourcePromise(this._withRequiredCommandInternal(command, helpLink)); + } + + /** @internal */ + private async _withEnvironmentInternal(name: string, value: string): Promise { + const rpcArgs: Record = { builder: this._handle, name, value }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withEnvironment', + rpcArgs + ); + return new ProjectResource(result, this._client); + } + + /** Sets an environment variable */ + withEnvironment(name: string, value: string): ProjectResourcePromise { + return new ProjectResourcePromise(this._withEnvironmentInternal(name, value)); + } + + /** @internal */ + private async _withEnvironmentExpressionInternal(name: string, value: ReferenceExpression): Promise { + const rpcArgs: Record = { builder: this._handle, name, value }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withEnvironmentExpression', + rpcArgs + ); + return new ProjectResource(result, this._client); + } + + /** Adds an environment variable with a reference expression */ + withEnvironmentExpression(name: string, value: ReferenceExpression): ProjectResourcePromise { + return new ProjectResourcePromise(this._withEnvironmentExpressionInternal(name, value)); + } + + /** @internal */ + private async _withEnvironmentCallbackInternal(callback: (obj: EnvironmentCallbackContext) => Promise): Promise { + const callbackId = registerCallback(async (objData: unknown) => { + const objHandle = wrapIfHandle(objData) as EnvironmentCallbackContextHandle; + const obj = new EnvironmentCallbackContext(objHandle, this._client); + await callback(obj); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withEnvironmentCallback', + rpcArgs + ); + return new ProjectResource(result, this._client); + } + + /** Sets environment variables via callback */ + withEnvironmentCallback(callback: (obj: EnvironmentCallbackContext) => Promise): ProjectResourcePromise { + return new ProjectResourcePromise(this._withEnvironmentCallbackInternal(callback)); + } + + /** @internal */ + private async _withEnvironmentCallbackAsyncInternal(callback: (arg: EnvironmentCallbackContext) => Promise): Promise { + const callbackId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as EnvironmentCallbackContextHandle; + const arg = new EnvironmentCallbackContext(argHandle, this._client); + await callback(arg); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withEnvironmentCallbackAsync', + rpcArgs + ); + return new ProjectResource(result, this._client); + } + + /** Sets environment variables via async callback */ + withEnvironmentCallbackAsync(callback: (arg: EnvironmentCallbackContext) => Promise): ProjectResourcePromise { + return new ProjectResourcePromise(this._withEnvironmentCallbackAsyncInternal(callback)); + } + + /** @internal */ + private async _withEnvironmentEndpointInternal(name: string, endpointReference: EndpointReference): Promise { + const rpcArgs: Record = { builder: this._handle, name, endpointReference }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withEnvironmentEndpoint', + rpcArgs + ); + return new ProjectResource(result, this._client); + } + + /** Sets an environment variable from an endpoint reference */ + withEnvironmentEndpoint(name: string, endpointReference: EndpointReference): ProjectResourcePromise { + return new ProjectResourcePromise(this._withEnvironmentEndpointInternal(name, endpointReference)); + } + + /** @internal */ + private async _withEnvironmentParameterInternal(name: string, parameter: ParameterResource): Promise { + const rpcArgs: Record = { builder: this._handle, name, parameter }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withEnvironmentParameter', + rpcArgs + ); + return new ProjectResource(result, this._client); + } + + /** Sets an environment variable from a parameter resource */ + withEnvironmentParameter(name: string, parameter: ParameterResource): ProjectResourcePromise { + return new ProjectResourcePromise(this._withEnvironmentParameterInternal(name, parameter)); + } + + /** @internal */ + private async _withEnvironmentConnectionStringInternal(envVarName: string, resource: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, envVarName, resource }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withEnvironmentConnectionString', + rpcArgs + ); + return new ProjectResource(result, this._client); + } + + /** Sets an environment variable from a connection string resource */ + withEnvironmentConnectionString(envVarName: string, resource: ResourceBuilderBase): ProjectResourcePromise { + return new ProjectResourcePromise(this._withEnvironmentConnectionStringInternal(envVarName, resource)); + } + + /** @internal */ + private async _withArgsInternal(args: string[]): Promise { + const rpcArgs: Record = { builder: this._handle, args }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withArgs', + rpcArgs + ); + return new ProjectResource(result, this._client); + } + + /** Adds arguments */ + withArgs(args: string[]): ProjectResourcePromise { + return new ProjectResourcePromise(this._withArgsInternal(args)); + } + + /** @internal */ + private async _withArgsCallbackInternal(callback: (obj: CommandLineArgsCallbackContext) => Promise): Promise { + const callbackId = registerCallback(async (objData: unknown) => { + const objHandle = wrapIfHandle(objData) as CommandLineArgsCallbackContextHandle; + const obj = new CommandLineArgsCallbackContext(objHandle, this._client); + await callback(obj); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withArgsCallback', + rpcArgs + ); + return new ProjectResource(result, this._client); + } + + /** Sets command-line arguments via callback */ + withArgsCallback(callback: (obj: CommandLineArgsCallbackContext) => Promise): ProjectResourcePromise { + return new ProjectResourcePromise(this._withArgsCallbackInternal(callback)); + } + + /** @internal */ + private async _withArgsCallbackAsyncInternal(callback: (arg: CommandLineArgsCallbackContext) => Promise): Promise { + const callbackId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as CommandLineArgsCallbackContextHandle; + const arg = new CommandLineArgsCallbackContext(argHandle, this._client); + await callback(arg); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withArgsCallbackAsync', + rpcArgs + ); + return new ProjectResource(result, this._client); + } + + /** Sets command-line arguments via async callback */ + withArgsCallbackAsync(callback: (arg: CommandLineArgsCallbackContext) => Promise): ProjectResourcePromise { + return new ProjectResourcePromise(this._withArgsCallbackAsyncInternal(callback)); + } + + /** @internal */ + private async _withReferenceInternal(source: ResourceBuilderBase, connectionName?: string, optional?: boolean): Promise { + const rpcArgs: Record = { builder: this._handle, source }; + if (connectionName !== undefined) rpcArgs.connectionName = connectionName; + if (optional !== undefined) rpcArgs.optional = optional; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withReference', + rpcArgs + ); + return new ProjectResource(result, this._client); + } + + /** Adds a reference to another resource */ + withReference(source: ResourceBuilderBase, options?: WithReferenceOptions): ProjectResourcePromise { + const connectionName = options?.connectionName; + const optional = options?.optional; + return new ProjectResourcePromise(this._withReferenceInternal(source, connectionName, optional)); + } + + /** @internal */ + private async _withServiceReferenceInternal(source: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, source }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withServiceReference', + rpcArgs + ); + return new ProjectResource(result, this._client); + } + + /** Adds a service discovery reference to another resource */ + withServiceReference(source: ResourceBuilderBase): ProjectResourcePromise { + return new ProjectResourcePromise(this._withServiceReferenceInternal(source)); + } + + /** @internal */ + private async _withServiceReferenceNamedInternal(source: ResourceBuilderBase, name: string): Promise { + const rpcArgs: Record = { builder: this._handle, source, name }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withServiceReferenceNamed', + rpcArgs + ); + return new ProjectResource(result, this._client); + } + + /** Adds a named service discovery reference */ + withServiceReferenceNamed(source: ResourceBuilderBase, name: string): ProjectResourcePromise { + return new ProjectResourcePromise(this._withServiceReferenceNamedInternal(source, name)); + } + + /** @internal */ + private async _withReferenceUriInternal(name: string, uri: string): Promise { + const rpcArgs: Record = { builder: this._handle, name, uri }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withReferenceUri', + rpcArgs + ); + return new ProjectResource(result, this._client); + } + + /** Adds a reference to a URI */ + withReferenceUri(name: string, uri: string): ProjectResourcePromise { + return new ProjectResourcePromise(this._withReferenceUriInternal(name, uri)); + } + + /** @internal */ + private async _withReferenceExternalServiceInternal(externalService: ExternalServiceResource): Promise { + const rpcArgs: Record = { builder: this._handle, externalService }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withReferenceExternalService', + rpcArgs + ); + return new ProjectResource(result, this._client); + } + + /** Adds a reference to an external service */ + withReferenceExternalService(externalService: ExternalServiceResource): ProjectResourcePromise { + return new ProjectResourcePromise(this._withReferenceExternalServiceInternal(externalService)); + } + + /** @internal */ + private async _withReferenceEndpointInternal(endpointReference: EndpointReference): Promise { + const rpcArgs: Record = { builder: this._handle, endpointReference }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withReferenceEndpoint', + rpcArgs + ); + return new ProjectResource(result, this._client); + } + + /** Adds a reference to an endpoint */ + withReferenceEndpoint(endpointReference: EndpointReference): ProjectResourcePromise { + return new ProjectResourcePromise(this._withReferenceEndpointInternal(endpointReference)); + } + + /** @internal */ + private async _withEndpointInternal(port?: number, targetPort?: number, scheme?: string, name?: string, env?: string, isProxied?: boolean, isExternal?: boolean, protocol?: ProtocolType): Promise { + const rpcArgs: Record = { builder: this._handle }; + if (port !== undefined) rpcArgs.port = port; + if (targetPort !== undefined) rpcArgs.targetPort = targetPort; + if (scheme !== undefined) rpcArgs.scheme = scheme; + if (name !== undefined) rpcArgs.name = name; + if (env !== undefined) rpcArgs.env = env; + if (isProxied !== undefined) rpcArgs.isProxied = isProxied; + if (isExternal !== undefined) rpcArgs.isExternal = isExternal; + if (protocol !== undefined) rpcArgs.protocol = protocol; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withEndpoint', + rpcArgs + ); + return new ProjectResource(result, this._client); + } + + /** Adds a network endpoint */ + withEndpoint(options?: WithEndpointOptions): ProjectResourcePromise { + const port = options?.port; + const targetPort = options?.targetPort; + const scheme = options?.scheme; + const name = options?.name; + const env = options?.env; + const isProxied = options?.isProxied; + const isExternal = options?.isExternal; + const protocol = options?.protocol; + return new ProjectResourcePromise(this._withEndpointInternal(port, targetPort, scheme, name, env, isProxied, isExternal, protocol)); + } + + /** @internal */ + private async _withHttpEndpointInternal(port?: number, targetPort?: number, name?: string, env?: string, isProxied?: boolean): Promise { + const rpcArgs: Record = { builder: this._handle }; + if (port !== undefined) rpcArgs.port = port; + if (targetPort !== undefined) rpcArgs.targetPort = targetPort; + if (name !== undefined) rpcArgs.name = name; + if (env !== undefined) rpcArgs.env = env; + if (isProxied !== undefined) rpcArgs.isProxied = isProxied; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withHttpEndpoint', + rpcArgs + ); + return new ProjectResource(result, this._client); + } + + /** Adds an HTTP endpoint */ + withHttpEndpoint(options?: WithHttpEndpointOptions): ProjectResourcePromise { + const port = options?.port; + const targetPort = options?.targetPort; + const name = options?.name; + const env = options?.env; + const isProxied = options?.isProxied; + return new ProjectResourcePromise(this._withHttpEndpointInternal(port, targetPort, name, env, isProxied)); + } + + /** @internal */ + private async _withHttpsEndpointInternal(port?: number, targetPort?: number, name?: string, env?: string, isProxied?: boolean): Promise { + const rpcArgs: Record = { builder: this._handle }; + if (port !== undefined) rpcArgs.port = port; + if (targetPort !== undefined) rpcArgs.targetPort = targetPort; + if (name !== undefined) rpcArgs.name = name; + if (env !== undefined) rpcArgs.env = env; + if (isProxied !== undefined) rpcArgs.isProxied = isProxied; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withHttpsEndpoint', + rpcArgs + ); + return new ProjectResource(result, this._client); + } + + /** Adds an HTTPS endpoint */ + withHttpsEndpoint(options?: WithHttpsEndpointOptions): ProjectResourcePromise { + const port = options?.port; + const targetPort = options?.targetPort; + const name = options?.name; + const env = options?.env; + const isProxied = options?.isProxied; + return new ProjectResourcePromise(this._withHttpsEndpointInternal(port, targetPort, name, env, isProxied)); + } + + /** @internal */ + private async _withExternalHttpEndpointsInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withExternalHttpEndpoints', + rpcArgs + ); + return new ProjectResource(result, this._client); + } + + /** Makes HTTP endpoints externally accessible */ + withExternalHttpEndpoints(): ProjectResourcePromise { + return new ProjectResourcePromise(this._withExternalHttpEndpointsInternal()); + } + + /** Gets an endpoint reference */ + async getEndpoint(name: string): Promise { + const rpcArgs: Record = { builder: this._handle, name }; + return await this._client.invokeCapability( + 'Aspire.Hosting/getEndpoint', + rpcArgs + ); + } + + /** @internal */ + private async _asHttp2ServiceInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/asHttp2Service', + rpcArgs + ); + return new ProjectResource(result, this._client); + } + + /** Configures resource for HTTP/2 */ + asHttp2Service(): ProjectResourcePromise { + return new ProjectResourcePromise(this._asHttp2ServiceInternal()); + } + + /** @internal */ + private async _withUrlsCallbackInternal(callback: (obj: ResourceUrlsCallbackContext) => Promise): Promise { + const callbackId = registerCallback(async (objData: unknown) => { + const objHandle = wrapIfHandle(objData) as ResourceUrlsCallbackContextHandle; + const obj = new ResourceUrlsCallbackContext(objHandle, this._client); + await callback(obj); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrlsCallback', + rpcArgs + ); + return new ProjectResource(result, this._client); + } + + /** Customizes displayed URLs via callback */ + withUrlsCallback(callback: (obj: ResourceUrlsCallbackContext) => Promise): ProjectResourcePromise { + return new ProjectResourcePromise(this._withUrlsCallbackInternal(callback)); + } + + /** @internal */ + private async _withUrlsCallbackAsyncInternal(callback: (arg: ResourceUrlsCallbackContext) => Promise): Promise { + const callbackId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as ResourceUrlsCallbackContextHandle; + const arg = new ResourceUrlsCallbackContext(argHandle, this._client); + await callback(arg); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrlsCallbackAsync', + rpcArgs + ); + return new ProjectResource(result, this._client); + } + + /** Customizes displayed URLs via async callback */ + withUrlsCallbackAsync(callback: (arg: ResourceUrlsCallbackContext) => Promise): ProjectResourcePromise { + return new ProjectResourcePromise(this._withUrlsCallbackAsyncInternal(callback)); + } + + /** @internal */ + private async _withUrlInternal(url: string, displayText?: string): Promise { + const rpcArgs: Record = { builder: this._handle, url }; + if (displayText !== undefined) rpcArgs.displayText = displayText; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrl', + rpcArgs + ); + return new ProjectResource(result, this._client); + } + + /** Adds or modifies displayed URLs */ + withUrl(url: string, options?: WithUrlOptions): ProjectResourcePromise { + const displayText = options?.displayText; + return new ProjectResourcePromise(this._withUrlInternal(url, displayText)); + } + + /** @internal */ + private async _withUrlExpressionInternal(url: ReferenceExpression, displayText?: string): Promise { + const rpcArgs: Record = { builder: this._handle, url }; + if (displayText !== undefined) rpcArgs.displayText = displayText; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrlExpression', + rpcArgs + ); + return new ProjectResource(result, this._client); + } + + /** Adds a URL using a reference expression */ + withUrlExpression(url: ReferenceExpression, options?: WithUrlExpressionOptions): ProjectResourcePromise { + const displayText = options?.displayText; + return new ProjectResourcePromise(this._withUrlExpressionInternal(url, displayText)); + } + + /** @internal */ + private async _withUrlForEndpointInternal(endpointName: string, callback: (obj: ResourceUrlAnnotation) => Promise): Promise { + const callbackId = registerCallback(async (objData: unknown) => { + const obj = wrapIfHandle(objData) as ResourceUrlAnnotation; + await callback(obj); + }); + const rpcArgs: Record = { builder: this._handle, endpointName, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrlForEndpoint', + rpcArgs + ); + return new ProjectResource(result, this._client); + } + + /** Customizes the URL for a specific endpoint via callback */ + withUrlForEndpoint(endpointName: string, callback: (obj: ResourceUrlAnnotation) => Promise): ProjectResourcePromise { + return new ProjectResourcePromise(this._withUrlForEndpointInternal(endpointName, callback)); + } + + /** @internal */ + private async _withUrlForEndpointFactoryInternal(endpointName: string, callback: (arg: EndpointReference) => Promise): Promise { + const callbackId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as EndpointReferenceHandle; + const arg = new EndpointReference(argHandle, this._client); + return await callback(arg); + }); + const rpcArgs: Record = { builder: this._handle, endpointName, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrlForEndpointFactory', + rpcArgs + ); + return new ProjectResource(result, this._client); + } + + /** Adds a URL for a specific endpoint via factory callback */ + withUrlForEndpointFactory(endpointName: string, callback: (arg: EndpointReference) => Promise): ProjectResourcePromise { + return new ProjectResourcePromise(this._withUrlForEndpointFactoryInternal(endpointName, callback)); + } + + /** @internal */ + private async _publishWithContainerFilesInternal(source: ResourceBuilderBase, destinationPath: string): Promise { + const rpcArgs: Record = { builder: this._handle, source, destinationPath }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/publishWithContainerFiles', + rpcArgs + ); + return new ProjectResource(result, this._client); + } + + /** Configures the resource to copy container files from the specified source during publishing */ + publishWithContainerFiles(source: ResourceBuilderBase, destinationPath: string): ProjectResourcePromise { + return new ProjectResourcePromise(this._publishWithContainerFilesInternal(source, destinationPath)); + } + + /** @internal */ + private async _excludeFromManifestInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/excludeFromManifest', + rpcArgs + ); + return new ProjectResource(result, this._client); + } + + /** Excludes the resource from the deployment manifest */ + excludeFromManifest(): ProjectResourcePromise { + return new ProjectResourcePromise(this._excludeFromManifestInternal()); + } + + /** @internal */ + private async _waitForInternal(dependency: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, dependency }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/waitFor', + rpcArgs + ); + return new ProjectResource(result, this._client); + } + + /** Waits for another resource to be ready */ + waitFor(dependency: ResourceBuilderBase): ProjectResourcePromise { + return new ProjectResourcePromise(this._waitForInternal(dependency)); + } + + /** @internal */ + private async _waitForWithBehaviorInternal(dependency: ResourceBuilderBase, waitBehavior: WaitBehavior): Promise { + const rpcArgs: Record = { builder: this._handle, dependency, waitBehavior }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/waitForWithBehavior', + rpcArgs + ); + return new ProjectResource(result, this._client); + } + + /** Waits for another resource with specific behavior */ + waitForWithBehavior(dependency: ResourceBuilderBase, waitBehavior: WaitBehavior): ProjectResourcePromise { + return new ProjectResourcePromise(this._waitForWithBehaviorInternal(dependency, waitBehavior)); + } + + /** @internal */ + private async _waitForStartInternal(dependency: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, dependency }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/waitForStart', + rpcArgs + ); + return new ProjectResource(result, this._client); + } + + /** Waits for another resource to start */ + waitForStart(dependency: ResourceBuilderBase): ProjectResourcePromise { + return new ProjectResourcePromise(this._waitForStartInternal(dependency)); + } + + /** @internal */ + private async _waitForStartWithBehaviorInternal(dependency: ResourceBuilderBase, waitBehavior: WaitBehavior): Promise { + const rpcArgs: Record = { builder: this._handle, dependency, waitBehavior }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/waitForStartWithBehavior', + rpcArgs + ); + return new ProjectResource(result, this._client); + } + + /** Waits for another resource to start with specific behavior */ + waitForStartWithBehavior(dependency: ResourceBuilderBase, waitBehavior: WaitBehavior): ProjectResourcePromise { + return new ProjectResourcePromise(this._waitForStartWithBehaviorInternal(dependency, waitBehavior)); + } + + /** @internal */ + private async _withExplicitStartInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withExplicitStart', + rpcArgs + ); + return new ProjectResource(result, this._client); + } + + /** Prevents resource from starting automatically */ + withExplicitStart(): ProjectResourcePromise { + return new ProjectResourcePromise(this._withExplicitStartInternal()); + } + + /** @internal */ + private async _waitForCompletionInternal(dependency: ResourceBuilderBase, exitCode?: number): Promise { + const rpcArgs: Record = { builder: this._handle, dependency }; + if (exitCode !== undefined) rpcArgs.exitCode = exitCode; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/waitForCompletion', + rpcArgs + ); + return new ProjectResource(result, this._client); + } + + /** Waits for resource completion */ + waitForCompletion(dependency: ResourceBuilderBase, options?: WaitForCompletionOptions): ProjectResourcePromise { + const exitCode = options?.exitCode; + return new ProjectResourcePromise(this._waitForCompletionInternal(dependency, exitCode)); + } + + /** @internal */ + private async _withHealthCheckInternal(key: string): Promise { + const rpcArgs: Record = { builder: this._handle, key }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withHealthCheck', + rpcArgs + ); + return new ProjectResource(result, this._client); + } + + /** Adds a health check by key */ + withHealthCheck(key: string): ProjectResourcePromise { + return new ProjectResourcePromise(this._withHealthCheckInternal(key)); + } + + /** @internal */ + private async _withHttpHealthCheckInternal(path?: string, statusCode?: number, endpointName?: string): Promise { + const rpcArgs: Record = { builder: this._handle }; + if (path !== undefined) rpcArgs.path = path; + if (statusCode !== undefined) rpcArgs.statusCode = statusCode; + if (endpointName !== undefined) rpcArgs.endpointName = endpointName; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withHttpHealthCheck', + rpcArgs + ); + return new ProjectResource(result, this._client); + } + + /** Adds an HTTP health check */ + withHttpHealthCheck(options?: WithHttpHealthCheckOptions): ProjectResourcePromise { + const path = options?.path; + const statusCode = options?.statusCode; + const endpointName = options?.endpointName; + return new ProjectResourcePromise(this._withHttpHealthCheckInternal(path, statusCode, endpointName)); + } + + /** @internal */ + private async _withCommandInternal(name: string, displayName: string, executeCommand: (arg: ExecuteCommandContext) => Promise, commandOptions?: CommandOptions): Promise { + const executeCommandId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as ExecuteCommandContextHandle; + const arg = new ExecuteCommandContext(argHandle, this._client); + return await executeCommand(arg); + }); + const rpcArgs: Record = { builder: this._handle, name, displayName, executeCommand: executeCommandId }; + if (commandOptions !== undefined) rpcArgs.commandOptions = commandOptions; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withCommand', + rpcArgs + ); + return new ProjectResource(result, this._client); + } + + /** Adds a resource command */ + withCommand(name: string, displayName: string, executeCommand: (arg: ExecuteCommandContext) => Promise, options?: WithCommandOptions): ProjectResourcePromise { + const commandOptions = options?.commandOptions; + return new ProjectResourcePromise(this._withCommandInternal(name, displayName, executeCommand, commandOptions)); + } + + /** @internal */ + private async _withDeveloperCertificateTrustInternal(trust: boolean): Promise { + const rpcArgs: Record = { builder: this._handle, trust }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withDeveloperCertificateTrust', + rpcArgs + ); + return new ProjectResource(result, this._client); + } + + /** Configures developer certificate trust */ + withDeveloperCertificateTrust(trust: boolean): ProjectResourcePromise { + return new ProjectResourcePromise(this._withDeveloperCertificateTrustInternal(trust)); + } + + /** @internal */ + private async _withCertificateTrustScopeInternal(scope: CertificateTrustScope): Promise { + const rpcArgs: Record = { builder: this._handle, scope }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withCertificateTrustScope', + rpcArgs + ); + return new ProjectResource(result, this._client); + } + + /** Sets the certificate trust scope */ + withCertificateTrustScope(scope: CertificateTrustScope): ProjectResourcePromise { + return new ProjectResourcePromise(this._withCertificateTrustScopeInternal(scope)); + } + + /** @internal */ + private async _withHttpsDeveloperCertificateInternal(password?: ParameterResource): Promise { + const rpcArgs: Record = { builder: this._handle }; + if (password !== undefined) rpcArgs.password = password; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withHttpsDeveloperCertificate', + rpcArgs + ); + return new ProjectResource(result, this._client); + } + + /** Configures HTTPS with a developer certificate */ + withHttpsDeveloperCertificate(options?: WithHttpsDeveloperCertificateOptions): ProjectResourcePromise { + const password = options?.password; + return new ProjectResourcePromise(this._withHttpsDeveloperCertificateInternal(password)); + } + + /** @internal */ + private async _withoutHttpsCertificateInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withoutHttpsCertificate', + rpcArgs + ); + return new ProjectResource(result, this._client); + } + + /** Removes HTTPS certificate configuration */ + withoutHttpsCertificate(): ProjectResourcePromise { + return new ProjectResourcePromise(this._withoutHttpsCertificateInternal()); + } + + /** @internal */ + private async _withParentRelationshipInternal(parent: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, parent }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withParentRelationship', + rpcArgs + ); + return new ProjectResource(result, this._client); + } + + /** Sets the parent relationship */ + withParentRelationship(parent: ResourceBuilderBase): ProjectResourcePromise { + return new ProjectResourcePromise(this._withParentRelationshipInternal(parent)); + } + + /** @internal */ + private async _withChildRelationshipInternal(child: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, child }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withChildRelationship', + rpcArgs + ); + return new ProjectResource(result, this._client); + } + + /** Sets a child relationship */ + withChildRelationship(child: ResourceBuilderBase): ProjectResourcePromise { + return new ProjectResourcePromise(this._withChildRelationshipInternal(child)); + } + + /** @internal */ + private async _withIconNameInternal(iconName: string, iconVariant?: IconVariant): Promise { + const rpcArgs: Record = { builder: this._handle, iconName }; + if (iconVariant !== undefined) rpcArgs.iconVariant = iconVariant; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withIconName', + rpcArgs + ); + return new ProjectResource(result, this._client); + } + + /** Sets the icon for the resource */ + withIconName(iconName: string, options?: WithIconNameOptions): ProjectResourcePromise { + const iconVariant = options?.iconVariant; + return new ProjectResourcePromise(this._withIconNameInternal(iconName, iconVariant)); + } + + /** @internal */ + private async _withHttpProbeInternal(probeType: ProbeType, path?: string, initialDelaySeconds?: number, periodSeconds?: number, timeoutSeconds?: number, failureThreshold?: number, successThreshold?: number, endpointName?: string): Promise { + const rpcArgs: Record = { builder: this._handle, probeType }; + if (path !== undefined) rpcArgs.path = path; + if (initialDelaySeconds !== undefined) rpcArgs.initialDelaySeconds = initialDelaySeconds; + if (periodSeconds !== undefined) rpcArgs.periodSeconds = periodSeconds; + if (timeoutSeconds !== undefined) rpcArgs.timeoutSeconds = timeoutSeconds; + if (failureThreshold !== undefined) rpcArgs.failureThreshold = failureThreshold; + if (successThreshold !== undefined) rpcArgs.successThreshold = successThreshold; + if (endpointName !== undefined) rpcArgs.endpointName = endpointName; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withHttpProbe', + rpcArgs + ); + return new ProjectResource(result, this._client); + } + + /** Adds an HTTP health probe to the resource */ + withHttpProbe(probeType: ProbeType, options?: WithHttpProbeOptions): ProjectResourcePromise { + const path = options?.path; + const initialDelaySeconds = options?.initialDelaySeconds; + const periodSeconds = options?.periodSeconds; + const timeoutSeconds = options?.timeoutSeconds; + const failureThreshold = options?.failureThreshold; + const successThreshold = options?.successThreshold; + const endpointName = options?.endpointName; + return new ProjectResourcePromise(this._withHttpProbeInternal(probeType, path, initialDelaySeconds, periodSeconds, timeoutSeconds, failureThreshold, successThreshold, endpointName)); + } + + /** @internal */ + private async _excludeFromMcpInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/excludeFromMcp', + rpcArgs + ); + return new ProjectResource(result, this._client); + } + + /** Excludes the resource from MCP server exposure */ + excludeFromMcp(): ProjectResourcePromise { + return new ProjectResourcePromise(this._excludeFromMcpInternal()); + } + + /** @internal */ + private async _withRemoteImageNameInternal(remoteImageName: string): Promise { + const rpcArgs: Record = { builder: this._handle, remoteImageName }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withRemoteImageName', + rpcArgs + ); + return new ProjectResource(result, this._client); + } + + /** Sets the remote image name for publishing */ + withRemoteImageName(remoteImageName: string): ProjectResourcePromise { + return new ProjectResourcePromise(this._withRemoteImageNameInternal(remoteImageName)); + } + + /** @internal */ + private async _withRemoteImageTagInternal(remoteImageTag: string): Promise { + const rpcArgs: Record = { builder: this._handle, remoteImageTag }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withRemoteImageTag', + rpcArgs + ); + return new ProjectResource(result, this._client); + } + + /** Sets the remote image tag for publishing */ + withRemoteImageTag(remoteImageTag: string): ProjectResourcePromise { + return new ProjectResourcePromise(this._withRemoteImageTagInternal(remoteImageTag)); + } + + /** @internal */ + private async _withPipelineStepFactoryInternal(stepName: string, callback: (arg: PipelineStepContext) => Promise, dependsOn?: string[], requiredBy?: string[], tags?: string[], description?: string): Promise { + const callbackId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as PipelineStepContextHandle; + const arg = new PipelineStepContext(argHandle, this._client); + await callback(arg); + }); + const rpcArgs: Record = { builder: this._handle, stepName, callback: callbackId }; + if (dependsOn !== undefined) rpcArgs.dependsOn = dependsOn; + if (requiredBy !== undefined) rpcArgs.requiredBy = requiredBy; + if (tags !== undefined) rpcArgs.tags = tags; + if (description !== undefined) rpcArgs.description = description; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withPipelineStepFactory', + rpcArgs + ); + return new ProjectResource(result, this._client); + } + + /** Adds a pipeline step to the resource */ + withPipelineStepFactory(stepName: string, callback: (arg: PipelineStepContext) => Promise, options?: WithPipelineStepFactoryOptions): ProjectResourcePromise { + const dependsOn = options?.dependsOn; + const requiredBy = options?.requiredBy; + const tags = options?.tags; + const description = options?.description; + return new ProjectResourcePromise(this._withPipelineStepFactoryInternal(stepName, callback, dependsOn, requiredBy, tags, description)); + } + + /** @internal */ + private async _withPipelineConfigurationAsyncInternal(callback: (arg: PipelineConfigurationContext) => Promise): Promise { + const callbackId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as PipelineConfigurationContextHandle; + const arg = new PipelineConfigurationContext(argHandle, this._client); + await callback(arg); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withPipelineConfigurationAsync', + rpcArgs + ); + return new ProjectResource(result, this._client); + } + + /** Configures pipeline step dependencies via an async callback */ + withPipelineConfigurationAsync(callback: (arg: PipelineConfigurationContext) => Promise): ProjectResourcePromise { + return new ProjectResourcePromise(this._withPipelineConfigurationAsyncInternal(callback)); + } + + /** @internal */ + private async _withPipelineConfigurationInternal(callback: (obj: PipelineConfigurationContext) => Promise): Promise { + const callbackId = registerCallback(async (objData: unknown) => { + const objHandle = wrapIfHandle(objData) as PipelineConfigurationContextHandle; + const obj = new PipelineConfigurationContext(objHandle, this._client); + await callback(obj); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withPipelineConfiguration', + rpcArgs + ); + return new ProjectResource(result, this._client); + } + + /** Configures pipeline step dependencies via a callback */ + withPipelineConfiguration(callback: (obj: PipelineConfigurationContext) => Promise): ProjectResourcePromise { + return new ProjectResourcePromise(this._withPipelineConfigurationInternal(callback)); + } + + /** Gets the resource name */ + async getResourceName(): Promise { + const rpcArgs: Record = { resource: this._handle }; + return await this._client.invokeCapability( + 'Aspire.Hosting/getResourceName', + rpcArgs + ); + } + + /** @internal */ + private async _withStorageRoleAssignmentsInternal(target: AzureStorageResource, roles: AzureStorageRole[]): Promise { + const rpcArgs: Record = { builder: this._handle, target, roles }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure.Storage/withStorageRoleAssignments', + rpcArgs + ); + return new ProjectResource(result, this._client); + } + + /** Assigns Azure Storage roles to a resource */ + withStorageRoleAssignments(target: AzureStorageResource, roles: AzureStorageRole[]): ProjectResourcePromise { + return new ProjectResourcePromise(this._withStorageRoleAssignmentsInternal(target, roles)); + } + + /** @internal */ + private async _withEventHubsRoleAssignmentsInternal(target: AzureEventHubsResource, roles: AzureEventHubsRole[]): Promise { + const rpcArgs: Record = { builder: this._handle, target, roles }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure.EventHubs/withEventHubsRoleAssignments', + rpcArgs + ); + return new ProjectResource(result, this._client); + } + + /** Assigns Event Hubs roles to a resource */ + withEventHubsRoleAssignments(target: AzureEventHubsResource, roles: AzureEventHubsRole[]): ProjectResourcePromise { + return new ProjectResourcePromise(this._withEventHubsRoleAssignmentsInternal(target, roles)); + } + + /** @internal */ + private async _withEnvironmentFromOutputInternal(name: string, bicepOutputReference: BicepOutputReference): Promise { + const rpcArgs: Record = { builder: this._handle, name, bicepOutputReference }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure/withEnvironmentFromOutput', + rpcArgs + ); + return new ProjectResource(result, this._client); + } + + /** Sets an environment variable from a Bicep output reference */ + withEnvironmentFromOutput(name: string, bicepOutputReference: BicepOutputReference): ProjectResourcePromise { + return new ProjectResourcePromise(this._withEnvironmentFromOutputInternal(name, bicepOutputReference)); + } + + /** @internal */ + private async _withEnvironmentFromKeyVaultSecretInternal(name: string, secretReference: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, name, secretReference }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure/withEnvironmentFromKeyVaultSecret', + rpcArgs + ); + return new ProjectResource(result, this._client); + } + + /** Sets an environment variable from an Azure Key Vault secret reference */ + withEnvironmentFromKeyVaultSecret(name: string, secretReference: ResourceBuilderBase): ProjectResourcePromise { + return new ProjectResourcePromise(this._withEnvironmentFromKeyVaultSecretInternal(name, secretReference)); + } + + /** @internal */ + private async _withAzureUserAssignedIdentityInternal(identityResourceBuilder: AzureUserAssignedIdentityResource): Promise { + const rpcArgs: Record = { builder: this._handle, identityResourceBuilder }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure/withUserAssignedIdentityAzureUserAssignedIdentity', + rpcArgs + ); + return new ProjectResource(result, this._client); + } + + /** Associates an Azure user-assigned identity with a compute resource */ + withAzureUserAssignedIdentity(identityResourceBuilder: AzureUserAssignedIdentityResource): ProjectResourcePromise { + return new ProjectResourcePromise(this._withAzureUserAssignedIdentityInternal(identityResourceBuilder)); + } + +} + +/** + * Thenable wrapper for ProjectResource that enables fluent chaining. + * @example + * await builder.addSomething().withX().withY(); + */ +export class ProjectResourcePromise implements PromiseLike { + constructor(private _promise: Promise) {} + + then( + onfulfilled?: ((value: ProjectResource) => TResult1 | PromiseLike) | null, + onrejected?: ((reason: unknown) => TResult2 | PromiseLike) | null + ): PromiseLike { + return this._promise.then(onfulfilled, onrejected); + } + + /** Configures a resource to use a container registry */ + withContainerRegistry(registry: ResourceBuilderBase): ProjectResourcePromise { + return new ProjectResourcePromise(this._promise.then(obj => obj.withContainerRegistry(registry))); + } + + /** Sets the base image for a Dockerfile build */ + withDockerfileBaseImage(options?: WithDockerfileBaseImageOptions): ProjectResourcePromise { + return new ProjectResourcePromise(this._promise.then(obj => obj.withDockerfileBaseImage(options))); + } + + /** Configures an MCP server endpoint on the resource */ + withMcpServer(options?: WithMcpServerOptions): ProjectResourcePromise { + return new ProjectResourcePromise(this._promise.then(obj => obj.withMcpServer(options))); + } + + /** Configures OTLP telemetry export */ + withOtlpExporter(): ProjectResourcePromise { + return new ProjectResourcePromise(this._promise.then(obj => obj.withOtlpExporter())); + } + + /** Configures OTLP telemetry export with specific protocol */ + withOtlpExporterProtocol(protocol: OtlpProtocol): ProjectResourcePromise { + return new ProjectResourcePromise(this._promise.then(obj => obj.withOtlpExporterProtocol(protocol))); + } + + /** Adds a required command dependency */ + withRequiredCommand(command: string, options?: WithRequiredCommandOptions): ProjectResourcePromise { + return new ProjectResourcePromise(this._promise.then(obj => obj.withRequiredCommand(command, options))); + } + + /** Sets an environment variable */ + withEnvironment(name: string, value: string): ProjectResourcePromise { + return new ProjectResourcePromise(this._promise.then(obj => obj.withEnvironment(name, value))); + } + + /** Adds an environment variable with a reference expression */ + withEnvironmentExpression(name: string, value: ReferenceExpression): ProjectResourcePromise { + return new ProjectResourcePromise(this._promise.then(obj => obj.withEnvironmentExpression(name, value))); + } + + /** Sets environment variables via callback */ + withEnvironmentCallback(callback: (obj: EnvironmentCallbackContext) => Promise): ProjectResourcePromise { + return new ProjectResourcePromise(this._promise.then(obj => obj.withEnvironmentCallback(callback))); + } + + /** Sets environment variables via async callback */ + withEnvironmentCallbackAsync(callback: (arg: EnvironmentCallbackContext) => Promise): ProjectResourcePromise { + return new ProjectResourcePromise(this._promise.then(obj => obj.withEnvironmentCallbackAsync(callback))); + } + + /** Sets an environment variable from an endpoint reference */ + withEnvironmentEndpoint(name: string, endpointReference: EndpointReference): ProjectResourcePromise { + return new ProjectResourcePromise(this._promise.then(obj => obj.withEnvironmentEndpoint(name, endpointReference))); + } + + /** Sets an environment variable from a parameter resource */ + withEnvironmentParameter(name: string, parameter: ParameterResource): ProjectResourcePromise { + return new ProjectResourcePromise(this._promise.then(obj => obj.withEnvironmentParameter(name, parameter))); + } + + /** Sets an environment variable from a connection string resource */ + withEnvironmentConnectionString(envVarName: string, resource: ResourceBuilderBase): ProjectResourcePromise { + return new ProjectResourcePromise(this._promise.then(obj => obj.withEnvironmentConnectionString(envVarName, resource))); + } + + /** Adds arguments */ + withArgs(args: string[]): ProjectResourcePromise { + return new ProjectResourcePromise(this._promise.then(obj => obj.withArgs(args))); + } + + /** Sets command-line arguments via callback */ + withArgsCallback(callback: (obj: CommandLineArgsCallbackContext) => Promise): ProjectResourcePromise { + return new ProjectResourcePromise(this._promise.then(obj => obj.withArgsCallback(callback))); + } + + /** Sets command-line arguments via async callback */ + withArgsCallbackAsync(callback: (arg: CommandLineArgsCallbackContext) => Promise): ProjectResourcePromise { + return new ProjectResourcePromise(this._promise.then(obj => obj.withArgsCallbackAsync(callback))); + } + + /** Adds a reference to another resource */ + withReference(source: ResourceBuilderBase, options?: WithReferenceOptions): ProjectResourcePromise { + return new ProjectResourcePromise(this._promise.then(obj => obj.withReference(source, options))); + } + + /** Adds a service discovery reference to another resource */ + withServiceReference(source: ResourceBuilderBase): ProjectResourcePromise { + return new ProjectResourcePromise(this._promise.then(obj => obj.withServiceReference(source))); + } + + /** Adds a named service discovery reference */ + withServiceReferenceNamed(source: ResourceBuilderBase, name: string): ProjectResourcePromise { + return new ProjectResourcePromise(this._promise.then(obj => obj.withServiceReferenceNamed(source, name))); + } + + /** Adds a reference to a URI */ + withReferenceUri(name: string, uri: string): ProjectResourcePromise { + return new ProjectResourcePromise(this._promise.then(obj => obj.withReferenceUri(name, uri))); + } + + /** Adds a reference to an external service */ + withReferenceExternalService(externalService: ExternalServiceResource): ProjectResourcePromise { + return new ProjectResourcePromise(this._promise.then(obj => obj.withReferenceExternalService(externalService))); + } + + /** Adds a reference to an endpoint */ + withReferenceEndpoint(endpointReference: EndpointReference): ProjectResourcePromise { + return new ProjectResourcePromise(this._promise.then(obj => obj.withReferenceEndpoint(endpointReference))); + } + + /** Adds a network endpoint */ + withEndpoint(options?: WithEndpointOptions): ProjectResourcePromise { + return new ProjectResourcePromise(this._promise.then(obj => obj.withEndpoint(options))); + } + + /** Adds an HTTP endpoint */ + withHttpEndpoint(options?: WithHttpEndpointOptions): ProjectResourcePromise { + return new ProjectResourcePromise(this._promise.then(obj => obj.withHttpEndpoint(options))); + } + + /** Adds an HTTPS endpoint */ + withHttpsEndpoint(options?: WithHttpsEndpointOptions): ProjectResourcePromise { + return new ProjectResourcePromise(this._promise.then(obj => obj.withHttpsEndpoint(options))); + } + + /** Makes HTTP endpoints externally accessible */ + withExternalHttpEndpoints(): ProjectResourcePromise { + return new ProjectResourcePromise(this._promise.then(obj => obj.withExternalHttpEndpoints())); + } + + /** Gets an endpoint reference */ + getEndpoint(name: string): Promise { + return this._promise.then(obj => obj.getEndpoint(name)); + } + + /** Configures resource for HTTP/2 */ + asHttp2Service(): ProjectResourcePromise { + return new ProjectResourcePromise(this._promise.then(obj => obj.asHttp2Service())); + } + + /** Customizes displayed URLs via callback */ + withUrlsCallback(callback: (obj: ResourceUrlsCallbackContext) => Promise): ProjectResourcePromise { + return new ProjectResourcePromise(this._promise.then(obj => obj.withUrlsCallback(callback))); + } + + /** Customizes displayed URLs via async callback */ + withUrlsCallbackAsync(callback: (arg: ResourceUrlsCallbackContext) => Promise): ProjectResourcePromise { + return new ProjectResourcePromise(this._promise.then(obj => obj.withUrlsCallbackAsync(callback))); + } + + /** Adds or modifies displayed URLs */ + withUrl(url: string, options?: WithUrlOptions): ProjectResourcePromise { + return new ProjectResourcePromise(this._promise.then(obj => obj.withUrl(url, options))); + } + + /** Adds a URL using a reference expression */ + withUrlExpression(url: ReferenceExpression, options?: WithUrlExpressionOptions): ProjectResourcePromise { + return new ProjectResourcePromise(this._promise.then(obj => obj.withUrlExpression(url, options))); + } + + /** Customizes the URL for a specific endpoint via callback */ + withUrlForEndpoint(endpointName: string, callback: (obj: ResourceUrlAnnotation) => Promise): ProjectResourcePromise { + return new ProjectResourcePromise(this._promise.then(obj => obj.withUrlForEndpoint(endpointName, callback))); + } + + /** Adds a URL for a specific endpoint via factory callback */ + withUrlForEndpointFactory(endpointName: string, callback: (arg: EndpointReference) => Promise): ProjectResourcePromise { + return new ProjectResourcePromise(this._promise.then(obj => obj.withUrlForEndpointFactory(endpointName, callback))); + } + + /** Configures the resource to copy container files from the specified source during publishing */ + publishWithContainerFiles(source: ResourceBuilderBase, destinationPath: string): ProjectResourcePromise { + return new ProjectResourcePromise(this._promise.then(obj => obj.publishWithContainerFiles(source, destinationPath))); + } + + /** Excludes the resource from the deployment manifest */ + excludeFromManifest(): ProjectResourcePromise { + return new ProjectResourcePromise(this._promise.then(obj => obj.excludeFromManifest())); + } + + /** Waits for another resource to be ready */ + waitFor(dependency: ResourceBuilderBase): ProjectResourcePromise { + return new ProjectResourcePromise(this._promise.then(obj => obj.waitFor(dependency))); + } + + /** Waits for another resource with specific behavior */ + waitForWithBehavior(dependency: ResourceBuilderBase, waitBehavior: WaitBehavior): ProjectResourcePromise { + return new ProjectResourcePromise(this._promise.then(obj => obj.waitForWithBehavior(dependency, waitBehavior))); + } + + /** Waits for another resource to start */ + waitForStart(dependency: ResourceBuilderBase): ProjectResourcePromise { + return new ProjectResourcePromise(this._promise.then(obj => obj.waitForStart(dependency))); + } + + /** Waits for another resource to start with specific behavior */ + waitForStartWithBehavior(dependency: ResourceBuilderBase, waitBehavior: WaitBehavior): ProjectResourcePromise { + return new ProjectResourcePromise(this._promise.then(obj => obj.waitForStartWithBehavior(dependency, waitBehavior))); + } + + /** Prevents resource from starting automatically */ + withExplicitStart(): ProjectResourcePromise { + return new ProjectResourcePromise(this._promise.then(obj => obj.withExplicitStart())); + } + + /** Waits for resource completion */ + waitForCompletion(dependency: ResourceBuilderBase, options?: WaitForCompletionOptions): ProjectResourcePromise { + return new ProjectResourcePromise(this._promise.then(obj => obj.waitForCompletion(dependency, options))); + } + + /** Adds a health check by key */ + withHealthCheck(key: string): ProjectResourcePromise { + return new ProjectResourcePromise(this._promise.then(obj => obj.withHealthCheck(key))); + } + + /** Adds an HTTP health check */ + withHttpHealthCheck(options?: WithHttpHealthCheckOptions): ProjectResourcePromise { + return new ProjectResourcePromise(this._promise.then(obj => obj.withHttpHealthCheck(options))); + } + + /** Adds a resource command */ + withCommand(name: string, displayName: string, executeCommand: (arg: ExecuteCommandContext) => Promise, options?: WithCommandOptions): ProjectResourcePromise { + return new ProjectResourcePromise(this._promise.then(obj => obj.withCommand(name, displayName, executeCommand, options))); + } + + /** Configures developer certificate trust */ + withDeveloperCertificateTrust(trust: boolean): ProjectResourcePromise { + return new ProjectResourcePromise(this._promise.then(obj => obj.withDeveloperCertificateTrust(trust))); + } + + /** Sets the certificate trust scope */ + withCertificateTrustScope(scope: CertificateTrustScope): ProjectResourcePromise { + return new ProjectResourcePromise(this._promise.then(obj => obj.withCertificateTrustScope(scope))); + } + + /** Configures HTTPS with a developer certificate */ + withHttpsDeveloperCertificate(options?: WithHttpsDeveloperCertificateOptions): ProjectResourcePromise { + return new ProjectResourcePromise(this._promise.then(obj => obj.withHttpsDeveloperCertificate(options))); + } + + /** Removes HTTPS certificate configuration */ + withoutHttpsCertificate(): ProjectResourcePromise { + return new ProjectResourcePromise(this._promise.then(obj => obj.withoutHttpsCertificate())); + } + + /** Sets the parent relationship */ + withParentRelationship(parent: ResourceBuilderBase): ProjectResourcePromise { + return new ProjectResourcePromise(this._promise.then(obj => obj.withParentRelationship(parent))); + } + + /** Sets a child relationship */ + withChildRelationship(child: ResourceBuilderBase): ProjectResourcePromise { + return new ProjectResourcePromise(this._promise.then(obj => obj.withChildRelationship(child))); + } + + /** Sets the icon for the resource */ + withIconName(iconName: string, options?: WithIconNameOptions): ProjectResourcePromise { + return new ProjectResourcePromise(this._promise.then(obj => obj.withIconName(iconName, options))); + } + + /** Adds an HTTP health probe to the resource */ + withHttpProbe(probeType: ProbeType, options?: WithHttpProbeOptions): ProjectResourcePromise { + return new ProjectResourcePromise(this._promise.then(obj => obj.withHttpProbe(probeType, options))); + } + + /** Excludes the resource from MCP server exposure */ + excludeFromMcp(): ProjectResourcePromise { + return new ProjectResourcePromise(this._promise.then(obj => obj.excludeFromMcp())); + } + + /** Sets the remote image name for publishing */ + withRemoteImageName(remoteImageName: string): ProjectResourcePromise { + return new ProjectResourcePromise(this._promise.then(obj => obj.withRemoteImageName(remoteImageName))); + } + + /** Sets the remote image tag for publishing */ + withRemoteImageTag(remoteImageTag: string): ProjectResourcePromise { + return new ProjectResourcePromise(this._promise.then(obj => obj.withRemoteImageTag(remoteImageTag))); + } + + /** Adds a pipeline step to the resource */ + withPipelineStepFactory(stepName: string, callback: (arg: PipelineStepContext) => Promise, options?: WithPipelineStepFactoryOptions): ProjectResourcePromise { + return new ProjectResourcePromise(this._promise.then(obj => obj.withPipelineStepFactory(stepName, callback, options))); + } + + /** Configures pipeline step dependencies via an async callback */ + withPipelineConfigurationAsync(callback: (arg: PipelineConfigurationContext) => Promise): ProjectResourcePromise { + return new ProjectResourcePromise(this._promise.then(obj => obj.withPipelineConfigurationAsync(callback))); + } + + /** Configures pipeline step dependencies via a callback */ + withPipelineConfiguration(callback: (obj: PipelineConfigurationContext) => Promise): ProjectResourcePromise { + return new ProjectResourcePromise(this._promise.then(obj => obj.withPipelineConfiguration(callback))); + } + + /** Gets the resource name */ + getResourceName(): Promise { + return this._promise.then(obj => obj.getResourceName()); + } + + /** Assigns Azure Storage roles to a resource */ + withStorageRoleAssignments(target: AzureStorageResource, roles: AzureStorageRole[]): ProjectResourcePromise { + return new ProjectResourcePromise(this._promise.then(obj => obj.withStorageRoleAssignments(target, roles))); + } + + /** Assigns Event Hubs roles to a resource */ + withEventHubsRoleAssignments(target: AzureEventHubsResource, roles: AzureEventHubsRole[]): ProjectResourcePromise { + return new ProjectResourcePromise(this._promise.then(obj => obj.withEventHubsRoleAssignments(target, roles))); + } + + /** Sets an environment variable from a Bicep output reference */ + withEnvironmentFromOutput(name: string, bicepOutputReference: BicepOutputReference): ProjectResourcePromise { + return new ProjectResourcePromise(this._promise.then(obj => obj.withEnvironmentFromOutput(name, bicepOutputReference))); + } + + /** Sets an environment variable from an Azure Key Vault secret reference */ + withEnvironmentFromKeyVaultSecret(name: string, secretReference: ResourceBuilderBase): ProjectResourcePromise { + return new ProjectResourcePromise(this._promise.then(obj => obj.withEnvironmentFromKeyVaultSecret(name, secretReference))); + } + + /** Associates an Azure user-assigned identity with a compute resource */ + withAzureUserAssignedIdentity(identityResourceBuilder: AzureUserAssignedIdentityResource): ProjectResourcePromise { + return new ProjectResourcePromise(this._promise.then(obj => obj.withAzureUserAssignedIdentity(identityResourceBuilder))); + } + +} + +// ============================================================================ +// ViteAppResource +// ============================================================================ + +export class ViteAppResource extends ResourceBuilderBase { + constructor(handle: ViteAppResourceHandle, client: AspireClientRpc) { + super(handle, client); + } + + /** Gets the Command property */ + command = { + get: async (): Promise => { + return await this._client.invokeCapability( + 'Aspire.Hosting.JavaScript/JavaScriptAppResource.command', + { context: this._handle } + ); + }, + }; + + /** Gets the WorkingDirectory property */ + workingDirectory = { + get: async (): Promise => { + return await this._client.invokeCapability( + 'Aspire.Hosting.JavaScript/JavaScriptAppResource.workingDirectory', + { context: this._handle } + ); + }, + }; + + /** Gets the Name property */ + name = { + get: async (): Promise => { + return await this._client.invokeCapability( + 'Aspire.Hosting.JavaScript/JavaScriptAppResource.name', + { context: this._handle } + ); + }, + }; + + /** @internal */ + private async _withContainerRegistryInternal(registry: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, registry }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withContainerRegistry', + rpcArgs + ); + return new ViteAppResource(result, this._client); + } + + /** Configures a resource to use a container registry */ + withContainerRegistry(registry: ResourceBuilderBase): ViteAppResourcePromise { + return new ViteAppResourcePromise(this._withContainerRegistryInternal(registry)); + } + + /** @internal */ + private async _withDockerfileBaseImageInternal(buildImage?: string, runtimeImage?: string): Promise { + const rpcArgs: Record = { builder: this._handle }; + if (buildImage !== undefined) rpcArgs.buildImage = buildImage; + if (runtimeImage !== undefined) rpcArgs.runtimeImage = runtimeImage; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withDockerfileBaseImage', + rpcArgs + ); + return new ViteAppResource(result, this._client); + } + + /** Sets the base image for a Dockerfile build */ + withDockerfileBaseImage(options?: WithDockerfileBaseImageOptions): ViteAppResourcePromise { + const buildImage = options?.buildImage; + const runtimeImage = options?.runtimeImage; + return new ViteAppResourcePromise(this._withDockerfileBaseImageInternal(buildImage, runtimeImage)); + } + + /** @internal */ + private async _publishAsDockerFileInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/publishAsDockerFile', + rpcArgs + ); + return new ViteAppResource(result, this._client); + } + + /** Publishes the executable as a Docker container */ + publishAsDockerFile(): ViteAppResourcePromise { + return new ViteAppResourcePromise(this._publishAsDockerFileInternal()); + } + + /** @internal */ + private async _publishAsDockerFileWithConfigureInternal(configure: (obj: ContainerResource) => Promise): Promise { + const configureId = registerCallback(async (objData: unknown) => { + const objHandle = wrapIfHandle(objData) as ContainerResourceHandle; + const obj = new ContainerResource(objHandle, this._client); + await configure(obj); + }); + const rpcArgs: Record = { builder: this._handle, configure: configureId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/publishAsDockerFileWithConfigure', + rpcArgs + ); + return new ViteAppResource(result, this._client); + } + + /** Publishes an executable as a Docker file with optional container configuration */ + publishAsDockerFileWithConfigure(configure: (obj: ContainerResource) => Promise): ViteAppResourcePromise { + return new ViteAppResourcePromise(this._publishAsDockerFileWithConfigureInternal(configure)); + } + + /** @internal */ + private async _withExecutableCommandInternal(command: string): Promise { + const rpcArgs: Record = { builder: this._handle, command }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withExecutableCommand', + rpcArgs + ); + return new ViteAppResource(result, this._client); + } + + /** Sets the executable command */ + withExecutableCommand(command: string): ViteAppResourcePromise { + return new ViteAppResourcePromise(this._withExecutableCommandInternal(command)); + } + + /** @internal */ + private async _withWorkingDirectoryInternal(workingDirectory: string): Promise { + const rpcArgs: Record = { builder: this._handle, workingDirectory }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withWorkingDirectory', + rpcArgs + ); + return new ViteAppResource(result, this._client); + } + + /** Sets the executable working directory */ + withWorkingDirectory(workingDirectory: string): ViteAppResourcePromise { + return new ViteAppResourcePromise(this._withWorkingDirectoryInternal(workingDirectory)); + } + + /** @internal */ + private async _withMcpServerInternal(path?: string, endpointName?: string): Promise { + const rpcArgs: Record = { builder: this._handle }; + if (path !== undefined) rpcArgs.path = path; + if (endpointName !== undefined) rpcArgs.endpointName = endpointName; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withMcpServer', + rpcArgs + ); + return new ViteAppResource(result, this._client); + } + + /** Configures an MCP server endpoint on the resource */ + withMcpServer(options?: WithMcpServerOptions): ViteAppResourcePromise { + const path = options?.path; + const endpointName = options?.endpointName; + return new ViteAppResourcePromise(this._withMcpServerInternal(path, endpointName)); + } + + /** @internal */ + private async _withOtlpExporterInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withOtlpExporter', + rpcArgs + ); + return new ViteAppResource(result, this._client); + } + + /** Configures OTLP telemetry export */ + withOtlpExporter(): ViteAppResourcePromise { + return new ViteAppResourcePromise(this._withOtlpExporterInternal()); + } + + /** @internal */ + private async _withOtlpExporterProtocolInternal(protocol: OtlpProtocol): Promise { + const rpcArgs: Record = { builder: this._handle, protocol }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withOtlpExporterProtocol', + rpcArgs + ); + return new ViteAppResource(result, this._client); + } + + /** Configures OTLP telemetry export with specific protocol */ + withOtlpExporterProtocol(protocol: OtlpProtocol): ViteAppResourcePromise { + return new ViteAppResourcePromise(this._withOtlpExporterProtocolInternal(protocol)); + } + + /** @internal */ + private async _withRequiredCommandInternal(command: string, helpLink?: string): Promise { + const rpcArgs: Record = { builder: this._handle, command }; + if (helpLink !== undefined) rpcArgs.helpLink = helpLink; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withRequiredCommand', + rpcArgs + ); + return new ViteAppResource(result, this._client); + } + + /** Adds a required command dependency */ + withRequiredCommand(command: string, options?: WithRequiredCommandOptions): ViteAppResourcePromise { + const helpLink = options?.helpLink; + return new ViteAppResourcePromise(this._withRequiredCommandInternal(command, helpLink)); + } + + /** @internal */ + private async _withEnvironmentInternal(name: string, value: string): Promise { + const rpcArgs: Record = { builder: this._handle, name, value }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withEnvironment', + rpcArgs + ); + return new ViteAppResource(result, this._client); + } + + /** Sets an environment variable */ + withEnvironment(name: string, value: string): ViteAppResourcePromise { + return new ViteAppResourcePromise(this._withEnvironmentInternal(name, value)); + } + + /** @internal */ + private async _withEnvironmentExpressionInternal(name: string, value: ReferenceExpression): Promise { + const rpcArgs: Record = { builder: this._handle, name, value }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withEnvironmentExpression', + rpcArgs + ); + return new ViteAppResource(result, this._client); + } + + /** Adds an environment variable with a reference expression */ + withEnvironmentExpression(name: string, value: ReferenceExpression): ViteAppResourcePromise { + return new ViteAppResourcePromise(this._withEnvironmentExpressionInternal(name, value)); + } + + /** @internal */ + private async _withEnvironmentCallbackInternal(callback: (obj: EnvironmentCallbackContext) => Promise): Promise { + const callbackId = registerCallback(async (objData: unknown) => { + const objHandle = wrapIfHandle(objData) as EnvironmentCallbackContextHandle; + const obj = new EnvironmentCallbackContext(objHandle, this._client); + await callback(obj); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withEnvironmentCallback', + rpcArgs + ); + return new ViteAppResource(result, this._client); + } + + /** Sets environment variables via callback */ + withEnvironmentCallback(callback: (obj: EnvironmentCallbackContext) => Promise): ViteAppResourcePromise { + return new ViteAppResourcePromise(this._withEnvironmentCallbackInternal(callback)); + } + + /** @internal */ + private async _withEnvironmentCallbackAsyncInternal(callback: (arg: EnvironmentCallbackContext) => Promise): Promise { + const callbackId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as EnvironmentCallbackContextHandle; + const arg = new EnvironmentCallbackContext(argHandle, this._client); + await callback(arg); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withEnvironmentCallbackAsync', + rpcArgs + ); + return new ViteAppResource(result, this._client); + } + + /** Sets environment variables via async callback */ + withEnvironmentCallbackAsync(callback: (arg: EnvironmentCallbackContext) => Promise): ViteAppResourcePromise { + return new ViteAppResourcePromise(this._withEnvironmentCallbackAsyncInternal(callback)); + } + + /** @internal */ + private async _withEnvironmentEndpointInternal(name: string, endpointReference: EndpointReference): Promise { + const rpcArgs: Record = { builder: this._handle, name, endpointReference }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withEnvironmentEndpoint', + rpcArgs + ); + return new ViteAppResource(result, this._client); + } + + /** Sets an environment variable from an endpoint reference */ + withEnvironmentEndpoint(name: string, endpointReference: EndpointReference): ViteAppResourcePromise { + return new ViteAppResourcePromise(this._withEnvironmentEndpointInternal(name, endpointReference)); + } + + /** @internal */ + private async _withEnvironmentParameterInternal(name: string, parameter: ParameterResource): Promise { + const rpcArgs: Record = { builder: this._handle, name, parameter }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withEnvironmentParameter', + rpcArgs + ); + return new ViteAppResource(result, this._client); + } + + /** Sets an environment variable from a parameter resource */ + withEnvironmentParameter(name: string, parameter: ParameterResource): ViteAppResourcePromise { + return new ViteAppResourcePromise(this._withEnvironmentParameterInternal(name, parameter)); + } + + /** @internal */ + private async _withEnvironmentConnectionStringInternal(envVarName: string, resource: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, envVarName, resource }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withEnvironmentConnectionString', + rpcArgs + ); + return new ViteAppResource(result, this._client); + } + + /** Sets an environment variable from a connection string resource */ + withEnvironmentConnectionString(envVarName: string, resource: ResourceBuilderBase): ViteAppResourcePromise { + return new ViteAppResourcePromise(this._withEnvironmentConnectionStringInternal(envVarName, resource)); + } + + /** @internal */ + private async _withArgsInternal(args: string[]): Promise { + const rpcArgs: Record = { builder: this._handle, args }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withArgs', + rpcArgs + ); + return new ViteAppResource(result, this._client); + } + + /** Adds arguments */ + withArgs(args: string[]): ViteAppResourcePromise { + return new ViteAppResourcePromise(this._withArgsInternal(args)); + } + + /** @internal */ + private async _withArgsCallbackInternal(callback: (obj: CommandLineArgsCallbackContext) => Promise): Promise { + const callbackId = registerCallback(async (objData: unknown) => { + const objHandle = wrapIfHandle(objData) as CommandLineArgsCallbackContextHandle; + const obj = new CommandLineArgsCallbackContext(objHandle, this._client); + await callback(obj); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withArgsCallback', + rpcArgs + ); + return new ViteAppResource(result, this._client); + } + + /** Sets command-line arguments via callback */ + withArgsCallback(callback: (obj: CommandLineArgsCallbackContext) => Promise): ViteAppResourcePromise { + return new ViteAppResourcePromise(this._withArgsCallbackInternal(callback)); + } + + /** @internal */ + private async _withArgsCallbackAsyncInternal(callback: (arg: CommandLineArgsCallbackContext) => Promise): Promise { + const callbackId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as CommandLineArgsCallbackContextHandle; + const arg = new CommandLineArgsCallbackContext(argHandle, this._client); + await callback(arg); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withArgsCallbackAsync', + rpcArgs + ); + return new ViteAppResource(result, this._client); + } + + /** Sets command-line arguments via async callback */ + withArgsCallbackAsync(callback: (arg: CommandLineArgsCallbackContext) => Promise): ViteAppResourcePromise { + return new ViteAppResourcePromise(this._withArgsCallbackAsyncInternal(callback)); + } + + /** @internal */ + private async _withReferenceInternal(source: ResourceBuilderBase, connectionName?: string, optional?: boolean): Promise { + const rpcArgs: Record = { builder: this._handle, source }; + if (connectionName !== undefined) rpcArgs.connectionName = connectionName; + if (optional !== undefined) rpcArgs.optional = optional; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withReference', + rpcArgs + ); + return new ViteAppResource(result, this._client); + } + + /** Adds a reference to another resource */ + withReference(source: ResourceBuilderBase, options?: WithReferenceOptions): ViteAppResourcePromise { + const connectionName = options?.connectionName; + const optional = options?.optional; + return new ViteAppResourcePromise(this._withReferenceInternal(source, connectionName, optional)); + } + + /** @internal */ + private async _withServiceReferenceInternal(source: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, source }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withServiceReference', + rpcArgs + ); + return new ViteAppResource(result, this._client); + } + + /** Adds a service discovery reference to another resource */ + withServiceReference(source: ResourceBuilderBase): ViteAppResourcePromise { + return new ViteAppResourcePromise(this._withServiceReferenceInternal(source)); + } + + /** @internal */ + private async _withServiceReferenceNamedInternal(source: ResourceBuilderBase, name: string): Promise { + const rpcArgs: Record = { builder: this._handle, source, name }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withServiceReferenceNamed', + rpcArgs + ); + return new ViteAppResource(result, this._client); + } + + /** Adds a named service discovery reference */ + withServiceReferenceNamed(source: ResourceBuilderBase, name: string): ViteAppResourcePromise { + return new ViteAppResourcePromise(this._withServiceReferenceNamedInternal(source, name)); + } + + /** @internal */ + private async _withReferenceUriInternal(name: string, uri: string): Promise { + const rpcArgs: Record = { builder: this._handle, name, uri }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withReferenceUri', + rpcArgs + ); + return new ViteAppResource(result, this._client); + } + + /** Adds a reference to a URI */ + withReferenceUri(name: string, uri: string): ViteAppResourcePromise { + return new ViteAppResourcePromise(this._withReferenceUriInternal(name, uri)); + } + + /** @internal */ + private async _withReferenceExternalServiceInternal(externalService: ExternalServiceResource): Promise { + const rpcArgs: Record = { builder: this._handle, externalService }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withReferenceExternalService', + rpcArgs + ); + return new ViteAppResource(result, this._client); + } + + /** Adds a reference to an external service */ + withReferenceExternalService(externalService: ExternalServiceResource): ViteAppResourcePromise { + return new ViteAppResourcePromise(this._withReferenceExternalServiceInternal(externalService)); + } + + /** @internal */ + private async _withReferenceEndpointInternal(endpointReference: EndpointReference): Promise { + const rpcArgs: Record = { builder: this._handle, endpointReference }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withReferenceEndpoint', + rpcArgs + ); + return new ViteAppResource(result, this._client); + } + + /** Adds a reference to an endpoint */ + withReferenceEndpoint(endpointReference: EndpointReference): ViteAppResourcePromise { + return new ViteAppResourcePromise(this._withReferenceEndpointInternal(endpointReference)); + } + + /** @internal */ + private async _withEndpointInternal(port?: number, targetPort?: number, scheme?: string, name?: string, env?: string, isProxied?: boolean, isExternal?: boolean, protocol?: ProtocolType): Promise { + const rpcArgs: Record = { builder: this._handle }; + if (port !== undefined) rpcArgs.port = port; + if (targetPort !== undefined) rpcArgs.targetPort = targetPort; + if (scheme !== undefined) rpcArgs.scheme = scheme; + if (name !== undefined) rpcArgs.name = name; + if (env !== undefined) rpcArgs.env = env; + if (isProxied !== undefined) rpcArgs.isProxied = isProxied; + if (isExternal !== undefined) rpcArgs.isExternal = isExternal; + if (protocol !== undefined) rpcArgs.protocol = protocol; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withEndpoint', + rpcArgs + ); + return new ViteAppResource(result, this._client); + } + + /** Adds a network endpoint */ + withEndpoint(options?: WithEndpointOptions): ViteAppResourcePromise { + const port = options?.port; + const targetPort = options?.targetPort; + const scheme = options?.scheme; + const name = options?.name; + const env = options?.env; + const isProxied = options?.isProxied; + const isExternal = options?.isExternal; + const protocol = options?.protocol; + return new ViteAppResourcePromise(this._withEndpointInternal(port, targetPort, scheme, name, env, isProxied, isExternal, protocol)); + } + + /** @internal */ + private async _withHttpEndpointInternal(port?: number, targetPort?: number, name?: string, env?: string, isProxied?: boolean): Promise { + const rpcArgs: Record = { builder: this._handle }; + if (port !== undefined) rpcArgs.port = port; + if (targetPort !== undefined) rpcArgs.targetPort = targetPort; + if (name !== undefined) rpcArgs.name = name; + if (env !== undefined) rpcArgs.env = env; + if (isProxied !== undefined) rpcArgs.isProxied = isProxied; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withHttpEndpoint', + rpcArgs + ); + return new ViteAppResource(result, this._client); + } + + /** Adds an HTTP endpoint */ + withHttpEndpoint(options?: WithHttpEndpointOptions): ViteAppResourcePromise { + const port = options?.port; + const targetPort = options?.targetPort; + const name = options?.name; + const env = options?.env; + const isProxied = options?.isProxied; + return new ViteAppResourcePromise(this._withHttpEndpointInternal(port, targetPort, name, env, isProxied)); + } + + /** @internal */ + private async _withHttpsEndpointInternal(port?: number, targetPort?: number, name?: string, env?: string, isProxied?: boolean): Promise { + const rpcArgs: Record = { builder: this._handle }; + if (port !== undefined) rpcArgs.port = port; + if (targetPort !== undefined) rpcArgs.targetPort = targetPort; + if (name !== undefined) rpcArgs.name = name; + if (env !== undefined) rpcArgs.env = env; + if (isProxied !== undefined) rpcArgs.isProxied = isProxied; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withHttpsEndpoint', + rpcArgs + ); + return new ViteAppResource(result, this._client); + } + + /** Adds an HTTPS endpoint */ + withHttpsEndpoint(options?: WithHttpsEndpointOptions): ViteAppResourcePromise { + const port = options?.port; + const targetPort = options?.targetPort; + const name = options?.name; + const env = options?.env; + const isProxied = options?.isProxied; + return new ViteAppResourcePromise(this._withHttpsEndpointInternal(port, targetPort, name, env, isProxied)); + } + + /** @internal */ + private async _withExternalHttpEndpointsInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withExternalHttpEndpoints', + rpcArgs + ); + return new ViteAppResource(result, this._client); + } + + /** Makes HTTP endpoints externally accessible */ + withExternalHttpEndpoints(): ViteAppResourcePromise { + return new ViteAppResourcePromise(this._withExternalHttpEndpointsInternal()); + } + + /** Gets an endpoint reference */ + async getEndpoint(name: string): Promise { + const rpcArgs: Record = { builder: this._handle, name }; + return await this._client.invokeCapability( + 'Aspire.Hosting/getEndpoint', + rpcArgs + ); + } + + /** @internal */ + private async _asHttp2ServiceInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/asHttp2Service', + rpcArgs + ); + return new ViteAppResource(result, this._client); + } + + /** Configures resource for HTTP/2 */ + asHttp2Service(): ViteAppResourcePromise { + return new ViteAppResourcePromise(this._asHttp2ServiceInternal()); + } + + /** @internal */ + private async _withUrlsCallbackInternal(callback: (obj: ResourceUrlsCallbackContext) => Promise): Promise { + const callbackId = registerCallback(async (objData: unknown) => { + const objHandle = wrapIfHandle(objData) as ResourceUrlsCallbackContextHandle; + const obj = new ResourceUrlsCallbackContext(objHandle, this._client); + await callback(obj); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrlsCallback', + rpcArgs + ); + return new ViteAppResource(result, this._client); + } + + /** Customizes displayed URLs via callback */ + withUrlsCallback(callback: (obj: ResourceUrlsCallbackContext) => Promise): ViteAppResourcePromise { + return new ViteAppResourcePromise(this._withUrlsCallbackInternal(callback)); + } + + /** @internal */ + private async _withUrlsCallbackAsyncInternal(callback: (arg: ResourceUrlsCallbackContext) => Promise): Promise { + const callbackId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as ResourceUrlsCallbackContextHandle; + const arg = new ResourceUrlsCallbackContext(argHandle, this._client); + await callback(arg); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrlsCallbackAsync', + rpcArgs + ); + return new ViteAppResource(result, this._client); + } + + /** Customizes displayed URLs via async callback */ + withUrlsCallbackAsync(callback: (arg: ResourceUrlsCallbackContext) => Promise): ViteAppResourcePromise { + return new ViteAppResourcePromise(this._withUrlsCallbackAsyncInternal(callback)); + } + + /** @internal */ + private async _withUrlInternal(url: string, displayText?: string): Promise { + const rpcArgs: Record = { builder: this._handle, url }; + if (displayText !== undefined) rpcArgs.displayText = displayText; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrl', + rpcArgs + ); + return new ViteAppResource(result, this._client); + } + + /** Adds or modifies displayed URLs */ + withUrl(url: string, options?: WithUrlOptions): ViteAppResourcePromise { + const displayText = options?.displayText; + return new ViteAppResourcePromise(this._withUrlInternal(url, displayText)); + } + + /** @internal */ + private async _withUrlExpressionInternal(url: ReferenceExpression, displayText?: string): Promise { + const rpcArgs: Record = { builder: this._handle, url }; + if (displayText !== undefined) rpcArgs.displayText = displayText; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrlExpression', + rpcArgs + ); + return new ViteAppResource(result, this._client); + } + + /** Adds a URL using a reference expression */ + withUrlExpression(url: ReferenceExpression, options?: WithUrlExpressionOptions): ViteAppResourcePromise { + const displayText = options?.displayText; + return new ViteAppResourcePromise(this._withUrlExpressionInternal(url, displayText)); + } + + /** @internal */ + private async _withUrlForEndpointInternal(endpointName: string, callback: (obj: ResourceUrlAnnotation) => Promise): Promise { + const callbackId = registerCallback(async (objData: unknown) => { + const obj = wrapIfHandle(objData) as ResourceUrlAnnotation; + await callback(obj); + }); + const rpcArgs: Record = { builder: this._handle, endpointName, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrlForEndpoint', + rpcArgs + ); + return new ViteAppResource(result, this._client); + } + + /** Customizes the URL for a specific endpoint via callback */ + withUrlForEndpoint(endpointName: string, callback: (obj: ResourceUrlAnnotation) => Promise): ViteAppResourcePromise { + return new ViteAppResourcePromise(this._withUrlForEndpointInternal(endpointName, callback)); + } + + /** @internal */ + private async _withUrlForEndpointFactoryInternal(endpointName: string, callback: (arg: EndpointReference) => Promise): Promise { + const callbackId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as EndpointReferenceHandle; + const arg = new EndpointReference(argHandle, this._client); + return await callback(arg); + }); + const rpcArgs: Record = { builder: this._handle, endpointName, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrlForEndpointFactory', + rpcArgs + ); + return new ViteAppResource(result, this._client); + } + + /** Adds a URL for a specific endpoint via factory callback */ + withUrlForEndpointFactory(endpointName: string, callback: (arg: EndpointReference) => Promise): ViteAppResourcePromise { + return new ViteAppResourcePromise(this._withUrlForEndpointFactoryInternal(endpointName, callback)); + } + + /** @internal */ + private async _withContainerFilesSourceInternal(sourcePath: string): Promise { + const rpcArgs: Record = { builder: this._handle, sourcePath }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withContainerFilesSource', + rpcArgs + ); + return new ViteAppResource(result, this._client); + } + + /** Sets the source directory for container files */ + withContainerFilesSource(sourcePath: string): ViteAppResourcePromise { + return new ViteAppResourcePromise(this._withContainerFilesSourceInternal(sourcePath)); + } + + /** @internal */ + private async _clearContainerFilesSourcesInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/clearContainerFilesSources', + rpcArgs + ); + return new ViteAppResource(result, this._client); + } + + /** Clears all container file sources */ + clearContainerFilesSources(): ViteAppResourcePromise { + return new ViteAppResourcePromise(this._clearContainerFilesSourcesInternal()); + } + + /** @internal */ + private async _excludeFromManifestInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/excludeFromManifest', + rpcArgs + ); + return new ViteAppResource(result, this._client); + } + + /** Excludes the resource from the deployment manifest */ + excludeFromManifest(): ViteAppResourcePromise { + return new ViteAppResourcePromise(this._excludeFromManifestInternal()); + } + + /** @internal */ + private async _waitForInternal(dependency: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, dependency }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/waitFor', + rpcArgs + ); + return new ViteAppResource(result, this._client); + } + + /** Waits for another resource to be ready */ + waitFor(dependency: ResourceBuilderBase): ViteAppResourcePromise { + return new ViteAppResourcePromise(this._waitForInternal(dependency)); + } + + /** @internal */ + private async _waitForWithBehaviorInternal(dependency: ResourceBuilderBase, waitBehavior: WaitBehavior): Promise { + const rpcArgs: Record = { builder: this._handle, dependency, waitBehavior }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/waitForWithBehavior', + rpcArgs + ); + return new ViteAppResource(result, this._client); + } + + /** Waits for another resource with specific behavior */ + waitForWithBehavior(dependency: ResourceBuilderBase, waitBehavior: WaitBehavior): ViteAppResourcePromise { + return new ViteAppResourcePromise(this._waitForWithBehaviorInternal(dependency, waitBehavior)); + } + + /** @internal */ + private async _waitForStartInternal(dependency: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, dependency }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/waitForStart', + rpcArgs + ); + return new ViteAppResource(result, this._client); + } + + /** Waits for another resource to start */ + waitForStart(dependency: ResourceBuilderBase): ViteAppResourcePromise { + return new ViteAppResourcePromise(this._waitForStartInternal(dependency)); + } + + /** @internal */ + private async _waitForStartWithBehaviorInternal(dependency: ResourceBuilderBase, waitBehavior: WaitBehavior): Promise { + const rpcArgs: Record = { builder: this._handle, dependency, waitBehavior }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/waitForStartWithBehavior', + rpcArgs + ); + return new ViteAppResource(result, this._client); + } + + /** Waits for another resource to start with specific behavior */ + waitForStartWithBehavior(dependency: ResourceBuilderBase, waitBehavior: WaitBehavior): ViteAppResourcePromise { + return new ViteAppResourcePromise(this._waitForStartWithBehaviorInternal(dependency, waitBehavior)); + } + + /** @internal */ + private async _withExplicitStartInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withExplicitStart', + rpcArgs + ); + return new ViteAppResource(result, this._client); + } + + /** Prevents resource from starting automatically */ + withExplicitStart(): ViteAppResourcePromise { + return new ViteAppResourcePromise(this._withExplicitStartInternal()); + } + + /** @internal */ + private async _waitForCompletionInternal(dependency: ResourceBuilderBase, exitCode?: number): Promise { + const rpcArgs: Record = { builder: this._handle, dependency }; + if (exitCode !== undefined) rpcArgs.exitCode = exitCode; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/waitForCompletion', + rpcArgs + ); + return new ViteAppResource(result, this._client); + } + + /** Waits for resource completion */ + waitForCompletion(dependency: ResourceBuilderBase, options?: WaitForCompletionOptions): ViteAppResourcePromise { + const exitCode = options?.exitCode; + return new ViteAppResourcePromise(this._waitForCompletionInternal(dependency, exitCode)); + } + + /** @internal */ + private async _withHealthCheckInternal(key: string): Promise { + const rpcArgs: Record = { builder: this._handle, key }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withHealthCheck', + rpcArgs + ); + return new ViteAppResource(result, this._client); + } + + /** Adds a health check by key */ + withHealthCheck(key: string): ViteAppResourcePromise { + return new ViteAppResourcePromise(this._withHealthCheckInternal(key)); + } + + /** @internal */ + private async _withHttpHealthCheckInternal(path?: string, statusCode?: number, endpointName?: string): Promise { + const rpcArgs: Record = { builder: this._handle }; + if (path !== undefined) rpcArgs.path = path; + if (statusCode !== undefined) rpcArgs.statusCode = statusCode; + if (endpointName !== undefined) rpcArgs.endpointName = endpointName; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withHttpHealthCheck', + rpcArgs + ); + return new ViteAppResource(result, this._client); + } + + /** Adds an HTTP health check */ + withHttpHealthCheck(options?: WithHttpHealthCheckOptions): ViteAppResourcePromise { + const path = options?.path; + const statusCode = options?.statusCode; + const endpointName = options?.endpointName; + return new ViteAppResourcePromise(this._withHttpHealthCheckInternal(path, statusCode, endpointName)); + } + + /** @internal */ + private async _withCommandInternal(name: string, displayName: string, executeCommand: (arg: ExecuteCommandContext) => Promise, commandOptions?: CommandOptions): Promise { + const executeCommandId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as ExecuteCommandContextHandle; + const arg = new ExecuteCommandContext(argHandle, this._client); + return await executeCommand(arg); + }); + const rpcArgs: Record = { builder: this._handle, name, displayName, executeCommand: executeCommandId }; + if (commandOptions !== undefined) rpcArgs.commandOptions = commandOptions; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withCommand', + rpcArgs + ); + return new ViteAppResource(result, this._client); + } + + /** Adds a resource command */ + withCommand(name: string, displayName: string, executeCommand: (arg: ExecuteCommandContext) => Promise, options?: WithCommandOptions): ViteAppResourcePromise { + const commandOptions = options?.commandOptions; + return new ViteAppResourcePromise(this._withCommandInternal(name, displayName, executeCommand, commandOptions)); + } + + /** @internal */ + private async _withDeveloperCertificateTrustInternal(trust: boolean): Promise { + const rpcArgs: Record = { builder: this._handle, trust }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withDeveloperCertificateTrust', + rpcArgs + ); + return new ViteAppResource(result, this._client); + } + + /** Configures developer certificate trust */ + withDeveloperCertificateTrust(trust: boolean): ViteAppResourcePromise { + return new ViteAppResourcePromise(this._withDeveloperCertificateTrustInternal(trust)); + } + + /** @internal */ + private async _withCertificateTrustScopeInternal(scope: CertificateTrustScope): Promise { + const rpcArgs: Record = { builder: this._handle, scope }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withCertificateTrustScope', + rpcArgs + ); + return new ViteAppResource(result, this._client); + } + + /** Sets the certificate trust scope */ + withCertificateTrustScope(scope: CertificateTrustScope): ViteAppResourcePromise { + return new ViteAppResourcePromise(this._withCertificateTrustScopeInternal(scope)); + } + + /** @internal */ + private async _withHttpsDeveloperCertificateInternal(password?: ParameterResource): Promise { + const rpcArgs: Record = { builder: this._handle }; + if (password !== undefined) rpcArgs.password = password; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withHttpsDeveloperCertificate', + rpcArgs + ); + return new ViteAppResource(result, this._client); + } + + /** Configures HTTPS with a developer certificate */ + withHttpsDeveloperCertificate(options?: WithHttpsDeveloperCertificateOptions): ViteAppResourcePromise { + const password = options?.password; + return new ViteAppResourcePromise(this._withHttpsDeveloperCertificateInternal(password)); + } + + /** @internal */ + private async _withoutHttpsCertificateInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withoutHttpsCertificate', + rpcArgs + ); + return new ViteAppResource(result, this._client); + } + + /** Removes HTTPS certificate configuration */ + withoutHttpsCertificate(): ViteAppResourcePromise { + return new ViteAppResourcePromise(this._withoutHttpsCertificateInternal()); + } + + /** @internal */ + private async _withParentRelationshipInternal(parent: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, parent }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withParentRelationship', + rpcArgs + ); + return new ViteAppResource(result, this._client); + } + + /** Sets the parent relationship */ + withParentRelationship(parent: ResourceBuilderBase): ViteAppResourcePromise { + return new ViteAppResourcePromise(this._withParentRelationshipInternal(parent)); + } + + /** @internal */ + private async _withChildRelationshipInternal(child: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, child }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withChildRelationship', + rpcArgs + ); + return new ViteAppResource(result, this._client); + } + + /** Sets a child relationship */ + withChildRelationship(child: ResourceBuilderBase): ViteAppResourcePromise { + return new ViteAppResourcePromise(this._withChildRelationshipInternal(child)); + } + + /** @internal */ + private async _withIconNameInternal(iconName: string, iconVariant?: IconVariant): Promise { + const rpcArgs: Record = { builder: this._handle, iconName }; + if (iconVariant !== undefined) rpcArgs.iconVariant = iconVariant; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withIconName', + rpcArgs + ); + return new ViteAppResource(result, this._client); + } + + /** Sets the icon for the resource */ + withIconName(iconName: string, options?: WithIconNameOptions): ViteAppResourcePromise { + const iconVariant = options?.iconVariant; + return new ViteAppResourcePromise(this._withIconNameInternal(iconName, iconVariant)); + } + + /** @internal */ + private async _withHttpProbeInternal(probeType: ProbeType, path?: string, initialDelaySeconds?: number, periodSeconds?: number, timeoutSeconds?: number, failureThreshold?: number, successThreshold?: number, endpointName?: string): Promise { + const rpcArgs: Record = { builder: this._handle, probeType }; + if (path !== undefined) rpcArgs.path = path; + if (initialDelaySeconds !== undefined) rpcArgs.initialDelaySeconds = initialDelaySeconds; + if (periodSeconds !== undefined) rpcArgs.periodSeconds = periodSeconds; + if (timeoutSeconds !== undefined) rpcArgs.timeoutSeconds = timeoutSeconds; + if (failureThreshold !== undefined) rpcArgs.failureThreshold = failureThreshold; + if (successThreshold !== undefined) rpcArgs.successThreshold = successThreshold; + if (endpointName !== undefined) rpcArgs.endpointName = endpointName; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withHttpProbe', + rpcArgs + ); + return new ViteAppResource(result, this._client); + } + + /** Adds an HTTP health probe to the resource */ + withHttpProbe(probeType: ProbeType, options?: WithHttpProbeOptions): ViteAppResourcePromise { + const path = options?.path; + const initialDelaySeconds = options?.initialDelaySeconds; + const periodSeconds = options?.periodSeconds; + const timeoutSeconds = options?.timeoutSeconds; + const failureThreshold = options?.failureThreshold; + const successThreshold = options?.successThreshold; + const endpointName = options?.endpointName; + return new ViteAppResourcePromise(this._withHttpProbeInternal(probeType, path, initialDelaySeconds, periodSeconds, timeoutSeconds, failureThreshold, successThreshold, endpointName)); + } + + /** @internal */ + private async _excludeFromMcpInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/excludeFromMcp', + rpcArgs + ); + return new ViteAppResource(result, this._client); + } + + /** Excludes the resource from MCP server exposure */ + excludeFromMcp(): ViteAppResourcePromise { + return new ViteAppResourcePromise(this._excludeFromMcpInternal()); + } + + /** @internal */ + private async _withRemoteImageNameInternal(remoteImageName: string): Promise { + const rpcArgs: Record = { builder: this._handle, remoteImageName }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withRemoteImageName', + rpcArgs + ); + return new ViteAppResource(result, this._client); + } + + /** Sets the remote image name for publishing */ + withRemoteImageName(remoteImageName: string): ViteAppResourcePromise { + return new ViteAppResourcePromise(this._withRemoteImageNameInternal(remoteImageName)); + } + + /** @internal */ + private async _withRemoteImageTagInternal(remoteImageTag: string): Promise { + const rpcArgs: Record = { builder: this._handle, remoteImageTag }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withRemoteImageTag', + rpcArgs + ); + return new ViteAppResource(result, this._client); + } + + /** Sets the remote image tag for publishing */ + withRemoteImageTag(remoteImageTag: string): ViteAppResourcePromise { + return new ViteAppResourcePromise(this._withRemoteImageTagInternal(remoteImageTag)); + } + + /** @internal */ + private async _withPipelineStepFactoryInternal(stepName: string, callback: (arg: PipelineStepContext) => Promise, dependsOn?: string[], requiredBy?: string[], tags?: string[], description?: string): Promise { + const callbackId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as PipelineStepContextHandle; + const arg = new PipelineStepContext(argHandle, this._client); + await callback(arg); + }); + const rpcArgs: Record = { builder: this._handle, stepName, callback: callbackId }; + if (dependsOn !== undefined) rpcArgs.dependsOn = dependsOn; + if (requiredBy !== undefined) rpcArgs.requiredBy = requiredBy; + if (tags !== undefined) rpcArgs.tags = tags; + if (description !== undefined) rpcArgs.description = description; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withPipelineStepFactory', + rpcArgs + ); + return new ViteAppResource(result, this._client); + } + + /** Adds a pipeline step to the resource */ + withPipelineStepFactory(stepName: string, callback: (arg: PipelineStepContext) => Promise, options?: WithPipelineStepFactoryOptions): ViteAppResourcePromise { + const dependsOn = options?.dependsOn; + const requiredBy = options?.requiredBy; + const tags = options?.tags; + const description = options?.description; + return new ViteAppResourcePromise(this._withPipelineStepFactoryInternal(stepName, callback, dependsOn, requiredBy, tags, description)); + } + + /** @internal */ + private async _withPipelineConfigurationAsyncInternal(callback: (arg: PipelineConfigurationContext) => Promise): Promise { + const callbackId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as PipelineConfigurationContextHandle; + const arg = new PipelineConfigurationContext(argHandle, this._client); + await callback(arg); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withPipelineConfigurationAsync', + rpcArgs + ); + return new ViteAppResource(result, this._client); + } + + /** Configures pipeline step dependencies via an async callback */ + withPipelineConfigurationAsync(callback: (arg: PipelineConfigurationContext) => Promise): ViteAppResourcePromise { + return new ViteAppResourcePromise(this._withPipelineConfigurationAsyncInternal(callback)); + } + + /** @internal */ + private async _withPipelineConfigurationInternal(callback: (obj: PipelineConfigurationContext) => Promise): Promise { + const callbackId = registerCallback(async (objData: unknown) => { + const objHandle = wrapIfHandle(objData) as PipelineConfigurationContextHandle; + const obj = new PipelineConfigurationContext(objHandle, this._client); + await callback(obj); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withPipelineConfiguration', + rpcArgs + ); + return new ViteAppResource(result, this._client); + } + + /** Configures pipeline step dependencies via a callback */ + withPipelineConfiguration(callback: (obj: PipelineConfigurationContext) => Promise): ViteAppResourcePromise { + return new ViteAppResourcePromise(this._withPipelineConfigurationInternal(callback)); + } + + /** Gets the resource name */ + async getResourceName(): Promise { + const rpcArgs: Record = { resource: this._handle }; + return await this._client.invokeCapability( + 'Aspire.Hosting/getResourceName', + rpcArgs + ); + } + + /** @internal */ + private async _withStorageRoleAssignmentsInternal(target: AzureStorageResource, roles: AzureStorageRole[]): Promise { + const rpcArgs: Record = { builder: this._handle, target, roles }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure.Storage/withStorageRoleAssignments', + rpcArgs + ); + return new ViteAppResource(result, this._client); + } + + /** Assigns Azure Storage roles to a resource */ + withStorageRoleAssignments(target: AzureStorageResource, roles: AzureStorageRole[]): ViteAppResourcePromise { + return new ViteAppResourcePromise(this._withStorageRoleAssignmentsInternal(target, roles)); + } + + /** @internal */ + private async _withEventHubsRoleAssignmentsInternal(target: AzureEventHubsResource, roles: AzureEventHubsRole[]): Promise { + const rpcArgs: Record = { builder: this._handle, target, roles }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure.EventHubs/withEventHubsRoleAssignments', + rpcArgs + ); + return new ViteAppResource(result, this._client); + } + + /** Assigns Event Hubs roles to a resource */ + withEventHubsRoleAssignments(target: AzureEventHubsResource, roles: AzureEventHubsRole[]): ViteAppResourcePromise { + return new ViteAppResourcePromise(this._withEventHubsRoleAssignmentsInternal(target, roles)); + } + + /** @internal */ + private async _withViteConfigInternal(configPath: string): Promise { + const rpcArgs: Record = { builder: this._handle, configPath }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.JavaScript/withViteConfig', + rpcArgs + ); + return new ViteAppResource(result, this._client); + } + + /** Configures a custom Vite configuration file */ + withViteConfig(configPath: string): ViteAppResourcePromise { + return new ViteAppResourcePromise(this._withViteConfigInternal(configPath)); + } + + /** @internal */ + private async _withNpmInternal(install?: boolean, installCommand?: string, installArgs?: string[]): Promise { + const rpcArgs: Record = { resource: this._handle }; + if (install !== undefined) rpcArgs.install = install; + if (installCommand !== undefined) rpcArgs.installCommand = installCommand; + if (installArgs !== undefined) rpcArgs.installArgs = installArgs; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.JavaScript/withNpm', + rpcArgs + ); + return new ViteAppResource(result, this._client); + } + + /** Configures npm as the package manager */ + withNpm(options?: WithNpmOptions): ViteAppResourcePromise { + const install = options?.install; + const installCommand = options?.installCommand; + const installArgs = options?.installArgs; + return new ViteAppResourcePromise(this._withNpmInternal(install, installCommand, installArgs)); + } + + /** @internal */ + private async _withBunInternal(install?: boolean, installArgs?: string[]): Promise { + const rpcArgs: Record = { resource: this._handle }; + if (install !== undefined) rpcArgs.install = install; + if (installArgs !== undefined) rpcArgs.installArgs = installArgs; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.JavaScript/withBun', + rpcArgs + ); + return new ViteAppResource(result, this._client); + } + + /** Configures Bun as the package manager */ + withBun(options?: WithBunOptions): ViteAppResourcePromise { + const install = options?.install; + const installArgs = options?.installArgs; + return new ViteAppResourcePromise(this._withBunInternal(install, installArgs)); + } + + /** @internal */ + private async _withYarnInternal(install?: boolean, installArgs?: string[]): Promise { + const rpcArgs: Record = { resource: this._handle }; + if (install !== undefined) rpcArgs.install = install; + if (installArgs !== undefined) rpcArgs.installArgs = installArgs; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.JavaScript/withYarn', + rpcArgs + ); + return new ViteAppResource(result, this._client); + } + + /** Configures yarn as the package manager */ + withYarn(options?: WithYarnOptions): ViteAppResourcePromise { + const install = options?.install; + const installArgs = options?.installArgs; + return new ViteAppResourcePromise(this._withYarnInternal(install, installArgs)); + } + + /** @internal */ + private async _withPnpmInternal(install?: boolean, installArgs?: string[]): Promise { + const rpcArgs: Record = { resource: this._handle }; + if (install !== undefined) rpcArgs.install = install; + if (installArgs !== undefined) rpcArgs.installArgs = installArgs; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.JavaScript/withPnpm', + rpcArgs + ); + return new ViteAppResource(result, this._client); + } + + /** Configures pnpm as the package manager */ + withPnpm(options?: WithPnpmOptions): ViteAppResourcePromise { + const install = options?.install; + const installArgs = options?.installArgs; + return new ViteAppResourcePromise(this._withPnpmInternal(install, installArgs)); + } + + /** @internal */ + private async _withBuildScriptInternal(scriptName: string, args?: string[]): Promise { + const rpcArgs: Record = { resource: this._handle, scriptName }; + if (args !== undefined) rpcArgs.args = args; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.JavaScript/withBuildScript', + rpcArgs + ); + return new ViteAppResource(result, this._client); + } + + /** Specifies an npm script to run before starting the application */ + withBuildScript(scriptName: string, options?: WithBuildScriptOptions): ViteAppResourcePromise { + const args = options?.args; + return new ViteAppResourcePromise(this._withBuildScriptInternal(scriptName, args)); + } + + /** @internal */ + private async _withRunScriptInternal(scriptName: string, args?: string[]): Promise { + const rpcArgs: Record = { resource: this._handle, scriptName }; + if (args !== undefined) rpcArgs.args = args; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.JavaScript/withRunScript', + rpcArgs + ); + return new ViteAppResource(result, this._client); + } + + /** Specifies an npm script to run during development */ + withRunScript(scriptName: string, options?: WithRunScriptOptions): ViteAppResourcePromise { + const args = options?.args; + return new ViteAppResourcePromise(this._withRunScriptInternal(scriptName, args)); + } + + /** @internal */ + private async _withBrowserDebuggerInternal(browser?: string): Promise { + const rpcArgs: Record = { builder: this._handle }; + if (browser !== undefined) rpcArgs.browser = browser; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.JavaScript/withBrowserDebugger', + rpcArgs + ); + return new ViteAppResource(result, this._client); + } + + /** Configures a browser debugger for the JavaScript application */ + withBrowserDebugger(options?: WithBrowserDebuggerOptions): ViteAppResourcePromise { + const browser = options?.browser; + return new ViteAppResourcePromise(this._withBrowserDebuggerInternal(browser)); + } + + /** @internal */ + private async _withEnvironmentFromOutputInternal(name: string, bicepOutputReference: BicepOutputReference): Promise { + const rpcArgs: Record = { builder: this._handle, name, bicepOutputReference }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure/withEnvironmentFromOutput', + rpcArgs + ); + return new ViteAppResource(result, this._client); + } + + /** Sets an environment variable from a Bicep output reference */ + withEnvironmentFromOutput(name: string, bicepOutputReference: BicepOutputReference): ViteAppResourcePromise { + return new ViteAppResourcePromise(this._withEnvironmentFromOutputInternal(name, bicepOutputReference)); + } + + /** @internal */ + private async _withEnvironmentFromKeyVaultSecretInternal(name: string, secretReference: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, name, secretReference }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure/withEnvironmentFromKeyVaultSecret', + rpcArgs + ); + return new ViteAppResource(result, this._client); + } + + /** Sets an environment variable from an Azure Key Vault secret reference */ + withEnvironmentFromKeyVaultSecret(name: string, secretReference: ResourceBuilderBase): ViteAppResourcePromise { + return new ViteAppResourcePromise(this._withEnvironmentFromKeyVaultSecretInternal(name, secretReference)); + } + + /** @internal */ + private async _withAzureUserAssignedIdentityInternal(identityResourceBuilder: AzureUserAssignedIdentityResource): Promise { + const rpcArgs: Record = { builder: this._handle, identityResourceBuilder }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure/withUserAssignedIdentityAzureUserAssignedIdentity', + rpcArgs + ); + return new ViteAppResource(result, this._client); + } + + /** Associates an Azure user-assigned identity with a compute resource */ + withAzureUserAssignedIdentity(identityResourceBuilder: AzureUserAssignedIdentityResource): ViteAppResourcePromise { + return new ViteAppResourcePromise(this._withAzureUserAssignedIdentityInternal(identityResourceBuilder)); + } + +} + +/** + * Thenable wrapper for ViteAppResource that enables fluent chaining. + * @example + * await builder.addSomething().withX().withY(); + */ +export class ViteAppResourcePromise implements PromiseLike { + constructor(private _promise: Promise) {} + + then( + onfulfilled?: ((value: ViteAppResource) => TResult1 | PromiseLike) | null, + onrejected?: ((reason: unknown) => TResult2 | PromiseLike) | null + ): PromiseLike { + return this._promise.then(onfulfilled, onrejected); + } + + /** Configures a resource to use a container registry */ + withContainerRegistry(registry: ResourceBuilderBase): ViteAppResourcePromise { + return new ViteAppResourcePromise(this._promise.then(obj => obj.withContainerRegistry(registry))); + } + + /** Sets the base image for a Dockerfile build */ + withDockerfileBaseImage(options?: WithDockerfileBaseImageOptions): ViteAppResourcePromise { + return new ViteAppResourcePromise(this._promise.then(obj => obj.withDockerfileBaseImage(options))); + } + + /** Publishes the executable as a Docker container */ + publishAsDockerFile(): ViteAppResourcePromise { + return new ViteAppResourcePromise(this._promise.then(obj => obj.publishAsDockerFile())); + } + + /** Publishes an executable as a Docker file with optional container configuration */ + publishAsDockerFileWithConfigure(configure: (obj: ContainerResource) => Promise): ViteAppResourcePromise { + return new ViteAppResourcePromise(this._promise.then(obj => obj.publishAsDockerFileWithConfigure(configure))); + } + + /** Sets the executable command */ + withExecutableCommand(command: string): ViteAppResourcePromise { + return new ViteAppResourcePromise(this._promise.then(obj => obj.withExecutableCommand(command))); + } + + /** Sets the executable working directory */ + withWorkingDirectory(workingDirectory: string): ViteAppResourcePromise { + return new ViteAppResourcePromise(this._promise.then(obj => obj.withWorkingDirectory(workingDirectory))); + } + + /** Configures an MCP server endpoint on the resource */ + withMcpServer(options?: WithMcpServerOptions): ViteAppResourcePromise { + return new ViteAppResourcePromise(this._promise.then(obj => obj.withMcpServer(options))); + } + + /** Configures OTLP telemetry export */ + withOtlpExporter(): ViteAppResourcePromise { + return new ViteAppResourcePromise(this._promise.then(obj => obj.withOtlpExporter())); + } + + /** Configures OTLP telemetry export with specific protocol */ + withOtlpExporterProtocol(protocol: OtlpProtocol): ViteAppResourcePromise { + return new ViteAppResourcePromise(this._promise.then(obj => obj.withOtlpExporterProtocol(protocol))); + } + + /** Adds a required command dependency */ + withRequiredCommand(command: string, options?: WithRequiredCommandOptions): ViteAppResourcePromise { + return new ViteAppResourcePromise(this._promise.then(obj => obj.withRequiredCommand(command, options))); + } + + /** Sets an environment variable */ + withEnvironment(name: string, value: string): ViteAppResourcePromise { + return new ViteAppResourcePromise(this._promise.then(obj => obj.withEnvironment(name, value))); + } + + /** Adds an environment variable with a reference expression */ + withEnvironmentExpression(name: string, value: ReferenceExpression): ViteAppResourcePromise { + return new ViteAppResourcePromise(this._promise.then(obj => obj.withEnvironmentExpression(name, value))); + } + + /** Sets environment variables via callback */ + withEnvironmentCallback(callback: (obj: EnvironmentCallbackContext) => Promise): ViteAppResourcePromise { + return new ViteAppResourcePromise(this._promise.then(obj => obj.withEnvironmentCallback(callback))); + } + + /** Sets environment variables via async callback */ + withEnvironmentCallbackAsync(callback: (arg: EnvironmentCallbackContext) => Promise): ViteAppResourcePromise { + return new ViteAppResourcePromise(this._promise.then(obj => obj.withEnvironmentCallbackAsync(callback))); + } + + /** Sets an environment variable from an endpoint reference */ + withEnvironmentEndpoint(name: string, endpointReference: EndpointReference): ViteAppResourcePromise { + return new ViteAppResourcePromise(this._promise.then(obj => obj.withEnvironmentEndpoint(name, endpointReference))); + } + + /** Sets an environment variable from a parameter resource */ + withEnvironmentParameter(name: string, parameter: ParameterResource): ViteAppResourcePromise { + return new ViteAppResourcePromise(this._promise.then(obj => obj.withEnvironmentParameter(name, parameter))); + } + + /** Sets an environment variable from a connection string resource */ + withEnvironmentConnectionString(envVarName: string, resource: ResourceBuilderBase): ViteAppResourcePromise { + return new ViteAppResourcePromise(this._promise.then(obj => obj.withEnvironmentConnectionString(envVarName, resource))); + } + + /** Adds arguments */ + withArgs(args: string[]): ViteAppResourcePromise { + return new ViteAppResourcePromise(this._promise.then(obj => obj.withArgs(args))); + } + + /** Sets command-line arguments via callback */ + withArgsCallback(callback: (obj: CommandLineArgsCallbackContext) => Promise): ViteAppResourcePromise { + return new ViteAppResourcePromise(this._promise.then(obj => obj.withArgsCallback(callback))); + } + + /** Sets command-line arguments via async callback */ + withArgsCallbackAsync(callback: (arg: CommandLineArgsCallbackContext) => Promise): ViteAppResourcePromise { + return new ViteAppResourcePromise(this._promise.then(obj => obj.withArgsCallbackAsync(callback))); + } + + /** Adds a reference to another resource */ + withReference(source: ResourceBuilderBase, options?: WithReferenceOptions): ViteAppResourcePromise { + return new ViteAppResourcePromise(this._promise.then(obj => obj.withReference(source, options))); + } + + /** Adds a service discovery reference to another resource */ + withServiceReference(source: ResourceBuilderBase): ViteAppResourcePromise { + return new ViteAppResourcePromise(this._promise.then(obj => obj.withServiceReference(source))); + } + + /** Adds a named service discovery reference */ + withServiceReferenceNamed(source: ResourceBuilderBase, name: string): ViteAppResourcePromise { + return new ViteAppResourcePromise(this._promise.then(obj => obj.withServiceReferenceNamed(source, name))); + } + + /** Adds a reference to a URI */ + withReferenceUri(name: string, uri: string): ViteAppResourcePromise { + return new ViteAppResourcePromise(this._promise.then(obj => obj.withReferenceUri(name, uri))); + } + + /** Adds a reference to an external service */ + withReferenceExternalService(externalService: ExternalServiceResource): ViteAppResourcePromise { + return new ViteAppResourcePromise(this._promise.then(obj => obj.withReferenceExternalService(externalService))); + } + + /** Adds a reference to an endpoint */ + withReferenceEndpoint(endpointReference: EndpointReference): ViteAppResourcePromise { + return new ViteAppResourcePromise(this._promise.then(obj => obj.withReferenceEndpoint(endpointReference))); + } + + /** Adds a network endpoint */ + withEndpoint(options?: WithEndpointOptions): ViteAppResourcePromise { + return new ViteAppResourcePromise(this._promise.then(obj => obj.withEndpoint(options))); + } + + /** Adds an HTTP endpoint */ + withHttpEndpoint(options?: WithHttpEndpointOptions): ViteAppResourcePromise { + return new ViteAppResourcePromise(this._promise.then(obj => obj.withHttpEndpoint(options))); + } + + /** Adds an HTTPS endpoint */ + withHttpsEndpoint(options?: WithHttpsEndpointOptions): ViteAppResourcePromise { + return new ViteAppResourcePromise(this._promise.then(obj => obj.withHttpsEndpoint(options))); + } + + /** Makes HTTP endpoints externally accessible */ + withExternalHttpEndpoints(): ViteAppResourcePromise { + return new ViteAppResourcePromise(this._promise.then(obj => obj.withExternalHttpEndpoints())); + } + + /** Gets an endpoint reference */ + getEndpoint(name: string): Promise { + return this._promise.then(obj => obj.getEndpoint(name)); + } + + /** Configures resource for HTTP/2 */ + asHttp2Service(): ViteAppResourcePromise { + return new ViteAppResourcePromise(this._promise.then(obj => obj.asHttp2Service())); + } + + /** Customizes displayed URLs via callback */ + withUrlsCallback(callback: (obj: ResourceUrlsCallbackContext) => Promise): ViteAppResourcePromise { + return new ViteAppResourcePromise(this._promise.then(obj => obj.withUrlsCallback(callback))); + } + + /** Customizes displayed URLs via async callback */ + withUrlsCallbackAsync(callback: (arg: ResourceUrlsCallbackContext) => Promise): ViteAppResourcePromise { + return new ViteAppResourcePromise(this._promise.then(obj => obj.withUrlsCallbackAsync(callback))); + } + + /** Adds or modifies displayed URLs */ + withUrl(url: string, options?: WithUrlOptions): ViteAppResourcePromise { + return new ViteAppResourcePromise(this._promise.then(obj => obj.withUrl(url, options))); + } + + /** Adds a URL using a reference expression */ + withUrlExpression(url: ReferenceExpression, options?: WithUrlExpressionOptions): ViteAppResourcePromise { + return new ViteAppResourcePromise(this._promise.then(obj => obj.withUrlExpression(url, options))); + } + + /** Customizes the URL for a specific endpoint via callback */ + withUrlForEndpoint(endpointName: string, callback: (obj: ResourceUrlAnnotation) => Promise): ViteAppResourcePromise { + return new ViteAppResourcePromise(this._promise.then(obj => obj.withUrlForEndpoint(endpointName, callback))); + } + + /** Adds a URL for a specific endpoint via factory callback */ + withUrlForEndpointFactory(endpointName: string, callback: (arg: EndpointReference) => Promise): ViteAppResourcePromise { + return new ViteAppResourcePromise(this._promise.then(obj => obj.withUrlForEndpointFactory(endpointName, callback))); + } + + /** Sets the source directory for container files */ + withContainerFilesSource(sourcePath: string): ViteAppResourcePromise { + return new ViteAppResourcePromise(this._promise.then(obj => obj.withContainerFilesSource(sourcePath))); + } + + /** Clears all container file sources */ + clearContainerFilesSources(): ViteAppResourcePromise { + return new ViteAppResourcePromise(this._promise.then(obj => obj.clearContainerFilesSources())); + } + + /** Excludes the resource from the deployment manifest */ + excludeFromManifest(): ViteAppResourcePromise { + return new ViteAppResourcePromise(this._promise.then(obj => obj.excludeFromManifest())); + } + + /** Waits for another resource to be ready */ + waitFor(dependency: ResourceBuilderBase): ViteAppResourcePromise { + return new ViteAppResourcePromise(this._promise.then(obj => obj.waitFor(dependency))); + } + + /** Waits for another resource with specific behavior */ + waitForWithBehavior(dependency: ResourceBuilderBase, waitBehavior: WaitBehavior): ViteAppResourcePromise { + return new ViteAppResourcePromise(this._promise.then(obj => obj.waitForWithBehavior(dependency, waitBehavior))); + } + + /** Waits for another resource to start */ + waitForStart(dependency: ResourceBuilderBase): ViteAppResourcePromise { + return new ViteAppResourcePromise(this._promise.then(obj => obj.waitForStart(dependency))); + } + + /** Waits for another resource to start with specific behavior */ + waitForStartWithBehavior(dependency: ResourceBuilderBase, waitBehavior: WaitBehavior): ViteAppResourcePromise { + return new ViteAppResourcePromise(this._promise.then(obj => obj.waitForStartWithBehavior(dependency, waitBehavior))); + } + + /** Prevents resource from starting automatically */ + withExplicitStart(): ViteAppResourcePromise { + return new ViteAppResourcePromise(this._promise.then(obj => obj.withExplicitStart())); + } + + /** Waits for resource completion */ + waitForCompletion(dependency: ResourceBuilderBase, options?: WaitForCompletionOptions): ViteAppResourcePromise { + return new ViteAppResourcePromise(this._promise.then(obj => obj.waitForCompletion(dependency, options))); + } + + /** Adds a health check by key */ + withHealthCheck(key: string): ViteAppResourcePromise { + return new ViteAppResourcePromise(this._promise.then(obj => obj.withHealthCheck(key))); + } + + /** Adds an HTTP health check */ + withHttpHealthCheck(options?: WithHttpHealthCheckOptions): ViteAppResourcePromise { + return new ViteAppResourcePromise(this._promise.then(obj => obj.withHttpHealthCheck(options))); + } + + /** Adds a resource command */ + withCommand(name: string, displayName: string, executeCommand: (arg: ExecuteCommandContext) => Promise, options?: WithCommandOptions): ViteAppResourcePromise { + return new ViteAppResourcePromise(this._promise.then(obj => obj.withCommand(name, displayName, executeCommand, options))); + } + + /** Configures developer certificate trust */ + withDeveloperCertificateTrust(trust: boolean): ViteAppResourcePromise { + return new ViteAppResourcePromise(this._promise.then(obj => obj.withDeveloperCertificateTrust(trust))); + } + + /** Sets the certificate trust scope */ + withCertificateTrustScope(scope: CertificateTrustScope): ViteAppResourcePromise { + return new ViteAppResourcePromise(this._promise.then(obj => obj.withCertificateTrustScope(scope))); + } + + /** Configures HTTPS with a developer certificate */ + withHttpsDeveloperCertificate(options?: WithHttpsDeveloperCertificateOptions): ViteAppResourcePromise { + return new ViteAppResourcePromise(this._promise.then(obj => obj.withHttpsDeveloperCertificate(options))); + } + + /** Removes HTTPS certificate configuration */ + withoutHttpsCertificate(): ViteAppResourcePromise { + return new ViteAppResourcePromise(this._promise.then(obj => obj.withoutHttpsCertificate())); + } + + /** Sets the parent relationship */ + withParentRelationship(parent: ResourceBuilderBase): ViteAppResourcePromise { + return new ViteAppResourcePromise(this._promise.then(obj => obj.withParentRelationship(parent))); + } + + /** Sets a child relationship */ + withChildRelationship(child: ResourceBuilderBase): ViteAppResourcePromise { + return new ViteAppResourcePromise(this._promise.then(obj => obj.withChildRelationship(child))); + } + + /** Sets the icon for the resource */ + withIconName(iconName: string, options?: WithIconNameOptions): ViteAppResourcePromise { + return new ViteAppResourcePromise(this._promise.then(obj => obj.withIconName(iconName, options))); + } + + /** Adds an HTTP health probe to the resource */ + withHttpProbe(probeType: ProbeType, options?: WithHttpProbeOptions): ViteAppResourcePromise { + return new ViteAppResourcePromise(this._promise.then(obj => obj.withHttpProbe(probeType, options))); + } + + /** Excludes the resource from MCP server exposure */ + excludeFromMcp(): ViteAppResourcePromise { + return new ViteAppResourcePromise(this._promise.then(obj => obj.excludeFromMcp())); + } + + /** Sets the remote image name for publishing */ + withRemoteImageName(remoteImageName: string): ViteAppResourcePromise { + return new ViteAppResourcePromise(this._promise.then(obj => obj.withRemoteImageName(remoteImageName))); + } + + /** Sets the remote image tag for publishing */ + withRemoteImageTag(remoteImageTag: string): ViteAppResourcePromise { + return new ViteAppResourcePromise(this._promise.then(obj => obj.withRemoteImageTag(remoteImageTag))); + } + + /** Adds a pipeline step to the resource */ + withPipelineStepFactory(stepName: string, callback: (arg: PipelineStepContext) => Promise, options?: WithPipelineStepFactoryOptions): ViteAppResourcePromise { + return new ViteAppResourcePromise(this._promise.then(obj => obj.withPipelineStepFactory(stepName, callback, options))); + } + + /** Configures pipeline step dependencies via an async callback */ + withPipelineConfigurationAsync(callback: (arg: PipelineConfigurationContext) => Promise): ViteAppResourcePromise { + return new ViteAppResourcePromise(this._promise.then(obj => obj.withPipelineConfigurationAsync(callback))); + } + + /** Configures pipeline step dependencies via a callback */ + withPipelineConfiguration(callback: (obj: PipelineConfigurationContext) => Promise): ViteAppResourcePromise { + return new ViteAppResourcePromise(this._promise.then(obj => obj.withPipelineConfiguration(callback))); + } + + /** Gets the resource name */ + getResourceName(): Promise { + return this._promise.then(obj => obj.getResourceName()); + } + + /** Assigns Azure Storage roles to a resource */ + withStorageRoleAssignments(target: AzureStorageResource, roles: AzureStorageRole[]): ViteAppResourcePromise { + return new ViteAppResourcePromise(this._promise.then(obj => obj.withStorageRoleAssignments(target, roles))); + } + + /** Assigns Event Hubs roles to a resource */ + withEventHubsRoleAssignments(target: AzureEventHubsResource, roles: AzureEventHubsRole[]): ViteAppResourcePromise { + return new ViteAppResourcePromise(this._promise.then(obj => obj.withEventHubsRoleAssignments(target, roles))); + } + + /** Configures a custom Vite configuration file */ + withViteConfig(configPath: string): ViteAppResourcePromise { + return new ViteAppResourcePromise(this._promise.then(obj => obj.withViteConfig(configPath))); + } + + /** Configures npm as the package manager */ + withNpm(options?: WithNpmOptions): ViteAppResourcePromise { + return new ViteAppResourcePromise(this._promise.then(obj => obj.withNpm(options))); + } + + /** Configures Bun as the package manager */ + withBun(options?: WithBunOptions): ViteAppResourcePromise { + return new ViteAppResourcePromise(this._promise.then(obj => obj.withBun(options))); + } + + /** Configures yarn as the package manager */ + withYarn(options?: WithYarnOptions): ViteAppResourcePromise { + return new ViteAppResourcePromise(this._promise.then(obj => obj.withYarn(options))); + } + + /** Configures pnpm as the package manager */ + withPnpm(options?: WithPnpmOptions): ViteAppResourcePromise { + return new ViteAppResourcePromise(this._promise.then(obj => obj.withPnpm(options))); + } + + /** Specifies an npm script to run before starting the application */ + withBuildScript(scriptName: string, options?: WithBuildScriptOptions): ViteAppResourcePromise { + return new ViteAppResourcePromise(this._promise.then(obj => obj.withBuildScript(scriptName, options))); + } + + /** Specifies an npm script to run during development */ + withRunScript(scriptName: string, options?: WithRunScriptOptions): ViteAppResourcePromise { + return new ViteAppResourcePromise(this._promise.then(obj => obj.withRunScript(scriptName, options))); + } + + /** Configures a browser debugger for the JavaScript application */ + withBrowserDebugger(options?: WithBrowserDebuggerOptions): ViteAppResourcePromise { + return new ViteAppResourcePromise(this._promise.then(obj => obj.withBrowserDebugger(options))); + } + + /** Sets an environment variable from a Bicep output reference */ + withEnvironmentFromOutput(name: string, bicepOutputReference: BicepOutputReference): ViteAppResourcePromise { + return new ViteAppResourcePromise(this._promise.then(obj => obj.withEnvironmentFromOutput(name, bicepOutputReference))); + } + + /** Sets an environment variable from an Azure Key Vault secret reference */ + withEnvironmentFromKeyVaultSecret(name: string, secretReference: ResourceBuilderBase): ViteAppResourcePromise { + return new ViteAppResourcePromise(this._promise.then(obj => obj.withEnvironmentFromKeyVaultSecret(name, secretReference))); + } + + /** Associates an Azure user-assigned identity with a compute resource */ + withAzureUserAssignedIdentity(identityResourceBuilder: AzureUserAssignedIdentityResource): ViteAppResourcePromise { + return new ViteAppResourcePromise(this._promise.then(obj => obj.withAzureUserAssignedIdentity(identityResourceBuilder))); + } + +} + +// ============================================================================ +// AzureResource +// ============================================================================ + +export class AzureResource extends ResourceBuilderBase { + constructor(handle: IAzureResourceHandle, client: AspireClientRpc) { + super(handle, client); + } + + /** @internal */ + private async _publishAsConnectionStringInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure/publishAsConnectionString', + rpcArgs + ); + return new AzureResource(result, this._client); + } + + /** Publishes an Azure resource to the manifest as a connection string */ + publishAsConnectionString(): AzureResourcePromise { + return new AzureResourcePromise(this._publishAsConnectionStringInternal()); + } + + /** Gets the normalized Bicep identifier for an Azure resource */ + async getBicepIdentifier(): Promise { + const rpcArgs: Record = { resource: this._handle }; + return await this._client.invokeCapability( + 'Aspire.Hosting.Azure/getBicepIdentifier', + rpcArgs + ); + } + + /** @internal */ + private async _clearDefaultRoleAssignmentsInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure/clearDefaultRoleAssignments', + rpcArgs + ); + return new AzureResource(result, this._client); + } + + /** Clears the default Azure role assignments from a resource */ + clearDefaultRoleAssignments(): AzureResourcePromise { + return new AzureResourcePromise(this._clearDefaultRoleAssignmentsInternal()); + } + + /** Determines whether a resource is marked as existing */ + async isExisting(): Promise { + const rpcArgs: Record = { resource: this._handle }; + return await this._client.invokeCapability( + 'Aspire.Hosting.Azure/isExisting', + rpcArgs + ); + } + + /** @internal */ + private async _runAsExistingFromParametersInternal(nameParameter: ParameterResource, resourceGroupParameter: ParameterResource): Promise { + const rpcArgs: Record = { builder: this._handle, nameParameter, resourceGroupParameter }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure/runAsExistingFromParameters', + rpcArgs + ); + return new AzureResource(result, this._client); + } + + /** Marks an Azure resource as existing in run mode by using parameter resources */ + runAsExistingFromParameters(nameParameter: ParameterResource, resourceGroupParameter: ParameterResource): AzureResourcePromise { + return new AzureResourcePromise(this._runAsExistingFromParametersInternal(nameParameter, resourceGroupParameter)); + } + + /** @internal */ + private async _runAsExistingInternal(name: string, resourceGroup: string): Promise { + const rpcArgs: Record = { builder: this._handle, name, resourceGroup }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure/runAsExisting', + rpcArgs + ); + return new AzureResource(result, this._client); + } + + /** Marks an Azure resource as existing in run mode */ + runAsExisting(name: string, resourceGroup: string): AzureResourcePromise { + return new AzureResourcePromise(this._runAsExistingInternal(name, resourceGroup)); + } + + /** @internal */ + private async _publishAsExistingFromParametersInternal(nameParameter: ParameterResource, resourceGroupParameter: ParameterResource): Promise { + const rpcArgs: Record = { builder: this._handle, nameParameter, resourceGroupParameter }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure/publishAsExistingFromParameters', + rpcArgs + ); + return new AzureResource(result, this._client); + } + + /** Marks an Azure resource as existing in publish mode by using parameter resources */ + publishAsExistingFromParameters(nameParameter: ParameterResource, resourceGroupParameter: ParameterResource): AzureResourcePromise { + return new AzureResourcePromise(this._publishAsExistingFromParametersInternal(nameParameter, resourceGroupParameter)); + } + + /** @internal */ + private async _publishAsExistingInternal(name: string, resourceGroup: string): Promise { + const rpcArgs: Record = { builder: this._handle, name, resourceGroup }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure/publishAsExisting', + rpcArgs + ); + return new AzureResource(result, this._client); + } + + /** Marks an Azure resource as existing in publish mode */ + publishAsExisting(name: string, resourceGroup: string): AzureResourcePromise { + return new AzureResourcePromise(this._publishAsExistingInternal(name, resourceGroup)); + } + + /** @internal */ + private async _asExistingInternal(nameParameter: ParameterResource, resourceGroupParameter: ParameterResource): Promise { + const rpcArgs: Record = { builder: this._handle, nameParameter, resourceGroupParameter }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure/asExistingFromParameters', + rpcArgs + ); + return new AzureResource(result, this._client); + } + + /** Marks an Azure resource as existing in both run and publish modes by using parameter resources */ + asExisting(nameParameter: ParameterResource, resourceGroupParameter: ParameterResource): AzureResourcePromise { + return new AzureResourcePromise(this._asExistingInternal(nameParameter, resourceGroupParameter)); + } + +} + +/** + * Thenable wrapper for AzureResource that enables fluent chaining. + * @example + * await builder.addSomething().withX().withY(); + */ +export class AzureResourcePromise implements PromiseLike { + constructor(private _promise: Promise) {} + + then( + onfulfilled?: ((value: AzureResource) => TResult1 | PromiseLike) | null, + onrejected?: ((reason: unknown) => TResult2 | PromiseLike) | null + ): PromiseLike { + return this._promise.then(onfulfilled, onrejected); + } + + /** Publishes an Azure resource to the manifest as a connection string */ + publishAsConnectionString(): AzureResourcePromise { + return new AzureResourcePromise(this._promise.then(obj => obj.publishAsConnectionString())); + } + + /** Gets the normalized Bicep identifier for an Azure resource */ + getBicepIdentifier(): Promise { + return this._promise.then(obj => obj.getBicepIdentifier()); + } + + /** Clears the default Azure role assignments from a resource */ + clearDefaultRoleAssignments(): AzureResourcePromise { + return new AzureResourcePromise(this._promise.then(obj => obj.clearDefaultRoleAssignments())); + } + + /** Determines whether a resource is marked as existing */ + isExisting(): Promise { + return this._promise.then(obj => obj.isExisting()); + } + + /** Marks an Azure resource as existing in run mode by using parameter resources */ + runAsExistingFromParameters(nameParameter: ParameterResource, resourceGroupParameter: ParameterResource): AzureResourcePromise { + return new AzureResourcePromise(this._promise.then(obj => obj.runAsExistingFromParameters(nameParameter, resourceGroupParameter))); + } + + /** Marks an Azure resource as existing in run mode */ + runAsExisting(name: string, resourceGroup: string): AzureResourcePromise { + return new AzureResourcePromise(this._promise.then(obj => obj.runAsExisting(name, resourceGroup))); + } + + /** Marks an Azure resource as existing in publish mode by using parameter resources */ + publishAsExistingFromParameters(nameParameter: ParameterResource, resourceGroupParameter: ParameterResource): AzureResourcePromise { + return new AzureResourcePromise(this._promise.then(obj => obj.publishAsExistingFromParameters(nameParameter, resourceGroupParameter))); + } + + /** Marks an Azure resource as existing in publish mode */ + publishAsExisting(name: string, resourceGroup: string): AzureResourcePromise { + return new AzureResourcePromise(this._promise.then(obj => obj.publishAsExisting(name, resourceGroup))); + } + + /** Marks an Azure resource as existing in both run and publish modes by using parameter resources */ + asExisting(nameParameter: ParameterResource, resourceGroupParameter: ParameterResource): AzureResourcePromise { + return new AzureResourcePromise(this._promise.then(obj => obj.asExisting(nameParameter, resourceGroupParameter))); + } + +} + +// ============================================================================ +// ComputeResource +// ============================================================================ + +export class ComputeResource extends ResourceBuilderBase { + constructor(handle: IComputeResourceHandle, client: AspireClientRpc) { + super(handle, client); + } + + /** @internal */ + private async _withRemoteImageNameInternal(remoteImageName: string): Promise { + const rpcArgs: Record = { builder: this._handle, remoteImageName }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withRemoteImageName', + rpcArgs + ); + return new ComputeResource(result, this._client); + } + + /** Sets the remote image name for publishing */ + withRemoteImageName(remoteImageName: string): ComputeResourcePromise { + return new ComputeResourcePromise(this._withRemoteImageNameInternal(remoteImageName)); + } + + /** @internal */ + private async _withRemoteImageTagInternal(remoteImageTag: string): Promise { + const rpcArgs: Record = { builder: this._handle, remoteImageTag }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withRemoteImageTag', + rpcArgs + ); + return new ComputeResource(result, this._client); + } + + /** Sets the remote image tag for publishing */ + withRemoteImageTag(remoteImageTag: string): ComputeResourcePromise { + return new ComputeResourcePromise(this._withRemoteImageTagInternal(remoteImageTag)); + } + + /** @internal */ + private async _withAzureUserAssignedIdentityInternal(identityResourceBuilder: AzureUserAssignedIdentityResource): Promise { + const rpcArgs: Record = { builder: this._handle, identityResourceBuilder }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure/withUserAssignedIdentityAzureUserAssignedIdentity', + rpcArgs + ); + return new ComputeResource(result, this._client); + } + + /** Associates an Azure user-assigned identity with a compute resource */ + withAzureUserAssignedIdentity(identityResourceBuilder: AzureUserAssignedIdentityResource): ComputeResourcePromise { + return new ComputeResourcePromise(this._withAzureUserAssignedIdentityInternal(identityResourceBuilder)); + } + +} + +/** + * Thenable wrapper for ComputeResource that enables fluent chaining. + * @example + * await builder.addSomething().withX().withY(); + */ +export class ComputeResourcePromise implements PromiseLike { + constructor(private _promise: Promise) {} + + then( + onfulfilled?: ((value: ComputeResource) => TResult1 | PromiseLike) | null, + onrejected?: ((reason: unknown) => TResult2 | PromiseLike) | null + ): PromiseLike { + return this._promise.then(onfulfilled, onrejected); + } + + /** Sets the remote image name for publishing */ + withRemoteImageName(remoteImageName: string): ComputeResourcePromise { + return new ComputeResourcePromise(this._promise.then(obj => obj.withRemoteImageName(remoteImageName))); + } + + /** Sets the remote image tag for publishing */ + withRemoteImageTag(remoteImageTag: string): ComputeResourcePromise { + return new ComputeResourcePromise(this._promise.then(obj => obj.withRemoteImageTag(remoteImageTag))); + } + + /** Associates an Azure user-assigned identity with a compute resource */ + withAzureUserAssignedIdentity(identityResourceBuilder: AzureUserAssignedIdentityResource): ComputeResourcePromise { + return new ComputeResourcePromise(this._promise.then(obj => obj.withAzureUserAssignedIdentity(identityResourceBuilder))); + } + +} + +// ============================================================================ +// ContainerFilesDestinationResource +// ============================================================================ + +export class ContainerFilesDestinationResource extends ResourceBuilderBase { + constructor(handle: IContainerFilesDestinationResourceHandle, client: AspireClientRpc) { + super(handle, client); + } + + /** @internal */ + private async _publishWithContainerFilesInternal(source: ResourceBuilderBase, destinationPath: string): Promise { + const rpcArgs: Record = { builder: this._handle, source, destinationPath }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/publishWithContainerFiles', + rpcArgs + ); + return new ContainerFilesDestinationResource(result, this._client); + } + + /** Configures the resource to copy container files from the specified source during publishing */ + publishWithContainerFiles(source: ResourceBuilderBase, destinationPath: string): ContainerFilesDestinationResourcePromise { + return new ContainerFilesDestinationResourcePromise(this._publishWithContainerFilesInternal(source, destinationPath)); + } + +} + +/** + * Thenable wrapper for ContainerFilesDestinationResource that enables fluent chaining. + * @example + * await builder.addSomething().withX().withY(); + */ +export class ContainerFilesDestinationResourcePromise implements PromiseLike { + constructor(private _promise: Promise) {} + + then( + onfulfilled?: ((value: ContainerFilesDestinationResource) => TResult1 | PromiseLike) | null, + onrejected?: ((reason: unknown) => TResult2 | PromiseLike) | null + ): PromiseLike { + return this._promise.then(onfulfilled, onrejected); + } + + /** Configures the resource to copy container files from the specified source during publishing */ + publishWithContainerFiles(source: ResourceBuilderBase, destinationPath: string): ContainerFilesDestinationResourcePromise { + return new ContainerFilesDestinationResourcePromise(this._promise.then(obj => obj.publishWithContainerFiles(source, destinationPath))); + } + +} + +// ============================================================================ +// Resource +// ============================================================================ + +export class Resource extends ResourceBuilderBase { + constructor(handle: IResourceHandle, client: AspireClientRpc) { + super(handle, client); + } + + /** @internal */ + private async _withContainerRegistryInternal(registry: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, registry }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withContainerRegistry', + rpcArgs + ); + return new Resource(result, this._client); + } + + /** Configures a resource to use a container registry */ + withContainerRegistry(registry: ResourceBuilderBase): ResourcePromise { + return new ResourcePromise(this._withContainerRegistryInternal(registry)); + } + + /** @internal */ + private async _withDockerfileBaseImageInternal(buildImage?: string, runtimeImage?: string): Promise { + const rpcArgs: Record = { builder: this._handle }; + if (buildImage !== undefined) rpcArgs.buildImage = buildImage; + if (runtimeImage !== undefined) rpcArgs.runtimeImage = runtimeImage; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withDockerfileBaseImage', + rpcArgs + ); + return new Resource(result, this._client); + } + + /** Sets the base image for a Dockerfile build */ + withDockerfileBaseImage(options?: WithDockerfileBaseImageOptions): ResourcePromise { + const buildImage = options?.buildImage; + const runtimeImage = options?.runtimeImage; + return new ResourcePromise(this._withDockerfileBaseImageInternal(buildImage, runtimeImage)); + } + + /** @internal */ + private async _withRequiredCommandInternal(command: string, helpLink?: string): Promise { + const rpcArgs: Record = { builder: this._handle, command }; + if (helpLink !== undefined) rpcArgs.helpLink = helpLink; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withRequiredCommand', + rpcArgs + ); + return new Resource(result, this._client); + } + + /** Adds a required command dependency */ + withRequiredCommand(command: string, options?: WithRequiredCommandOptions): ResourcePromise { + const helpLink = options?.helpLink; + return new ResourcePromise(this._withRequiredCommandInternal(command, helpLink)); + } + + /** @internal */ + private async _withUrlsCallbackInternal(callback: (obj: ResourceUrlsCallbackContext) => Promise): Promise { + const callbackId = registerCallback(async (objData: unknown) => { + const objHandle = wrapIfHandle(objData) as ResourceUrlsCallbackContextHandle; + const obj = new ResourceUrlsCallbackContext(objHandle, this._client); + await callback(obj); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrlsCallback', + rpcArgs + ); + return new Resource(result, this._client); + } + + /** Customizes displayed URLs via callback */ + withUrlsCallback(callback: (obj: ResourceUrlsCallbackContext) => Promise): ResourcePromise { + return new ResourcePromise(this._withUrlsCallbackInternal(callback)); + } + + /** @internal */ + private async _withUrlsCallbackAsyncInternal(callback: (arg: ResourceUrlsCallbackContext) => Promise): Promise { + const callbackId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as ResourceUrlsCallbackContextHandle; + const arg = new ResourceUrlsCallbackContext(argHandle, this._client); + await callback(arg); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrlsCallbackAsync', + rpcArgs + ); + return new Resource(result, this._client); + } + + /** Customizes displayed URLs via async callback */ + withUrlsCallbackAsync(callback: (arg: ResourceUrlsCallbackContext) => Promise): ResourcePromise { + return new ResourcePromise(this._withUrlsCallbackAsyncInternal(callback)); + } + + /** @internal */ + private async _withUrlInternal(url: string, displayText?: string): Promise { + const rpcArgs: Record = { builder: this._handle, url }; + if (displayText !== undefined) rpcArgs.displayText = displayText; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrl', + rpcArgs + ); + return new Resource(result, this._client); + } + + /** Adds or modifies displayed URLs */ + withUrl(url: string, options?: WithUrlOptions): ResourcePromise { + const displayText = options?.displayText; + return new ResourcePromise(this._withUrlInternal(url, displayText)); + } + + /** @internal */ + private async _withUrlExpressionInternal(url: ReferenceExpression, displayText?: string): Promise { + const rpcArgs: Record = { builder: this._handle, url }; + if (displayText !== undefined) rpcArgs.displayText = displayText; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrlExpression', + rpcArgs + ); + return new Resource(result, this._client); + } + + /** Adds a URL using a reference expression */ + withUrlExpression(url: ReferenceExpression, options?: WithUrlExpressionOptions): ResourcePromise { + const displayText = options?.displayText; + return new ResourcePromise(this._withUrlExpressionInternal(url, displayText)); + } + + /** @internal */ + private async _withUrlForEndpointInternal(endpointName: string, callback: (obj: ResourceUrlAnnotation) => Promise): Promise { + const callbackId = registerCallback(async (objData: unknown) => { + const obj = wrapIfHandle(objData) as ResourceUrlAnnotation; + await callback(obj); + }); + const rpcArgs: Record = { builder: this._handle, endpointName, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrlForEndpoint', + rpcArgs + ); + return new Resource(result, this._client); + } + + /** Customizes the URL for a specific endpoint via callback */ + withUrlForEndpoint(endpointName: string, callback: (obj: ResourceUrlAnnotation) => Promise): ResourcePromise { + return new ResourcePromise(this._withUrlForEndpointInternal(endpointName, callback)); + } + + /** @internal */ + private async _excludeFromManifestInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/excludeFromManifest', + rpcArgs + ); + return new Resource(result, this._client); + } + + /** Excludes the resource from the deployment manifest */ + excludeFromManifest(): ResourcePromise { + return new ResourcePromise(this._excludeFromManifestInternal()); + } + + /** @internal */ + private async _withExplicitStartInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withExplicitStart', + rpcArgs + ); + return new Resource(result, this._client); + } + + /** Prevents resource from starting automatically */ + withExplicitStart(): ResourcePromise { + return new ResourcePromise(this._withExplicitStartInternal()); + } + + /** @internal */ + private async _withHealthCheckInternal(key: string): Promise { + const rpcArgs: Record = { builder: this._handle, key }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withHealthCheck', + rpcArgs + ); + return new Resource(result, this._client); + } + + /** Adds a health check by key */ + withHealthCheck(key: string): ResourcePromise { + return new ResourcePromise(this._withHealthCheckInternal(key)); + } + + /** @internal */ + private async _withCommandInternal(name: string, displayName: string, executeCommand: (arg: ExecuteCommandContext) => Promise, commandOptions?: CommandOptions): Promise { + const executeCommandId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as ExecuteCommandContextHandle; + const arg = new ExecuteCommandContext(argHandle, this._client); + return await executeCommand(arg); + }); + const rpcArgs: Record = { builder: this._handle, name, displayName, executeCommand: executeCommandId }; + if (commandOptions !== undefined) rpcArgs.commandOptions = commandOptions; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withCommand', + rpcArgs + ); + return new Resource(result, this._client); + } + + /** Adds a resource command */ + withCommand(name: string, displayName: string, executeCommand: (arg: ExecuteCommandContext) => Promise, options?: WithCommandOptions): ResourcePromise { + const commandOptions = options?.commandOptions; + return new ResourcePromise(this._withCommandInternal(name, displayName, executeCommand, commandOptions)); + } + + /** @internal */ + private async _withParentRelationshipInternal(parent: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, parent }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withParentRelationship', + rpcArgs + ); + return new Resource(result, this._client); + } + + /** Sets the parent relationship */ + withParentRelationship(parent: ResourceBuilderBase): ResourcePromise { + return new ResourcePromise(this._withParentRelationshipInternal(parent)); + } + + /** @internal */ + private async _withChildRelationshipInternal(child: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, child }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withChildRelationship', + rpcArgs + ); + return new Resource(result, this._client); + } + + /** Sets a child relationship */ + withChildRelationship(child: ResourceBuilderBase): ResourcePromise { + return new ResourcePromise(this._withChildRelationshipInternal(child)); + } + + /** @internal */ + private async _withIconNameInternal(iconName: string, iconVariant?: IconVariant): Promise { + const rpcArgs: Record = { builder: this._handle, iconName }; + if (iconVariant !== undefined) rpcArgs.iconVariant = iconVariant; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withIconName', + rpcArgs + ); + return new Resource(result, this._client); + } + + /** Sets the icon for the resource */ + withIconName(iconName: string, options?: WithIconNameOptions): ResourcePromise { + const iconVariant = options?.iconVariant; + return new ResourcePromise(this._withIconNameInternal(iconName, iconVariant)); + } + + /** @internal */ + private async _excludeFromMcpInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/excludeFromMcp', + rpcArgs + ); + return new Resource(result, this._client); + } + + /** Excludes the resource from MCP server exposure */ + excludeFromMcp(): ResourcePromise { + return new ResourcePromise(this._excludeFromMcpInternal()); + } + + /** @internal */ + private async _withPipelineStepFactoryInternal(stepName: string, callback: (arg: PipelineStepContext) => Promise, dependsOn?: string[], requiredBy?: string[], tags?: string[], description?: string): Promise { + const callbackId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as PipelineStepContextHandle; + const arg = new PipelineStepContext(argHandle, this._client); + await callback(arg); + }); + const rpcArgs: Record = { builder: this._handle, stepName, callback: callbackId }; + if (dependsOn !== undefined) rpcArgs.dependsOn = dependsOn; + if (requiredBy !== undefined) rpcArgs.requiredBy = requiredBy; + if (tags !== undefined) rpcArgs.tags = tags; + if (description !== undefined) rpcArgs.description = description; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withPipelineStepFactory', + rpcArgs + ); + return new Resource(result, this._client); + } + + /** Adds a pipeline step to the resource */ + withPipelineStepFactory(stepName: string, callback: (arg: PipelineStepContext) => Promise, options?: WithPipelineStepFactoryOptions): ResourcePromise { + const dependsOn = options?.dependsOn; + const requiredBy = options?.requiredBy; + const tags = options?.tags; + const description = options?.description; + return new ResourcePromise(this._withPipelineStepFactoryInternal(stepName, callback, dependsOn, requiredBy, tags, description)); + } + + /** @internal */ + private async _withPipelineConfigurationAsyncInternal(callback: (arg: PipelineConfigurationContext) => Promise): Promise { + const callbackId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as PipelineConfigurationContextHandle; + const arg = new PipelineConfigurationContext(argHandle, this._client); + await callback(arg); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withPipelineConfigurationAsync', + rpcArgs + ); + return new Resource(result, this._client); + } + + /** Configures pipeline step dependencies via an async callback */ + withPipelineConfigurationAsync(callback: (arg: PipelineConfigurationContext) => Promise): ResourcePromise { + return new ResourcePromise(this._withPipelineConfigurationAsyncInternal(callback)); + } + + /** @internal */ + private async _withPipelineConfigurationInternal(callback: (obj: PipelineConfigurationContext) => Promise): Promise { + const callbackId = registerCallback(async (objData: unknown) => { + const objHandle = wrapIfHandle(objData) as PipelineConfigurationContextHandle; + const obj = new PipelineConfigurationContext(objHandle, this._client); + await callback(obj); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withPipelineConfiguration', + rpcArgs + ); + return new Resource(result, this._client); + } + + /** Configures pipeline step dependencies via a callback */ + withPipelineConfiguration(callback: (obj: PipelineConfigurationContext) => Promise): ResourcePromise { + return new ResourcePromise(this._withPipelineConfigurationInternal(callback)); + } + + /** Gets the resource name */ + async getResourceName(): Promise { + const rpcArgs: Record = { resource: this._handle }; + return await this._client.invokeCapability( + 'Aspire.Hosting/getResourceName', + rpcArgs + ); + } + + /** @internal */ + private async _withStorageRoleAssignmentsInternal(target: AzureStorageResource, roles: AzureStorageRole[]): Promise { + const rpcArgs: Record = { builder: this._handle, target, roles }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure.Storage/withStorageRoleAssignments', + rpcArgs + ); + return new Resource(result, this._client); + } + + /** Assigns Azure Storage roles to a resource */ + withStorageRoleAssignments(target: AzureStorageResource, roles: AzureStorageRole[]): ResourcePromise { + return new ResourcePromise(this._withStorageRoleAssignmentsInternal(target, roles)); + } + + /** @internal */ + private async _withEventHubsRoleAssignmentsInternal(target: AzureEventHubsResource, roles: AzureEventHubsRole[]): Promise { + const rpcArgs: Record = { builder: this._handle, target, roles }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure.EventHubs/withEventHubsRoleAssignments', + rpcArgs + ); + return new Resource(result, this._client); + } + + /** Assigns Event Hubs roles to a resource */ + withEventHubsRoleAssignments(target: AzureEventHubsResource, roles: AzureEventHubsRole[]): ResourcePromise { + return new ResourcePromise(this._withEventHubsRoleAssignmentsInternal(target, roles)); + } + +} + +/** + * Thenable wrapper for Resource that enables fluent chaining. + * @example + * await builder.addSomething().withX().withY(); + */ +export class ResourcePromise implements PromiseLike { + constructor(private _promise: Promise) {} + + then( + onfulfilled?: ((value: Resource) => TResult1 | PromiseLike) | null, + onrejected?: ((reason: unknown) => TResult2 | PromiseLike) | null + ): PromiseLike { + return this._promise.then(onfulfilled, onrejected); + } + + /** Configures a resource to use a container registry */ + withContainerRegistry(registry: ResourceBuilderBase): ResourcePromise { + return new ResourcePromise(this._promise.then(obj => obj.withContainerRegistry(registry))); + } + + /** Sets the base image for a Dockerfile build */ + withDockerfileBaseImage(options?: WithDockerfileBaseImageOptions): ResourcePromise { + return new ResourcePromise(this._promise.then(obj => obj.withDockerfileBaseImage(options))); + } + + /** Adds a required command dependency */ + withRequiredCommand(command: string, options?: WithRequiredCommandOptions): ResourcePromise { + return new ResourcePromise(this._promise.then(obj => obj.withRequiredCommand(command, options))); + } + + /** Customizes displayed URLs via callback */ + withUrlsCallback(callback: (obj: ResourceUrlsCallbackContext) => Promise): ResourcePromise { + return new ResourcePromise(this._promise.then(obj => obj.withUrlsCallback(callback))); + } + + /** Customizes displayed URLs via async callback */ + withUrlsCallbackAsync(callback: (arg: ResourceUrlsCallbackContext) => Promise): ResourcePromise { + return new ResourcePromise(this._promise.then(obj => obj.withUrlsCallbackAsync(callback))); + } + + /** Adds or modifies displayed URLs */ + withUrl(url: string, options?: WithUrlOptions): ResourcePromise { + return new ResourcePromise(this._promise.then(obj => obj.withUrl(url, options))); + } + + /** Adds a URL using a reference expression */ + withUrlExpression(url: ReferenceExpression, options?: WithUrlExpressionOptions): ResourcePromise { + return new ResourcePromise(this._promise.then(obj => obj.withUrlExpression(url, options))); + } + + /** Customizes the URL for a specific endpoint via callback */ + withUrlForEndpoint(endpointName: string, callback: (obj: ResourceUrlAnnotation) => Promise): ResourcePromise { + return new ResourcePromise(this._promise.then(obj => obj.withUrlForEndpoint(endpointName, callback))); + } + + /** Excludes the resource from the deployment manifest */ + excludeFromManifest(): ResourcePromise { + return new ResourcePromise(this._promise.then(obj => obj.excludeFromManifest())); + } + + /** Prevents resource from starting automatically */ + withExplicitStart(): ResourcePromise { + return new ResourcePromise(this._promise.then(obj => obj.withExplicitStart())); + } + + /** Adds a health check by key */ + withHealthCheck(key: string): ResourcePromise { + return new ResourcePromise(this._promise.then(obj => obj.withHealthCheck(key))); + } + + /** Adds a resource command */ + withCommand(name: string, displayName: string, executeCommand: (arg: ExecuteCommandContext) => Promise, options?: WithCommandOptions): ResourcePromise { + return new ResourcePromise(this._promise.then(obj => obj.withCommand(name, displayName, executeCommand, options))); + } + + /** Sets the parent relationship */ + withParentRelationship(parent: ResourceBuilderBase): ResourcePromise { + return new ResourcePromise(this._promise.then(obj => obj.withParentRelationship(parent))); + } + + /** Sets a child relationship */ + withChildRelationship(child: ResourceBuilderBase): ResourcePromise { + return new ResourcePromise(this._promise.then(obj => obj.withChildRelationship(child))); + } + + /** Sets the icon for the resource */ + withIconName(iconName: string, options?: WithIconNameOptions): ResourcePromise { + return new ResourcePromise(this._promise.then(obj => obj.withIconName(iconName, options))); + } + + /** Excludes the resource from MCP server exposure */ + excludeFromMcp(): ResourcePromise { + return new ResourcePromise(this._promise.then(obj => obj.excludeFromMcp())); + } + + /** Adds a pipeline step to the resource */ + withPipelineStepFactory(stepName: string, callback: (arg: PipelineStepContext) => Promise, options?: WithPipelineStepFactoryOptions): ResourcePromise { + return new ResourcePromise(this._promise.then(obj => obj.withPipelineStepFactory(stepName, callback, options))); + } + + /** Configures pipeline step dependencies via an async callback */ + withPipelineConfigurationAsync(callback: (arg: PipelineConfigurationContext) => Promise): ResourcePromise { + return new ResourcePromise(this._promise.then(obj => obj.withPipelineConfigurationAsync(callback))); + } + + /** Configures pipeline step dependencies via a callback */ + withPipelineConfiguration(callback: (obj: PipelineConfigurationContext) => Promise): ResourcePromise { + return new ResourcePromise(this._promise.then(obj => obj.withPipelineConfiguration(callback))); + } + + /** Gets the resource name */ + getResourceName(): Promise { + return this._promise.then(obj => obj.getResourceName()); + } + + /** Assigns Azure Storage roles to a resource */ + withStorageRoleAssignments(target: AzureStorageResource, roles: AzureStorageRole[]): ResourcePromise { + return new ResourcePromise(this._promise.then(obj => obj.withStorageRoleAssignments(target, roles))); + } + + /** Assigns Event Hubs roles to a resource */ + withEventHubsRoleAssignments(target: AzureEventHubsResource, roles: AzureEventHubsRole[]): ResourcePromise { + return new ResourcePromise(this._promise.then(obj => obj.withEventHubsRoleAssignments(target, roles))); + } + +} + +// ============================================================================ +// ResourceWithArgs +// ============================================================================ + +export class ResourceWithArgs extends ResourceBuilderBase { + constructor(handle: IResourceWithArgsHandle, client: AspireClientRpc) { + super(handle, client); + } + + /** @internal */ + private async _withArgsInternal(args: string[]): Promise { + const rpcArgs: Record = { builder: this._handle, args }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withArgs', + rpcArgs + ); + return new ResourceWithArgs(result, this._client); + } + + /** Adds arguments */ + withArgs(args: string[]): ResourceWithArgsPromise { + return new ResourceWithArgsPromise(this._withArgsInternal(args)); + } + + /** @internal */ + private async _withArgsCallbackInternal(callback: (obj: CommandLineArgsCallbackContext) => Promise): Promise { + const callbackId = registerCallback(async (objData: unknown) => { + const objHandle = wrapIfHandle(objData) as CommandLineArgsCallbackContextHandle; + const obj = new CommandLineArgsCallbackContext(objHandle, this._client); + await callback(obj); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withArgsCallback', + rpcArgs + ); + return new ResourceWithArgs(result, this._client); + } + + /** Sets command-line arguments via callback */ + withArgsCallback(callback: (obj: CommandLineArgsCallbackContext) => Promise): ResourceWithArgsPromise { + return new ResourceWithArgsPromise(this._withArgsCallbackInternal(callback)); + } + + /** @internal */ + private async _withArgsCallbackAsyncInternal(callback: (arg: CommandLineArgsCallbackContext) => Promise): Promise { + const callbackId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as CommandLineArgsCallbackContextHandle; + const arg = new CommandLineArgsCallbackContext(argHandle, this._client); + await callback(arg); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withArgsCallbackAsync', + rpcArgs + ); + return new ResourceWithArgs(result, this._client); + } + + /** Sets command-line arguments via async callback */ + withArgsCallbackAsync(callback: (arg: CommandLineArgsCallbackContext) => Promise): ResourceWithArgsPromise { + return new ResourceWithArgsPromise(this._withArgsCallbackAsyncInternal(callback)); + } + +} + +/** + * Thenable wrapper for ResourceWithArgs that enables fluent chaining. + * @example + * await builder.addSomething().withX().withY(); + */ +export class ResourceWithArgsPromise implements PromiseLike { + constructor(private _promise: Promise) {} + + then( + onfulfilled?: ((value: ResourceWithArgs) => TResult1 | PromiseLike) | null, + onrejected?: ((reason: unknown) => TResult2 | PromiseLike) | null + ): PromiseLike { + return this._promise.then(onfulfilled, onrejected); + } + + /** Adds arguments */ + withArgs(args: string[]): ResourceWithArgsPromise { + return new ResourceWithArgsPromise(this._promise.then(obj => obj.withArgs(args))); + } + + /** Sets command-line arguments via callback */ + withArgsCallback(callback: (obj: CommandLineArgsCallbackContext) => Promise): ResourceWithArgsPromise { + return new ResourceWithArgsPromise(this._promise.then(obj => obj.withArgsCallback(callback))); + } + + /** Sets command-line arguments via async callback */ + withArgsCallbackAsync(callback: (arg: CommandLineArgsCallbackContext) => Promise): ResourceWithArgsPromise { + return new ResourceWithArgsPromise(this._promise.then(obj => obj.withArgsCallbackAsync(callback))); + } + +} + +// ============================================================================ +// ResourceWithConnectionString +// ============================================================================ + +export class ResourceWithConnectionString extends ResourceBuilderBase { + constructor(handle: IResourceWithConnectionStringHandle, client: AspireClientRpc) { + super(handle, client); + } + + /** @internal */ + private async _withConnectionPropertyInternal(name: string, value: ReferenceExpression): Promise { + const rpcArgs: Record = { builder: this._handle, name, value }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withConnectionProperty', + rpcArgs + ); + return new ResourceWithConnectionString(result, this._client); + } + + /** Adds a connection property with a reference expression */ + withConnectionProperty(name: string, value: ReferenceExpression): ResourceWithConnectionStringPromise { + return new ResourceWithConnectionStringPromise(this._withConnectionPropertyInternal(name, value)); + } + + /** @internal */ + private async _withConnectionPropertyValueInternal(name: string, value: string): Promise { + const rpcArgs: Record = { builder: this._handle, name, value }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withConnectionPropertyValue', + rpcArgs + ); + return new ResourceWithConnectionString(result, this._client); + } + + /** Adds a connection property with a string value */ + withConnectionPropertyValue(name: string, value: string): ResourceWithConnectionStringPromise { + return new ResourceWithConnectionStringPromise(this._withConnectionPropertyValueInternal(name, value)); + } + +} + +/** + * Thenable wrapper for ResourceWithConnectionString that enables fluent chaining. + * @example + * await builder.addSomething().withX().withY(); + */ +export class ResourceWithConnectionStringPromise implements PromiseLike { + constructor(private _promise: Promise) {} + + then( + onfulfilled?: ((value: ResourceWithConnectionString) => TResult1 | PromiseLike) | null, + onrejected?: ((reason: unknown) => TResult2 | PromiseLike) | null + ): PromiseLike { + return this._promise.then(onfulfilled, onrejected); + } + + /** Adds a connection property with a reference expression */ + withConnectionProperty(name: string, value: ReferenceExpression): ResourceWithConnectionStringPromise { + return new ResourceWithConnectionStringPromise(this._promise.then(obj => obj.withConnectionProperty(name, value))); + } + + /** Adds a connection property with a string value */ + withConnectionPropertyValue(name: string, value: string): ResourceWithConnectionStringPromise { + return new ResourceWithConnectionStringPromise(this._promise.then(obj => obj.withConnectionPropertyValue(name, value))); + } + +} + +// ============================================================================ +// ResourceWithContainerFiles +// ============================================================================ + +export class ResourceWithContainerFiles extends ResourceBuilderBase { + constructor(handle: IResourceWithContainerFilesHandle, client: AspireClientRpc) { + super(handle, client); + } + + /** @internal */ + private async _withContainerFilesSourceInternal(sourcePath: string): Promise { + const rpcArgs: Record = { builder: this._handle, sourcePath }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withContainerFilesSource', + rpcArgs + ); + return new ResourceWithContainerFiles(result, this._client); + } + + /** Sets the source directory for container files */ + withContainerFilesSource(sourcePath: string): ResourceWithContainerFilesPromise { + return new ResourceWithContainerFilesPromise(this._withContainerFilesSourceInternal(sourcePath)); + } + + /** @internal */ + private async _clearContainerFilesSourcesInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/clearContainerFilesSources', + rpcArgs + ); + return new ResourceWithContainerFiles(result, this._client); + } + + /** Clears all container file sources */ + clearContainerFilesSources(): ResourceWithContainerFilesPromise { + return new ResourceWithContainerFilesPromise(this._clearContainerFilesSourcesInternal()); + } + +} + +/** + * Thenable wrapper for ResourceWithContainerFiles that enables fluent chaining. + * @example + * await builder.addSomething().withX().withY(); + */ +export class ResourceWithContainerFilesPromise implements PromiseLike { + constructor(private _promise: Promise) {} + + then( + onfulfilled?: ((value: ResourceWithContainerFiles) => TResult1 | PromiseLike) | null, + onrejected?: ((reason: unknown) => TResult2 | PromiseLike) | null + ): PromiseLike { + return this._promise.then(onfulfilled, onrejected); + } + + /** Sets the source directory for container files */ + withContainerFilesSource(sourcePath: string): ResourceWithContainerFilesPromise { + return new ResourceWithContainerFilesPromise(this._promise.then(obj => obj.withContainerFilesSource(sourcePath))); + } + + /** Clears all container file sources */ + clearContainerFilesSources(): ResourceWithContainerFilesPromise { + return new ResourceWithContainerFilesPromise(this._promise.then(obj => obj.clearContainerFilesSources())); + } + +} + +// ============================================================================ +// ResourceWithEndpoints +// ============================================================================ + +export class ResourceWithEndpoints extends ResourceBuilderBase { + constructor(handle: IResourceWithEndpointsHandle, client: AspireClientRpc) { + super(handle, client); + } + + /** @internal */ + private async _withMcpServerInternal(path?: string, endpointName?: string): Promise { + const rpcArgs: Record = { builder: this._handle }; + if (path !== undefined) rpcArgs.path = path; + if (endpointName !== undefined) rpcArgs.endpointName = endpointName; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withMcpServer', + rpcArgs + ); + return new ResourceWithEndpoints(result, this._client); + } + + /** Configures an MCP server endpoint on the resource */ + withMcpServer(options?: WithMcpServerOptions): ResourceWithEndpointsPromise { + const path = options?.path; + const endpointName = options?.endpointName; + return new ResourceWithEndpointsPromise(this._withMcpServerInternal(path, endpointName)); + } + + /** @internal */ + private async _withEndpointInternal(port?: number, targetPort?: number, scheme?: string, name?: string, env?: string, isProxied?: boolean, isExternal?: boolean, protocol?: ProtocolType): Promise { + const rpcArgs: Record = { builder: this._handle }; + if (port !== undefined) rpcArgs.port = port; + if (targetPort !== undefined) rpcArgs.targetPort = targetPort; + if (scheme !== undefined) rpcArgs.scheme = scheme; + if (name !== undefined) rpcArgs.name = name; + if (env !== undefined) rpcArgs.env = env; + if (isProxied !== undefined) rpcArgs.isProxied = isProxied; + if (isExternal !== undefined) rpcArgs.isExternal = isExternal; + if (protocol !== undefined) rpcArgs.protocol = protocol; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withEndpoint', + rpcArgs + ); + return new ResourceWithEndpoints(result, this._client); + } + + /** Adds a network endpoint */ + withEndpoint(options?: WithEndpointOptions): ResourceWithEndpointsPromise { + const port = options?.port; + const targetPort = options?.targetPort; + const scheme = options?.scheme; + const name = options?.name; + const env = options?.env; + const isProxied = options?.isProxied; + const isExternal = options?.isExternal; + const protocol = options?.protocol; + return new ResourceWithEndpointsPromise(this._withEndpointInternal(port, targetPort, scheme, name, env, isProxied, isExternal, protocol)); + } + + /** @internal */ + private async _withHttpEndpointInternal(port?: number, targetPort?: number, name?: string, env?: string, isProxied?: boolean): Promise { + const rpcArgs: Record = { builder: this._handle }; + if (port !== undefined) rpcArgs.port = port; + if (targetPort !== undefined) rpcArgs.targetPort = targetPort; + if (name !== undefined) rpcArgs.name = name; + if (env !== undefined) rpcArgs.env = env; + if (isProxied !== undefined) rpcArgs.isProxied = isProxied; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withHttpEndpoint', + rpcArgs + ); + return new ResourceWithEndpoints(result, this._client); + } + + /** Adds an HTTP endpoint */ + withHttpEndpoint(options?: WithHttpEndpointOptions): ResourceWithEndpointsPromise { + const port = options?.port; + const targetPort = options?.targetPort; + const name = options?.name; + const env = options?.env; + const isProxied = options?.isProxied; + return new ResourceWithEndpointsPromise(this._withHttpEndpointInternal(port, targetPort, name, env, isProxied)); + } + + /** @internal */ + private async _withHttpsEndpointInternal(port?: number, targetPort?: number, name?: string, env?: string, isProxied?: boolean): Promise { + const rpcArgs: Record = { builder: this._handle }; + if (port !== undefined) rpcArgs.port = port; + if (targetPort !== undefined) rpcArgs.targetPort = targetPort; + if (name !== undefined) rpcArgs.name = name; + if (env !== undefined) rpcArgs.env = env; + if (isProxied !== undefined) rpcArgs.isProxied = isProxied; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withHttpsEndpoint', + rpcArgs + ); + return new ResourceWithEndpoints(result, this._client); + } + + /** Adds an HTTPS endpoint */ + withHttpsEndpoint(options?: WithHttpsEndpointOptions): ResourceWithEndpointsPromise { + const port = options?.port; + const targetPort = options?.targetPort; + const name = options?.name; + const env = options?.env; + const isProxied = options?.isProxied; + return new ResourceWithEndpointsPromise(this._withHttpsEndpointInternal(port, targetPort, name, env, isProxied)); + } + + /** @internal */ + private async _withExternalHttpEndpointsInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withExternalHttpEndpoints', + rpcArgs + ); + return new ResourceWithEndpoints(result, this._client); + } + + /** Makes HTTP endpoints externally accessible */ + withExternalHttpEndpoints(): ResourceWithEndpointsPromise { + return new ResourceWithEndpointsPromise(this._withExternalHttpEndpointsInternal()); + } + + /** Gets an endpoint reference */ + async getEndpoint(name: string): Promise { + const rpcArgs: Record = { builder: this._handle, name }; + return await this._client.invokeCapability( + 'Aspire.Hosting/getEndpoint', + rpcArgs + ); + } + + /** @internal */ + private async _asHttp2ServiceInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/asHttp2Service', + rpcArgs + ); + return new ResourceWithEndpoints(result, this._client); + } + + /** Configures resource for HTTP/2 */ + asHttp2Service(): ResourceWithEndpointsPromise { + return new ResourceWithEndpointsPromise(this._asHttp2ServiceInternal()); + } + + /** @internal */ + private async _withUrlForEndpointFactoryInternal(endpointName: string, callback: (arg: EndpointReference) => Promise): Promise { + const callbackId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as EndpointReferenceHandle; + const arg = new EndpointReference(argHandle, this._client); + return await callback(arg); + }); + const rpcArgs: Record = { builder: this._handle, endpointName, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withUrlForEndpointFactory', + rpcArgs + ); + return new ResourceWithEndpoints(result, this._client); + } + + /** Adds a URL for a specific endpoint via factory callback */ + withUrlForEndpointFactory(endpointName: string, callback: (arg: EndpointReference) => Promise): ResourceWithEndpointsPromise { + return new ResourceWithEndpointsPromise(this._withUrlForEndpointFactoryInternal(endpointName, callback)); + } + + /** @internal */ + private async _withHttpHealthCheckInternal(path?: string, statusCode?: number, endpointName?: string): Promise { + const rpcArgs: Record = { builder: this._handle }; + if (path !== undefined) rpcArgs.path = path; + if (statusCode !== undefined) rpcArgs.statusCode = statusCode; + if (endpointName !== undefined) rpcArgs.endpointName = endpointName; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withHttpHealthCheck', + rpcArgs + ); + return new ResourceWithEndpoints(result, this._client); + } + + /** Adds an HTTP health check */ + withHttpHealthCheck(options?: WithHttpHealthCheckOptions): ResourceWithEndpointsPromise { + const path = options?.path; + const statusCode = options?.statusCode; + const endpointName = options?.endpointName; + return new ResourceWithEndpointsPromise(this._withHttpHealthCheckInternal(path, statusCode, endpointName)); + } + + /** @internal */ + private async _withHttpProbeInternal(probeType: ProbeType, path?: string, initialDelaySeconds?: number, periodSeconds?: number, timeoutSeconds?: number, failureThreshold?: number, successThreshold?: number, endpointName?: string): Promise { + const rpcArgs: Record = { builder: this._handle, probeType }; + if (path !== undefined) rpcArgs.path = path; + if (initialDelaySeconds !== undefined) rpcArgs.initialDelaySeconds = initialDelaySeconds; + if (periodSeconds !== undefined) rpcArgs.periodSeconds = periodSeconds; + if (timeoutSeconds !== undefined) rpcArgs.timeoutSeconds = timeoutSeconds; + if (failureThreshold !== undefined) rpcArgs.failureThreshold = failureThreshold; + if (successThreshold !== undefined) rpcArgs.successThreshold = successThreshold; + if (endpointName !== undefined) rpcArgs.endpointName = endpointName; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withHttpProbe', + rpcArgs + ); + return new ResourceWithEndpoints(result, this._client); + } + + /** Adds an HTTP health probe to the resource */ + withHttpProbe(probeType: ProbeType, options?: WithHttpProbeOptions): ResourceWithEndpointsPromise { + const path = options?.path; + const initialDelaySeconds = options?.initialDelaySeconds; + const periodSeconds = options?.periodSeconds; + const timeoutSeconds = options?.timeoutSeconds; + const failureThreshold = options?.failureThreshold; + const successThreshold = options?.successThreshold; + const endpointName = options?.endpointName; + return new ResourceWithEndpointsPromise(this._withHttpProbeInternal(probeType, path, initialDelaySeconds, periodSeconds, timeoutSeconds, failureThreshold, successThreshold, endpointName)); + } + +} + +/** + * Thenable wrapper for ResourceWithEndpoints that enables fluent chaining. + * @example + * await builder.addSomething().withX().withY(); + */ +export class ResourceWithEndpointsPromise implements PromiseLike { + constructor(private _promise: Promise) {} + + then( + onfulfilled?: ((value: ResourceWithEndpoints) => TResult1 | PromiseLike) | null, + onrejected?: ((reason: unknown) => TResult2 | PromiseLike) | null + ): PromiseLike { + return this._promise.then(onfulfilled, onrejected); + } + + /** Configures an MCP server endpoint on the resource */ + withMcpServer(options?: WithMcpServerOptions): ResourceWithEndpointsPromise { + return new ResourceWithEndpointsPromise(this._promise.then(obj => obj.withMcpServer(options))); + } + + /** Adds a network endpoint */ + withEndpoint(options?: WithEndpointOptions): ResourceWithEndpointsPromise { + return new ResourceWithEndpointsPromise(this._promise.then(obj => obj.withEndpoint(options))); + } + + /** Adds an HTTP endpoint */ + withHttpEndpoint(options?: WithHttpEndpointOptions): ResourceWithEndpointsPromise { + return new ResourceWithEndpointsPromise(this._promise.then(obj => obj.withHttpEndpoint(options))); + } + + /** Adds an HTTPS endpoint */ + withHttpsEndpoint(options?: WithHttpsEndpointOptions): ResourceWithEndpointsPromise { + return new ResourceWithEndpointsPromise(this._promise.then(obj => obj.withHttpsEndpoint(options))); + } + + /** Makes HTTP endpoints externally accessible */ + withExternalHttpEndpoints(): ResourceWithEndpointsPromise { + return new ResourceWithEndpointsPromise(this._promise.then(obj => obj.withExternalHttpEndpoints())); + } + + /** Gets an endpoint reference */ + getEndpoint(name: string): Promise { + return this._promise.then(obj => obj.getEndpoint(name)); + } + + /** Configures resource for HTTP/2 */ + asHttp2Service(): ResourceWithEndpointsPromise { + return new ResourceWithEndpointsPromise(this._promise.then(obj => obj.asHttp2Service())); + } + + /** Adds a URL for a specific endpoint via factory callback */ + withUrlForEndpointFactory(endpointName: string, callback: (arg: EndpointReference) => Promise): ResourceWithEndpointsPromise { + return new ResourceWithEndpointsPromise(this._promise.then(obj => obj.withUrlForEndpointFactory(endpointName, callback))); + } + + /** Adds an HTTP health check */ + withHttpHealthCheck(options?: WithHttpHealthCheckOptions): ResourceWithEndpointsPromise { + return new ResourceWithEndpointsPromise(this._promise.then(obj => obj.withHttpHealthCheck(options))); + } + + /** Adds an HTTP health probe to the resource */ + withHttpProbe(probeType: ProbeType, options?: WithHttpProbeOptions): ResourceWithEndpointsPromise { + return new ResourceWithEndpointsPromise(this._promise.then(obj => obj.withHttpProbe(probeType, options))); + } + +} + +// ============================================================================ +// ResourceWithEnvironment +// ============================================================================ + +export class ResourceWithEnvironment extends ResourceBuilderBase { + constructor(handle: IResourceWithEnvironmentHandle, client: AspireClientRpc) { + super(handle, client); + } + + /** @internal */ + private async _withOtlpExporterInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withOtlpExporter', + rpcArgs + ); + return new ResourceWithEnvironment(result, this._client); + } + + /** Configures OTLP telemetry export */ + withOtlpExporter(): ResourceWithEnvironmentPromise { + return new ResourceWithEnvironmentPromise(this._withOtlpExporterInternal()); + } + + /** @internal */ + private async _withOtlpExporterProtocolInternal(protocol: OtlpProtocol): Promise { + const rpcArgs: Record = { builder: this._handle, protocol }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withOtlpExporterProtocol', + rpcArgs + ); + return new ResourceWithEnvironment(result, this._client); + } + + /** Configures OTLP telemetry export with specific protocol */ + withOtlpExporterProtocol(protocol: OtlpProtocol): ResourceWithEnvironmentPromise { + return new ResourceWithEnvironmentPromise(this._withOtlpExporterProtocolInternal(protocol)); + } + + /** @internal */ + private async _withEnvironmentInternal(name: string, value: string): Promise { + const rpcArgs: Record = { builder: this._handle, name, value }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withEnvironment', + rpcArgs + ); + return new ResourceWithEnvironment(result, this._client); + } + + /** Sets an environment variable */ + withEnvironment(name: string, value: string): ResourceWithEnvironmentPromise { + return new ResourceWithEnvironmentPromise(this._withEnvironmentInternal(name, value)); + } + + /** @internal */ + private async _withEnvironmentExpressionInternal(name: string, value: ReferenceExpression): Promise { + const rpcArgs: Record = { builder: this._handle, name, value }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withEnvironmentExpression', + rpcArgs + ); + return new ResourceWithEnvironment(result, this._client); + } + + /** Adds an environment variable with a reference expression */ + withEnvironmentExpression(name: string, value: ReferenceExpression): ResourceWithEnvironmentPromise { + return new ResourceWithEnvironmentPromise(this._withEnvironmentExpressionInternal(name, value)); + } + + /** @internal */ + private async _withEnvironmentCallbackInternal(callback: (obj: EnvironmentCallbackContext) => Promise): Promise { + const callbackId = registerCallback(async (objData: unknown) => { + const objHandle = wrapIfHandle(objData) as EnvironmentCallbackContextHandle; + const obj = new EnvironmentCallbackContext(objHandle, this._client); + await callback(obj); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withEnvironmentCallback', + rpcArgs + ); + return new ResourceWithEnvironment(result, this._client); + } + + /** Sets environment variables via callback */ + withEnvironmentCallback(callback: (obj: EnvironmentCallbackContext) => Promise): ResourceWithEnvironmentPromise { + return new ResourceWithEnvironmentPromise(this._withEnvironmentCallbackInternal(callback)); + } + + /** @internal */ + private async _withEnvironmentCallbackAsyncInternal(callback: (arg: EnvironmentCallbackContext) => Promise): Promise { + const callbackId = registerCallback(async (argData: unknown) => { + const argHandle = wrapIfHandle(argData) as EnvironmentCallbackContextHandle; + const arg = new EnvironmentCallbackContext(argHandle, this._client); + await callback(arg); + }); + const rpcArgs: Record = { builder: this._handle, callback: callbackId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withEnvironmentCallbackAsync', + rpcArgs + ); + return new ResourceWithEnvironment(result, this._client); + } + + /** Sets environment variables via async callback */ + withEnvironmentCallbackAsync(callback: (arg: EnvironmentCallbackContext) => Promise): ResourceWithEnvironmentPromise { + return new ResourceWithEnvironmentPromise(this._withEnvironmentCallbackAsyncInternal(callback)); + } + + /** @internal */ + private async _withEnvironmentEndpointInternal(name: string, endpointReference: EndpointReference): Promise { + const rpcArgs: Record = { builder: this._handle, name, endpointReference }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withEnvironmentEndpoint', + rpcArgs + ); + return new ResourceWithEnvironment(result, this._client); + } + + /** Sets an environment variable from an endpoint reference */ + withEnvironmentEndpoint(name: string, endpointReference: EndpointReference): ResourceWithEnvironmentPromise { + return new ResourceWithEnvironmentPromise(this._withEnvironmentEndpointInternal(name, endpointReference)); + } + + /** @internal */ + private async _withEnvironmentParameterInternal(name: string, parameter: ParameterResource): Promise { + const rpcArgs: Record = { builder: this._handle, name, parameter }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withEnvironmentParameter', + rpcArgs + ); + return new ResourceWithEnvironment(result, this._client); + } + + /** Sets an environment variable from a parameter resource */ + withEnvironmentParameter(name: string, parameter: ParameterResource): ResourceWithEnvironmentPromise { + return new ResourceWithEnvironmentPromise(this._withEnvironmentParameterInternal(name, parameter)); + } + + /** @internal */ + private async _withEnvironmentConnectionStringInternal(envVarName: string, resource: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, envVarName, resource }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withEnvironmentConnectionString', + rpcArgs + ); + return new ResourceWithEnvironment(result, this._client); + } + + /** Sets an environment variable from a connection string resource */ + withEnvironmentConnectionString(envVarName: string, resource: ResourceBuilderBase): ResourceWithEnvironmentPromise { + return new ResourceWithEnvironmentPromise(this._withEnvironmentConnectionStringInternal(envVarName, resource)); + } + + /** @internal */ + private async _withReferenceInternal(source: ResourceBuilderBase, connectionName?: string, optional?: boolean): Promise { + const rpcArgs: Record = { builder: this._handle, source }; + if (connectionName !== undefined) rpcArgs.connectionName = connectionName; + if (optional !== undefined) rpcArgs.optional = optional; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withReference', + rpcArgs + ); + return new ResourceWithEnvironment(result, this._client); + } + + /** Adds a reference to another resource */ + withReference(source: ResourceBuilderBase, options?: WithReferenceOptions): ResourceWithEnvironmentPromise { + const connectionName = options?.connectionName; + const optional = options?.optional; + return new ResourceWithEnvironmentPromise(this._withReferenceInternal(source, connectionName, optional)); + } + + /** @internal */ + private async _withServiceReferenceInternal(source: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, source }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withServiceReference', + rpcArgs + ); + return new ResourceWithEnvironment(result, this._client); + } + + /** Adds a service discovery reference to another resource */ + withServiceReference(source: ResourceBuilderBase): ResourceWithEnvironmentPromise { + return new ResourceWithEnvironmentPromise(this._withServiceReferenceInternal(source)); + } + + /** @internal */ + private async _withServiceReferenceNamedInternal(source: ResourceBuilderBase, name: string): Promise { + const rpcArgs: Record = { builder: this._handle, source, name }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withServiceReferenceNamed', + rpcArgs + ); + return new ResourceWithEnvironment(result, this._client); + } + + /** Adds a named service discovery reference */ + withServiceReferenceNamed(source: ResourceBuilderBase, name: string): ResourceWithEnvironmentPromise { + return new ResourceWithEnvironmentPromise(this._withServiceReferenceNamedInternal(source, name)); + } + + /** @internal */ + private async _withReferenceUriInternal(name: string, uri: string): Promise { + const rpcArgs: Record = { builder: this._handle, name, uri }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withReferenceUri', + rpcArgs + ); + return new ResourceWithEnvironment(result, this._client); + } + + /** Adds a reference to a URI */ + withReferenceUri(name: string, uri: string): ResourceWithEnvironmentPromise { + return new ResourceWithEnvironmentPromise(this._withReferenceUriInternal(name, uri)); + } + + /** @internal */ + private async _withReferenceExternalServiceInternal(externalService: ExternalServiceResource): Promise { + const rpcArgs: Record = { builder: this._handle, externalService }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withReferenceExternalService', + rpcArgs + ); + return new ResourceWithEnvironment(result, this._client); + } + + /** Adds a reference to an external service */ + withReferenceExternalService(externalService: ExternalServiceResource): ResourceWithEnvironmentPromise { + return new ResourceWithEnvironmentPromise(this._withReferenceExternalServiceInternal(externalService)); + } + + /** @internal */ + private async _withReferenceEndpointInternal(endpointReference: EndpointReference): Promise { + const rpcArgs: Record = { builder: this._handle, endpointReference }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withReferenceEndpoint', + rpcArgs + ); + return new ResourceWithEnvironment(result, this._client); + } + + /** Adds a reference to an endpoint */ + withReferenceEndpoint(endpointReference: EndpointReference): ResourceWithEnvironmentPromise { + return new ResourceWithEnvironmentPromise(this._withReferenceEndpointInternal(endpointReference)); + } + + /** @internal */ + private async _withDeveloperCertificateTrustInternal(trust: boolean): Promise { + const rpcArgs: Record = { builder: this._handle, trust }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withDeveloperCertificateTrust', + rpcArgs + ); + return new ResourceWithEnvironment(result, this._client); + } + + /** Configures developer certificate trust */ + withDeveloperCertificateTrust(trust: boolean): ResourceWithEnvironmentPromise { + return new ResourceWithEnvironmentPromise(this._withDeveloperCertificateTrustInternal(trust)); + } + + /** @internal */ + private async _withCertificateTrustScopeInternal(scope: CertificateTrustScope): Promise { + const rpcArgs: Record = { builder: this._handle, scope }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withCertificateTrustScope', + rpcArgs + ); + return new ResourceWithEnvironment(result, this._client); + } + + /** Sets the certificate trust scope */ + withCertificateTrustScope(scope: CertificateTrustScope): ResourceWithEnvironmentPromise { + return new ResourceWithEnvironmentPromise(this._withCertificateTrustScopeInternal(scope)); + } + + /** @internal */ + private async _withHttpsDeveloperCertificateInternal(password?: ParameterResource): Promise { + const rpcArgs: Record = { builder: this._handle }; + if (password !== undefined) rpcArgs.password = password; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withHttpsDeveloperCertificate', + rpcArgs + ); + return new ResourceWithEnvironment(result, this._client); + } + + /** Configures HTTPS with a developer certificate */ + withHttpsDeveloperCertificate(options?: WithHttpsDeveloperCertificateOptions): ResourceWithEnvironmentPromise { + const password = options?.password; + return new ResourceWithEnvironmentPromise(this._withHttpsDeveloperCertificateInternal(password)); + } + + /** @internal */ + private async _withoutHttpsCertificateInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withoutHttpsCertificate', + rpcArgs + ); + return new ResourceWithEnvironment(result, this._client); + } + + /** Removes HTTPS certificate configuration */ + withoutHttpsCertificate(): ResourceWithEnvironmentPromise { + return new ResourceWithEnvironmentPromise(this._withoutHttpsCertificateInternal()); + } + + /** @internal */ + private async _withEnvironmentFromOutputInternal(name: string, bicepOutputReference: BicepOutputReference): Promise { + const rpcArgs: Record = { builder: this._handle, name, bicepOutputReference }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure/withEnvironmentFromOutput', + rpcArgs + ); + return new ResourceWithEnvironment(result, this._client); + } + + /** Sets an environment variable from a Bicep output reference */ + withEnvironmentFromOutput(name: string, bicepOutputReference: BicepOutputReference): ResourceWithEnvironmentPromise { + return new ResourceWithEnvironmentPromise(this._withEnvironmentFromOutputInternal(name, bicepOutputReference)); + } + + /** @internal */ + private async _withEnvironmentFromKeyVaultSecretInternal(name: string, secretReference: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, name, secretReference }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting.Azure/withEnvironmentFromKeyVaultSecret', + rpcArgs + ); + return new ResourceWithEnvironment(result, this._client); + } + + /** Sets an environment variable from an Azure Key Vault secret reference */ + withEnvironmentFromKeyVaultSecret(name: string, secretReference: ResourceBuilderBase): ResourceWithEnvironmentPromise { + return new ResourceWithEnvironmentPromise(this._withEnvironmentFromKeyVaultSecretInternal(name, secretReference)); + } + +} + +/** + * Thenable wrapper for ResourceWithEnvironment that enables fluent chaining. + * @example + * await builder.addSomething().withX().withY(); + */ +export class ResourceWithEnvironmentPromise implements PromiseLike { + constructor(private _promise: Promise) {} + + then( + onfulfilled?: ((value: ResourceWithEnvironment) => TResult1 | PromiseLike) | null, + onrejected?: ((reason: unknown) => TResult2 | PromiseLike) | null + ): PromiseLike { + return this._promise.then(onfulfilled, onrejected); + } + + /** Configures OTLP telemetry export */ + withOtlpExporter(): ResourceWithEnvironmentPromise { + return new ResourceWithEnvironmentPromise(this._promise.then(obj => obj.withOtlpExporter())); + } + + /** Configures OTLP telemetry export with specific protocol */ + withOtlpExporterProtocol(protocol: OtlpProtocol): ResourceWithEnvironmentPromise { + return new ResourceWithEnvironmentPromise(this._promise.then(obj => obj.withOtlpExporterProtocol(protocol))); + } + + /** Sets an environment variable */ + withEnvironment(name: string, value: string): ResourceWithEnvironmentPromise { + return new ResourceWithEnvironmentPromise(this._promise.then(obj => obj.withEnvironment(name, value))); + } + + /** Adds an environment variable with a reference expression */ + withEnvironmentExpression(name: string, value: ReferenceExpression): ResourceWithEnvironmentPromise { + return new ResourceWithEnvironmentPromise(this._promise.then(obj => obj.withEnvironmentExpression(name, value))); + } + + /** Sets environment variables via callback */ + withEnvironmentCallback(callback: (obj: EnvironmentCallbackContext) => Promise): ResourceWithEnvironmentPromise { + return new ResourceWithEnvironmentPromise(this._promise.then(obj => obj.withEnvironmentCallback(callback))); + } + + /** Sets environment variables via async callback */ + withEnvironmentCallbackAsync(callback: (arg: EnvironmentCallbackContext) => Promise): ResourceWithEnvironmentPromise { + return new ResourceWithEnvironmentPromise(this._promise.then(obj => obj.withEnvironmentCallbackAsync(callback))); + } + + /** Sets an environment variable from an endpoint reference */ + withEnvironmentEndpoint(name: string, endpointReference: EndpointReference): ResourceWithEnvironmentPromise { + return new ResourceWithEnvironmentPromise(this._promise.then(obj => obj.withEnvironmentEndpoint(name, endpointReference))); + } + + /** Sets an environment variable from a parameter resource */ + withEnvironmentParameter(name: string, parameter: ParameterResource): ResourceWithEnvironmentPromise { + return new ResourceWithEnvironmentPromise(this._promise.then(obj => obj.withEnvironmentParameter(name, parameter))); + } + + /** Sets an environment variable from a connection string resource */ + withEnvironmentConnectionString(envVarName: string, resource: ResourceBuilderBase): ResourceWithEnvironmentPromise { + return new ResourceWithEnvironmentPromise(this._promise.then(obj => obj.withEnvironmentConnectionString(envVarName, resource))); + } + + /** Adds a reference to another resource */ + withReference(source: ResourceBuilderBase, options?: WithReferenceOptions): ResourceWithEnvironmentPromise { + return new ResourceWithEnvironmentPromise(this._promise.then(obj => obj.withReference(source, options))); + } + + /** Adds a service discovery reference to another resource */ + withServiceReference(source: ResourceBuilderBase): ResourceWithEnvironmentPromise { + return new ResourceWithEnvironmentPromise(this._promise.then(obj => obj.withServiceReference(source))); + } + + /** Adds a named service discovery reference */ + withServiceReferenceNamed(source: ResourceBuilderBase, name: string): ResourceWithEnvironmentPromise { + return new ResourceWithEnvironmentPromise(this._promise.then(obj => obj.withServiceReferenceNamed(source, name))); + } + + /** Adds a reference to a URI */ + withReferenceUri(name: string, uri: string): ResourceWithEnvironmentPromise { + return new ResourceWithEnvironmentPromise(this._promise.then(obj => obj.withReferenceUri(name, uri))); + } + + /** Adds a reference to an external service */ + withReferenceExternalService(externalService: ExternalServiceResource): ResourceWithEnvironmentPromise { + return new ResourceWithEnvironmentPromise(this._promise.then(obj => obj.withReferenceExternalService(externalService))); + } + + /** Adds a reference to an endpoint */ + withReferenceEndpoint(endpointReference: EndpointReference): ResourceWithEnvironmentPromise { + return new ResourceWithEnvironmentPromise(this._promise.then(obj => obj.withReferenceEndpoint(endpointReference))); + } + + /** Configures developer certificate trust */ + withDeveloperCertificateTrust(trust: boolean): ResourceWithEnvironmentPromise { + return new ResourceWithEnvironmentPromise(this._promise.then(obj => obj.withDeveloperCertificateTrust(trust))); + } + + /** Sets the certificate trust scope */ + withCertificateTrustScope(scope: CertificateTrustScope): ResourceWithEnvironmentPromise { + return new ResourceWithEnvironmentPromise(this._promise.then(obj => obj.withCertificateTrustScope(scope))); + } + + /** Configures HTTPS with a developer certificate */ + withHttpsDeveloperCertificate(options?: WithHttpsDeveloperCertificateOptions): ResourceWithEnvironmentPromise { + return new ResourceWithEnvironmentPromise(this._promise.then(obj => obj.withHttpsDeveloperCertificate(options))); + } + + /** Removes HTTPS certificate configuration */ + withoutHttpsCertificate(): ResourceWithEnvironmentPromise { + return new ResourceWithEnvironmentPromise(this._promise.then(obj => obj.withoutHttpsCertificate())); + } + + /** Sets an environment variable from a Bicep output reference */ + withEnvironmentFromOutput(name: string, bicepOutputReference: BicepOutputReference): ResourceWithEnvironmentPromise { + return new ResourceWithEnvironmentPromise(this._promise.then(obj => obj.withEnvironmentFromOutput(name, bicepOutputReference))); + } + + /** Sets an environment variable from an Azure Key Vault secret reference */ + withEnvironmentFromKeyVaultSecret(name: string, secretReference: ResourceBuilderBase): ResourceWithEnvironmentPromise { + return new ResourceWithEnvironmentPromise(this._promise.then(obj => obj.withEnvironmentFromKeyVaultSecret(name, secretReference))); + } + +} + +// ============================================================================ +// ResourceWithServiceDiscovery +// ============================================================================ + +export class ResourceWithServiceDiscovery extends ResourceBuilderBase { + constructor(handle: IResourceWithServiceDiscoveryHandle, client: AspireClientRpc) { + super(handle, client); + } + +} + +/** + * Thenable wrapper for ResourceWithServiceDiscovery that enables fluent chaining. + * @example + * await builder.addSomething().withX().withY(); + */ +export class ResourceWithServiceDiscoveryPromise implements PromiseLike { + constructor(private _promise: Promise) {} + + then( + onfulfilled?: ((value: ResourceWithServiceDiscovery) => TResult1 | PromiseLike) | null, + onrejected?: ((reason: unknown) => TResult2 | PromiseLike) | null + ): PromiseLike { + return this._promise.then(onfulfilled, onrejected); + } + +} + +// ============================================================================ +// ResourceWithWaitSupport +// ============================================================================ + +export class ResourceWithWaitSupport extends ResourceBuilderBase { + constructor(handle: IResourceWithWaitSupportHandle, client: AspireClientRpc) { + super(handle, client); + } + + /** @internal */ + private async _waitForInternal(dependency: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, dependency }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/waitFor', + rpcArgs + ); + return new ResourceWithWaitSupport(result, this._client); + } + + /** Waits for another resource to be ready */ + waitFor(dependency: ResourceBuilderBase): ResourceWithWaitSupportPromise { + return new ResourceWithWaitSupportPromise(this._waitForInternal(dependency)); + } + + /** @internal */ + private async _waitForWithBehaviorInternal(dependency: ResourceBuilderBase, waitBehavior: WaitBehavior): Promise { + const rpcArgs: Record = { builder: this._handle, dependency, waitBehavior }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/waitForWithBehavior', + rpcArgs + ); + return new ResourceWithWaitSupport(result, this._client); + } + + /** Waits for another resource with specific behavior */ + waitForWithBehavior(dependency: ResourceBuilderBase, waitBehavior: WaitBehavior): ResourceWithWaitSupportPromise { + return new ResourceWithWaitSupportPromise(this._waitForWithBehaviorInternal(dependency, waitBehavior)); + } + + /** @internal */ + private async _waitForStartInternal(dependency: ResourceBuilderBase): Promise { + const rpcArgs: Record = { builder: this._handle, dependency }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/waitForStart', + rpcArgs + ); + return new ResourceWithWaitSupport(result, this._client); + } + + /** Waits for another resource to start */ + waitForStart(dependency: ResourceBuilderBase): ResourceWithWaitSupportPromise { + return new ResourceWithWaitSupportPromise(this._waitForStartInternal(dependency)); + } + + /** @internal */ + private async _waitForStartWithBehaviorInternal(dependency: ResourceBuilderBase, waitBehavior: WaitBehavior): Promise { + const rpcArgs: Record = { builder: this._handle, dependency, waitBehavior }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/waitForStartWithBehavior', + rpcArgs + ); + return new ResourceWithWaitSupport(result, this._client); + } + + /** Waits for another resource to start with specific behavior */ + waitForStartWithBehavior(dependency: ResourceBuilderBase, waitBehavior: WaitBehavior): ResourceWithWaitSupportPromise { + return new ResourceWithWaitSupportPromise(this._waitForStartWithBehaviorInternal(dependency, waitBehavior)); + } + + /** @internal */ + private async _waitForCompletionInternal(dependency: ResourceBuilderBase, exitCode?: number): Promise { + const rpcArgs: Record = { builder: this._handle, dependency }; + if (exitCode !== undefined) rpcArgs.exitCode = exitCode; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/waitForCompletion', + rpcArgs + ); + return new ResourceWithWaitSupport(result, this._client); + } + + /** Waits for resource completion */ + waitForCompletion(dependency: ResourceBuilderBase, options?: WaitForCompletionOptions): ResourceWithWaitSupportPromise { + const exitCode = options?.exitCode; + return new ResourceWithWaitSupportPromise(this._waitForCompletionInternal(dependency, exitCode)); + } + +} + +/** + * Thenable wrapper for ResourceWithWaitSupport that enables fluent chaining. + * @example + * await builder.addSomething().withX().withY(); + */ +export class ResourceWithWaitSupportPromise implements PromiseLike { + constructor(private _promise: Promise) {} + + then( + onfulfilled?: ((value: ResourceWithWaitSupport) => TResult1 | PromiseLike) | null, + onrejected?: ((reason: unknown) => TResult2 | PromiseLike) | null + ): PromiseLike { + return this._promise.then(onfulfilled, onrejected); + } + + /** Waits for another resource to be ready */ + waitFor(dependency: ResourceBuilderBase): ResourceWithWaitSupportPromise { + return new ResourceWithWaitSupportPromise(this._promise.then(obj => obj.waitFor(dependency))); + } + + /** Waits for another resource with specific behavior */ + waitForWithBehavior(dependency: ResourceBuilderBase, waitBehavior: WaitBehavior): ResourceWithWaitSupportPromise { + return new ResourceWithWaitSupportPromise(this._promise.then(obj => obj.waitForWithBehavior(dependency, waitBehavior))); + } + + /** Waits for another resource to start */ + waitForStart(dependency: ResourceBuilderBase): ResourceWithWaitSupportPromise { + return new ResourceWithWaitSupportPromise(this._promise.then(obj => obj.waitForStart(dependency))); + } + + /** Waits for another resource to start with specific behavior */ + waitForStartWithBehavior(dependency: ResourceBuilderBase, waitBehavior: WaitBehavior): ResourceWithWaitSupportPromise { + return new ResourceWithWaitSupportPromise(this._promise.then(obj => obj.waitForStartWithBehavior(dependency, waitBehavior))); + } + + /** Waits for resource completion */ + waitForCompletion(dependency: ResourceBuilderBase, options?: WaitForCompletionOptions): ResourceWithWaitSupportPromise { + return new ResourceWithWaitSupportPromise(this._promise.then(obj => obj.waitForCompletion(dependency, options))); + } + +} + +// ============================================================================ +// Connection Helper +// ============================================================================ + +/** + * Creates and connects to the Aspire AppHost. + * Reads connection info from environment variables set by `aspire run`. + */ +export async function connect(): Promise { + const socketPath = process.env.REMOTE_APP_HOST_SOCKET_PATH; + if (!socketPath) { + throw new Error( + 'REMOTE_APP_HOST_SOCKET_PATH environment variable not set. ' + + 'Run this application using `aspire run`.' + ); + } + + const client = new AspireClientRpc(socketPath); + await client.connect(); + + // Exit the process if the server connection is lost + client.onDisconnect(() => { + console.error('Connection to AppHost lost. Exiting...'); + process.exit(1); + }); + + return client; +} + +/** + * Creates a new distributed application builder. + * This is the entry point for building Aspire applications. + * + * @param options - Optional configuration options for the builder + * @returns A DistributedApplicationBuilder instance + * + * @example + * const builder = await createBuilder(); + * builder.addRedis("cache"); + * builder.addContainer("api", "mcr.microsoft.com/dotnet/samples:aspnetapp"); + * const app = await builder.build(); + * await app.run(); + */ +export async function createBuilder(options?: CreateBuilderOptions): Promise { + const client = await connect(); + + // Default args, projectDirectory, and appHostFilePath if not provided + // ASPIRE_APPHOST_FILEPATH is set by the CLI for consistent socket hash computation + const effectiveOptions: CreateBuilderOptions = { + ...options, + args: options?.args ?? process.argv.slice(2), + projectDirectory: options?.projectDirectory ?? process.env.ASPIRE_PROJECT_DIRECTORY ?? process.cwd(), + appHostFilePath: options?.appHostFilePath ?? process.env.ASPIRE_APPHOST_FILEPATH + }; + + const handle = await client.invokeCapability( + 'Aspire.Hosting/createBuilderWithOptions', + { options: effectiveOptions } + ); + return new DistributedApplicationBuilder(handle, client); +} + +// Re-export commonly used types +export { Handle, AppHostUsageError, CapabilityError, registerCallback } from './transport.js'; +export { refExpr, ReferenceExpression } from './base.js'; + +// ============================================================================ +// Global Error Handling +// ============================================================================ + +/** + * Set up global error handlers to ensure the process exits properly on errors. + * Node.js doesn't exit on unhandled rejections by default, so we need to handle them. + */ +process.on('unhandledRejection', (reason: unknown) => { + const error = reason instanceof Error ? reason : new Error(String(reason)); + + if (reason instanceof AppHostUsageError) { + console.error(`\n❌ AppHost Error: ${error.message}`); + } else if (reason instanceof CapabilityError) { + console.error(`\n❌ Capability Error: ${error.message}`); + console.error(` Code: ${(reason as CapabilityError).code}`); + if ((reason as CapabilityError).capability) { + console.error(` Capability: ${(reason as CapabilityError).capability}`); + } + } else { + console.error(`\n❌ Unhandled Error: ${error.message}`); + if (error.stack) { + console.error(error.stack); + } + } + + process.exit(1); +}); + +process.on('uncaughtException', (error: Error) => { + if (error instanceof AppHostUsageError) { + console.error(`\n❌ AppHost Error: ${error.message}`); + } else { + console.error(`\n❌ Uncaught Exception: ${error.message}`); + } + if (!(error instanceof AppHostUsageError) && error.stack) { + console.error(error.stack); + } + process.exit(1); +}); + +// ============================================================================ +// Handle Wrapper Registrations +// ============================================================================ + +// Register wrapper factories for typed handle wrapping in callbacks +registerHandleWrapper('Aspire.Hosting.Azure/Aspire.Hosting.Azure.AzureResourceInfrastructure', (handle, client) => new AzureResourceInfrastructure(handle as AzureResourceInfrastructureHandle, client)); +registerHandleWrapper('Aspire.Hosting.Azure/Aspire.Hosting.Azure.BicepOutputReference', (handle, client) => new BicepOutputReference(handle as BicepOutputReferenceHandle, client)); +registerHandleWrapper('Aspire.Hosting/Aspire.Hosting.ApplicationModel.CommandLineArgsCallbackContext', (handle, client) => new CommandLineArgsCallbackContext(handle as CommandLineArgsCallbackContextHandle, client)); +registerHandleWrapper('Aspire.Hosting/Aspire.Hosting.DistributedApplication', (handle, client) => new DistributedApplication(handle as DistributedApplicationHandle, client)); +registerHandleWrapper('Aspire.Hosting/Aspire.Hosting.DistributedApplicationExecutionContext', (handle, client) => new DistributedApplicationExecutionContext(handle as DistributedApplicationExecutionContextHandle, client)); +registerHandleWrapper('Aspire.Hosting/Aspire.Hosting.ApplicationModel.EndpointReference', (handle, client) => new EndpointReference(handle as EndpointReferenceHandle, client)); +registerHandleWrapper('Aspire.Hosting/Aspire.Hosting.ApplicationModel.EndpointReferenceExpression', (handle, client) => new EndpointReferenceExpression(handle as EndpointReferenceExpressionHandle, client)); +registerHandleWrapper('Aspire.Hosting/Aspire.Hosting.ApplicationModel.EnvironmentCallbackContext', (handle, client) => new EnvironmentCallbackContext(handle as EnvironmentCallbackContextHandle, client)); +registerHandleWrapper('Aspire.Hosting/Aspire.Hosting.ApplicationModel.ExecuteCommandContext', (handle, client) => new ExecuteCommandContext(handle as ExecuteCommandContextHandle, client)); +registerHandleWrapper('Aspire.Hosting/Aspire.Hosting.Pipelines.PipelineConfigurationContext', (handle, client) => new PipelineConfigurationContext(handle as PipelineConfigurationContextHandle, client)); +registerHandleWrapper('Aspire.Hosting/Aspire.Hosting.Pipelines.PipelineStep', (handle, client) => new PipelineStep(handle as PipelineStepHandle, client)); +registerHandleWrapper('Aspire.Hosting/Aspire.Hosting.Pipelines.PipelineStepContext', (handle, client) => new PipelineStepContext(handle as PipelineStepContextHandle, client)); +registerHandleWrapper('Aspire.Hosting/Aspire.Hosting.ProjectResourceOptions', (handle, client) => new ProjectResourceOptions(handle as ProjectResourceOptionsHandle, client)); +registerHandleWrapper('Aspire.Hosting/Aspire.Hosting.ApplicationModel.ReferenceExpressionBuilder', (handle, client) => new ReferenceExpressionBuilder(handle as ReferenceExpressionBuilderHandle, client)); +registerHandleWrapper('Aspire.Hosting/Aspire.Hosting.ApplicationModel.ResourceUrlsCallbackContext', (handle, client) => new ResourceUrlsCallbackContext(handle as ResourceUrlsCallbackContextHandle, client)); +registerHandleWrapper('Aspire.Hosting/Aspire.Hosting.IDistributedApplicationBuilder', (handle, client) => new DistributedApplicationBuilder(handle as IDistributedApplicationBuilderHandle, client)); +registerHandleWrapper('Aspire.Hosting/Aspire.Hosting.Eventing.IDistributedApplicationEventing', (handle, client) => new DistributedApplicationEventing(handle as IDistributedApplicationEventingHandle, client)); +registerHandleWrapper('Aspire.Hosting.Azure/Aspire.Hosting.Azure.AzureBicepResource', (handle, client) => new AzureBicepResource(handle as AzureBicepResourceHandle, client)); +registerHandleWrapper('Aspire.Hosting.Azure.Storage/Aspire.Hosting.Azure.AzureBlobStorageContainerResource', (handle, client) => new AzureBlobStorageContainerResource(handle as AzureBlobStorageContainerResourceHandle, client)); +registerHandleWrapper('Aspire.Hosting.Azure.Storage/Aspire.Hosting.Azure.AzureBlobStorageResource', (handle, client) => new AzureBlobStorageResource(handle as AzureBlobStorageResourceHandle, client)); +registerHandleWrapper('Aspire.Hosting.Azure.Storage/Aspire.Hosting.Azure.AzureDataLakeStorageFileSystemResource', (handle, client) => new AzureDataLakeStorageFileSystemResource(handle as AzureDataLakeStorageFileSystemResourceHandle, client)); +registerHandleWrapper('Aspire.Hosting.Azure.Storage/Aspire.Hosting.Azure.AzureDataLakeStorageResource', (handle, client) => new AzureDataLakeStorageResource(handle as AzureDataLakeStorageResourceHandle, client)); +registerHandleWrapper('Aspire.Hosting.Azure/Aspire.Hosting.Azure.AzureEnvironmentResource', (handle, client) => new AzureEnvironmentResource(handle as AzureEnvironmentResourceHandle, client)); +registerHandleWrapper('Aspire.Hosting.Azure.EventHubs/Aspire.Hosting.Azure.AzureEventHubConsumerGroupResource', (handle, client) => new AzureEventHubConsumerGroupResource(handle as AzureEventHubConsumerGroupResourceHandle, client)); +registerHandleWrapper('Aspire.Hosting.Azure.EventHubs/Aspire.Hosting.Azure.AzureEventHubResource', (handle, client) => new AzureEventHubResource(handle as AzureEventHubResourceHandle, client)); +registerHandleWrapper('Aspire.Hosting.Azure.EventHubs/Aspire.Hosting.Azure.AzureEventHubsEmulatorResource', (handle, client) => new AzureEventHubsEmulatorResource(handle as AzureEventHubsEmulatorResourceHandle, client)); +registerHandleWrapper('Aspire.Hosting.Azure.EventHubs/Aspire.Hosting.Azure.AzureEventHubsResource', (handle, client) => new AzureEventHubsResource(handle as AzureEventHubsResourceHandle, client)); +registerHandleWrapper('Aspire.Hosting.Azure/Aspire.Hosting.Azure.AzureProvisioningResource', (handle, client) => new AzureProvisioningResource(handle as AzureProvisioningResourceHandle, client)); +registerHandleWrapper('Aspire.Hosting.Azure.Storage/Aspire.Hosting.Azure.AzureQueueStorageQueueResource', (handle, client) => new AzureQueueStorageQueueResource(handle as AzureQueueStorageQueueResourceHandle, client)); +registerHandleWrapper('Aspire.Hosting.Azure.Storage/Aspire.Hosting.Azure.AzureQueueStorageResource', (handle, client) => new AzureQueueStorageResource(handle as AzureQueueStorageResourceHandle, client)); +registerHandleWrapper('Aspire.Hosting.Azure.Storage/Aspire.Hosting.Azure.AzureStorageEmulatorResource', (handle, client) => new AzureStorageEmulatorResource(handle as AzureStorageEmulatorResourceHandle, client)); +registerHandleWrapper('Aspire.Hosting.Azure.Storage/Aspire.Hosting.Azure.AzureStorageResource', (handle, client) => new AzureStorageResource(handle as AzureStorageResourceHandle, client)); +registerHandleWrapper('Aspire.Hosting.Azure.Storage/Aspire.Hosting.Azure.AzureTableStorageResource', (handle, client) => new AzureTableStorageResource(handle as AzureTableStorageResourceHandle, client)); +registerHandleWrapper('Aspire.Hosting.Azure/Aspire.Hosting.Azure.AzureUserAssignedIdentityResource', (handle, client) => new AzureUserAssignedIdentityResource(handle as AzureUserAssignedIdentityResourceHandle, client)); +registerHandleWrapper('Aspire.Hosting/Aspire.Hosting.ConnectionStringResource', (handle, client) => new ConnectionStringResource(handle as ConnectionStringResourceHandle, client)); +registerHandleWrapper('Aspire.Hosting/Aspire.Hosting.ApplicationModel.ContainerRegistryResource', (handle, client) => new ContainerRegistryResource(handle as ContainerRegistryResourceHandle, client)); +registerHandleWrapper('Aspire.Hosting/Aspire.Hosting.ApplicationModel.ContainerResource', (handle, client) => new ContainerResource(handle as ContainerResourceHandle, client)); +registerHandleWrapper('Aspire.Hosting/Aspire.Hosting.ApplicationModel.CSharpAppResource', (handle, client) => new CSharpAppResource(handle as CSharpAppResourceHandle, client)); +registerHandleWrapper('Aspire.Hosting/Aspire.Hosting.ApplicationModel.DotnetToolResource', (handle, client) => new DotnetToolResource(handle as DotnetToolResourceHandle, client)); +registerHandleWrapper('Aspire.Hosting/Aspire.Hosting.ApplicationModel.ExecutableResource', (handle, client) => new ExecutableResource(handle as ExecutableResourceHandle, client)); +registerHandleWrapper('Aspire.Hosting/Aspire.Hosting.ExternalServiceResource', (handle, client) => new ExternalServiceResource(handle as ExternalServiceResourceHandle, client)); +registerHandleWrapper('Aspire.Hosting.JavaScript/Aspire.Hosting.JavaScript.JavaScriptAppResource', (handle, client) => new JavaScriptAppResource(handle as JavaScriptAppResourceHandle, client)); +registerHandleWrapper('Aspire.Hosting.JavaScript/Aspire.Hosting.JavaScript.NodeAppResource', (handle, client) => new NodeAppResource(handle as NodeAppResourceHandle, client)); +registerHandleWrapper('Aspire.Hosting/Aspire.Hosting.ApplicationModel.ParameterResource', (handle, client) => new ParameterResource(handle as ParameterResourceHandle, client)); +registerHandleWrapper('Aspire.Hosting/Aspire.Hosting.ApplicationModel.ProjectResource', (handle, client) => new ProjectResource(handle as ProjectResourceHandle, client)); +registerHandleWrapper('Aspire.Hosting.JavaScript/Aspire.Hosting.JavaScript.ViteAppResource', (handle, client) => new ViteAppResource(handle as ViteAppResourceHandle, client)); +registerHandleWrapper('Aspire.Hosting.Azure/Aspire.Hosting.ApplicationModel.IAzureResource', (handle, client) => new AzureResource(handle as IAzureResourceHandle, client)); +registerHandleWrapper('Aspire.Hosting/Aspire.Hosting.ApplicationModel.IComputeResource', (handle, client) => new ComputeResource(handle as IComputeResourceHandle, client)); +registerHandleWrapper('Aspire.Hosting/Aspire.Hosting.ApplicationModel.IContainerFilesDestinationResource', (handle, client) => new ContainerFilesDestinationResource(handle as IContainerFilesDestinationResourceHandle, client)); +registerHandleWrapper('Aspire.Hosting/Aspire.Hosting.ApplicationModel.IResource', (handle, client) => new Resource(handle as IResourceHandle, client)); +registerHandleWrapper('Aspire.Hosting/Aspire.Hosting.ApplicationModel.IResourceWithArgs', (handle, client) => new ResourceWithArgs(handle as IResourceWithArgsHandle, client)); +registerHandleWrapper('Aspire.Hosting/Aspire.Hosting.ApplicationModel.IResourceWithConnectionString', (handle, client) => new ResourceWithConnectionString(handle as IResourceWithConnectionStringHandle, client)); +registerHandleWrapper('Aspire.Hosting/Aspire.Hosting.IResourceWithContainerFiles', (handle, client) => new ResourceWithContainerFiles(handle as IResourceWithContainerFilesHandle, client)); +registerHandleWrapper('Aspire.Hosting/Aspire.Hosting.ApplicationModel.IResourceWithEndpoints', (handle, client) => new ResourceWithEndpoints(handle as IResourceWithEndpointsHandle, client)); +registerHandleWrapper('Aspire.Hosting/Aspire.Hosting.ApplicationModel.IResourceWithEnvironment', (handle, client) => new ResourceWithEnvironment(handle as IResourceWithEnvironmentHandle, client)); +registerHandleWrapper('Aspire.Hosting/Aspire.Hosting.IResourceWithServiceDiscovery', (handle, client) => new ResourceWithServiceDiscovery(handle as IResourceWithServiceDiscoveryHandle, client)); +registerHandleWrapper('Aspire.Hosting/Aspire.Hosting.ApplicationModel.IResourceWithWaitSupport', (handle, client) => new ResourceWithWaitSupport(handle as IResourceWithWaitSupportHandle, client)); + diff --git a/playground/TypeScriptApps/AzureFunctionsSample/AppHost/.modules/base.ts b/playground/TypeScriptApps/AzureFunctionsSample/AppHost/.modules/base.ts new file mode 100644 index 00000000000..9a3427e7e72 --- /dev/null +++ b/playground/TypeScriptApps/AzureFunctionsSample/AppHost/.modules/base.ts @@ -0,0 +1,530 @@ +// aspire.ts - Core Aspire types: base classes, ReferenceExpression +import { Handle, AspireClient, MarshalledHandle } from './transport.js'; + +// Re-export transport types for convenience +export { Handle, AspireClient, CapabilityError, registerCallback, unregisterCallback, registerCancellation, unregisterCancellation } from './transport.js'; +export type { MarshalledHandle, AtsError, AtsErrorDetails, CallbackFunction } from './transport.js'; +export { AtsErrorCodes, isMarshalledHandle, isAtsError, wrapIfHandle } from './transport.js'; + +// ============================================================================ +// Reference Expression +// ============================================================================ + +/** + * Represents a reference expression that can be passed to capabilities. + * + * Reference expressions are serialized in the protocol as: + * ```json + * { + * "$expr": { + * "format": "redis://{0}:{1}", + * "valueProviders": [ + * { "$handle": "Aspire.Hosting.ApplicationModel/EndpointReference:1" }, + * { "$handle": "Aspire.Hosting.ApplicationModel/EndpointReference:2" } + * ] + * } + * } + * ``` + * + * @example + * ```typescript + * const redis = await builder.addRedis("cache"); + * const endpoint = await redis.getEndpoint("tcp"); + * + * // Create a reference expression + * const expr = refExpr`redis://${endpoint}:6379`; + * + * // Use it in an environment variable + * await api.withEnvironment("REDIS_URL", expr); + * ``` + */ +export class ReferenceExpression { + // Expression mode fields + private readonly _format?: string; + private readonly _valueProviders?: unknown[]; + + // Conditional mode fields + private readonly _condition?: unknown; + private readonly _whenTrue?: ReferenceExpression; + private readonly _whenFalse?: ReferenceExpression; + private readonly _matchValue?: string; + + // Handle mode fields (when wrapping a server-returned handle) + private readonly _handle?: Handle; + private readonly _client?: AspireClient; + + constructor(format: string, valueProviders: unknown[]); + constructor(handle: Handle, client: AspireClient); + constructor(condition: unknown, matchValue: string, whenTrue: ReferenceExpression, whenFalse: ReferenceExpression); + constructor( + handleOrFormatOrCondition: Handle | string | unknown, + clientOrValueProvidersOrMatchValue: AspireClient | unknown[] | string, + whenTrueOrWhenFalse?: ReferenceExpression, + whenFalse?: ReferenceExpression + ) { + if (typeof handleOrFormatOrCondition === 'string') { + this._format = handleOrFormatOrCondition; + this._valueProviders = clientOrValueProvidersOrMatchValue as unknown[]; + } else if (handleOrFormatOrCondition instanceof Handle) { + this._handle = handleOrFormatOrCondition; + this._client = clientOrValueProvidersOrMatchValue as AspireClient; + } else { + this._condition = handleOrFormatOrCondition; + this._matchValue = (clientOrValueProvidersOrMatchValue as string) ?? 'True'; + this._whenTrue = whenTrueOrWhenFalse; + this._whenFalse = whenFalse; + } + } + + /** + * Gets whether this reference expression is conditional. + */ + get isConditional(): boolean { + return this._condition !== undefined; + } + + /** + * Creates a reference expression from a tagged template literal. + * + * @param strings - The template literal string parts + * @param values - The interpolated values (handles to value providers) + * @returns A ReferenceExpression instance + */ + static create(strings: TemplateStringsArray, ...values: unknown[]): ReferenceExpression { + // Build the format string with {0}, {1}, etc. placeholders + let format = ''; + for (let i = 0; i < strings.length; i++) { + format += strings[i]; + if (i < values.length) { + format += `{${i}}`; + } + } + + // Extract handles from values + const valueProviders = values.map(extractHandleForExpr); + + return new ReferenceExpression(format, valueProviders); + } + + /** + * Creates a conditional reference expression from its constituent parts. + * + * @param condition - A value provider whose result is compared to matchValue + * @param whenTrue - The expression to use when the condition matches + * @param whenFalse - The expression to use when the condition does not match + * @param matchValue - The value to compare the condition against (defaults to "True") + * @returns A ReferenceExpression instance in conditional mode + */ + static createConditional( + condition: unknown, + matchValue: string, + whenTrue: ReferenceExpression, + whenFalse: ReferenceExpression + ): ReferenceExpression { + return new ReferenceExpression(condition, matchValue, whenTrue, whenFalse); + } + + /** + * Serializes the reference expression for JSON-RPC transport. + * In expression mode, uses the $expr format with format + valueProviders. + * In conditional mode, uses the $expr format with condition + whenTrue + whenFalse. + * In handle mode, delegates to the handle's serialization. + */ + toJSON(): { $expr: { format: string; valueProviders?: unknown[] } | { condition: unknown; whenTrue: unknown; whenFalse: unknown; matchValue: string } } | MarshalledHandle { + if (this._handle) { + return this._handle.toJSON(); + } + + if (this.isConditional) { + return { + $expr: { + condition: this._condition instanceof Handle ? this._condition.toJSON() : this._condition, + whenTrue: this._whenTrue!.toJSON(), + whenFalse: this._whenFalse!.toJSON(), + matchValue: this._matchValue! + } + }; + } + + return { + $expr: { + format: this._format!, + valueProviders: this._valueProviders && this._valueProviders.length > 0 ? this._valueProviders : undefined + } + }; + } + + /** + * String representation for debugging. + */ + toString(): string { + if (this._handle) { + return `ReferenceExpression(handle)`; + } + if (this.isConditional) { + return `ReferenceExpression(conditional)`; + } + return `ReferenceExpression(${this._format})`; + } +} + +/** + * Extracts a value for use in reference expressions. + * Supports handles (objects) and string literals. + * @internal + */ +function extractHandleForExpr(value: unknown): unknown { + if (value === null || value === undefined) { + throw new Error('Cannot use null or undefined in reference expression'); + } + + // String literals - include directly in the expression + if (typeof value === 'string') { + return value; + } + + // Number literals - convert to string + if (typeof value === 'number') { + return String(value); + } + + // Handle objects - get their JSON representation + if (value instanceof Handle) { + return value.toJSON(); + } + + // Objects with $handle property (already in handle format) + if (typeof value === 'object' && value !== null && '$handle' in value) { + return value; + } + + // Objects with toJSON that returns a handle + if (typeof value === 'object' && value !== null && 'toJSON' in value && typeof value.toJSON === 'function') { + const json = value.toJSON(); + if (json && typeof json === 'object' && '$handle' in json) { + return json; + } + } + + throw new Error( + `Cannot use value of type ${typeof value} in reference expression. ` + + `Expected a Handle, string, or number.` + ); +} + +/** + * Tagged template function for creating reference expressions. + * + * Use this to create dynamic expressions that reference endpoints, parameters, and other + * value providers. The expression is evaluated at runtime by Aspire. + * + * @example + * ```typescript + * const redis = await builder.addRedis("cache"); + * const endpoint = await redis.getEndpoint("tcp"); + * + * // Create a reference expression using the tagged template + * const expr = refExpr`redis://${endpoint}:6379`; + * + * // Use it in an environment variable + * await api.withEnvironment("REDIS_URL", expr); + * ``` + */ +export function refExpr(strings: TemplateStringsArray, ...values: unknown[]): ReferenceExpression { + return ReferenceExpression.create(strings, ...values); +} + +// ============================================================================ +// ResourceBuilderBase +// ============================================================================ + +/** + * Base class for resource builders (e.g., RedisBuilder, ContainerBuilder). + * Provides handle management and JSON serialization. + */ +export class ResourceBuilderBase { + constructor(protected _handle: THandle, protected _client: AspireClient) {} + + toJSON(): MarshalledHandle { return this._handle.toJSON(); } +} + +// ============================================================================ +// AspireList - Mutable List Wrapper +// ============================================================================ + +/** + * Wrapper for a mutable .NET List. + * Provides array-like methods that invoke capabilities on the underlying collection. + * + * @example + * ```typescript + * const items = await resource.getItems(); // Returns AspireList + * const count = await items.count(); + * const first = await items.get(0); + * await items.add(newItem); + * ``` + */ +export class AspireList { + private _resolvedHandle?: Handle; + private _resolvePromise?: Promise; + + constructor( + private readonly _handleOrContext: Handle, + private readonly _client: AspireClient, + private readonly _typeId: string, + private readonly _getterCapabilityId?: string + ) { + // If no getter capability, the handle is already the list handle + if (!_getterCapabilityId) { + this._resolvedHandle = _handleOrContext; + } + } + + /** + * Ensures we have the actual list handle by calling the getter if needed. + */ + private async _ensureHandle(): Promise { + if (this._resolvedHandle) { + return this._resolvedHandle; + } + if (this._resolvePromise) { + return this._resolvePromise; + } + // Call the getter capability to get the actual list handle + this._resolvePromise = (async () => { + const result = await this._client.invokeCapability(this._getterCapabilityId!, { + context: this._handleOrContext + }); + this._resolvedHandle = result as Handle; + return this._resolvedHandle; + })(); + return this._resolvePromise; + } + + /** + * Gets the number of elements in the list. + */ + async count(): Promise { + const handle = await this._ensureHandle(); + return await this._client.invokeCapability('Aspire.Hosting/List.length', { + list: handle + }) as number; + } + + /** + * Gets the element at the specified index. + */ + async get(index: number): Promise { + const handle = await this._ensureHandle(); + return await this._client.invokeCapability('Aspire.Hosting/List.get', { + list: handle, + index + }) as T; + } + + /** + * Adds an element to the end of the list. + */ + async add(item: T): Promise { + const handle = await this._ensureHandle(); + await this._client.invokeCapability('Aspire.Hosting/List.add', { + list: handle, + item + }); + } + + /** + * Removes the element at the specified index. + */ + async removeAt(index: number): Promise { + const handle = await this._ensureHandle(); + await this._client.invokeCapability('Aspire.Hosting/List.removeAt', { + list: handle, + index + }); + } + + /** + * Clears all elements from the list. + */ + async clear(): Promise { + const handle = await this._ensureHandle(); + await this._client.invokeCapability('Aspire.Hosting/List.clear', { + list: handle + }); + } + + /** + * Converts the list to an array (creates a copy). + */ + async toArray(): Promise { + const handle = await this._ensureHandle(); + return await this._client.invokeCapability('Aspire.Hosting/List.toArray', { + list: handle + }) as T[]; + } + + toJSON(): MarshalledHandle { + if (this._resolvedHandle) { + return this._resolvedHandle.toJSON(); + } + return this._handleOrContext.toJSON(); + } +} + +// ============================================================================ +// AspireDict - Mutable Dictionary Wrapper +// ============================================================================ + +/** + * Wrapper for a mutable .NET Dictionary. + * Provides object-like methods that invoke capabilities on the underlying collection. + * + * @example + * ```typescript + * const config = await resource.getConfig(); // Returns AspireDict + * const value = await config.get("key"); + * await config.set("key", "value"); + * const hasKey = await config.containsKey("key"); + * ``` + */ +export class AspireDict { + private _resolvedHandle?: Handle; + private _resolvePromise?: Promise; + + constructor( + private readonly _handleOrContext: Handle, + private readonly _client: AspireClient, + private readonly _typeId: string, + private readonly _getterCapabilityId?: string + ) { + // If no getter capability, the handle is already the dictionary handle + if (!_getterCapabilityId) { + this._resolvedHandle = _handleOrContext; + } + } + + /** + * Ensures we have the actual dictionary handle by calling the getter if needed. + */ + private async _ensureHandle(): Promise { + if (this._resolvedHandle) { + return this._resolvedHandle; + } + if (this._resolvePromise) { + return this._resolvePromise; + } + // Call the getter capability to get the actual dictionary handle + this._resolvePromise = (async () => { + const result = await this._client.invokeCapability(this._getterCapabilityId!, { + context: this._handleOrContext + }); + this._resolvedHandle = result as Handle; + return this._resolvedHandle; + })(); + return this._resolvePromise; + } + + /** + * Gets the number of key-value pairs in the dictionary. + */ + async count(): Promise { + const handle = await this._ensureHandle(); + return await this._client.invokeCapability('Aspire.Hosting/Dict.count', { + dict: handle + }) as number; + } + + /** + * Gets the value associated with the specified key. + * @throws If the key is not found. + */ + async get(key: K): Promise { + const handle = await this._ensureHandle(); + return await this._client.invokeCapability('Aspire.Hosting/Dict.get', { + dict: handle, + key + }) as V; + } + + /** + * Sets the value for the specified key. + */ + async set(key: K, value: V): Promise { + const handle = await this._ensureHandle(); + await this._client.invokeCapability('Aspire.Hosting/Dict.set', { + dict: handle, + key, + value + }); + } + + /** + * Determines whether the dictionary contains the specified key. + */ + async containsKey(key: K): Promise { + const handle = await this._ensureHandle(); + return await this._client.invokeCapability('Aspire.Hosting/Dict.has', { + dict: handle, + key + }) as boolean; + } + + /** + * Removes the value with the specified key. + * @returns True if the element was removed; false if the key was not found. + */ + async remove(key: K): Promise { + const handle = await this._ensureHandle(); + return await this._client.invokeCapability('Aspire.Hosting/Dict.remove', { + dict: handle, + key + }) as boolean; + } + + /** + * Clears all key-value pairs from the dictionary. + */ + async clear(): Promise { + const handle = await this._ensureHandle(); + await this._client.invokeCapability('Aspire.Hosting/Dict.clear', { + dict: handle + }); + } + + /** + * Gets all keys in the dictionary. + */ + async keys(): Promise { + const handle = await this._ensureHandle(); + return await this._client.invokeCapability('Aspire.Hosting/Dict.keys', { + dict: handle + }) as K[]; + } + + /** + * Gets all values in the dictionary. + */ + async values(): Promise { + const handle = await this._ensureHandle(); + return await this._client.invokeCapability('Aspire.Hosting/Dict.values', { + dict: handle + }) as V[]; + } + + /** + * Converts the dictionary to a plain object (creates a copy). + * Only works when K is string. + */ + async toObject(): Promise> { + const handle = await this._ensureHandle(); + return await this._client.invokeCapability('Aspire.Hosting/Dict.toObject', { + dict: handle + }) as Record; + } + + async toJSON(): Promise { + const handle = await this._ensureHandle(); + return handle.toJSON(); + } +} diff --git a/playground/TypeScriptApps/AzureFunctionsSample/AppHost/.modules/transport.ts b/playground/TypeScriptApps/AzureFunctionsSample/AppHost/.modules/transport.ts new file mode 100644 index 00000000000..7ee1ba87e3f --- /dev/null +++ b/playground/TypeScriptApps/AzureFunctionsSample/AppHost/.modules/transport.ts @@ -0,0 +1,645 @@ +// transport.ts - ATS transport layer: RPC, Handle, errors, callbacks +import * as net from 'net'; +import * as rpc from 'vscode-jsonrpc/node.js'; + +// ============================================================================ +// Base Types +// ============================================================================ + +/** + * Type for callback functions that can be registered and invoked from .NET. + * Internal: receives args and client for handle wrapping. + */ +export type CallbackFunction = (args: unknown, client: AspireClient) => unknown | Promise; + +/** + * Represents a handle to a .NET object in the ATS system. + * Handles are typed references that can be passed between capabilities. + */ +export interface MarshalledHandle { + /** The handle ID (instance number) */ + $handle: string; + /** The ATS type ID */ + $type: string; +} + +/** + * Error details for ATS errors. + */ +export interface AtsErrorDetails { + /** The parameter that caused the error */ + parameter?: string; + /** The expected type or value */ + expected?: string; + /** The actual type or value */ + actual?: string; +} + +/** + * Structured error from ATS capability invocation. + */ +export interface AtsError { + /** Machine-readable error code */ + code: string; + /** Human-readable error message */ + message: string; + /** The capability that failed (if applicable) */ + capability?: string; + /** Additional error details */ + details?: AtsErrorDetails; +} + +/** + * ATS error codes returned by the server. + */ +export const AtsErrorCodes = { + /** Unknown capability ID */ + CapabilityNotFound: 'CAPABILITY_NOT_FOUND', + /** Handle ID doesn't exist or was disposed */ + HandleNotFound: 'HANDLE_NOT_FOUND', + /** Handle type doesn't satisfy capability's type constraint */ + TypeMismatch: 'TYPE_MISMATCH', + /** Missing required argument or wrong type */ + InvalidArgument: 'INVALID_ARGUMENT', + /** Argument value outside valid range */ + ArgumentOutOfRange: 'ARGUMENT_OUT_OF_RANGE', + /** Error occurred during callback invocation */ + CallbackError: 'CALLBACK_ERROR', + /** Unexpected error in capability execution */ + InternalError: 'INTERNAL_ERROR', +} as const; + +/** + * Type guard to check if a value is an ATS error response. + */ +export function isAtsError(value: unknown): value is { $error: AtsError } { + return ( + value !== null && + typeof value === 'object' && + '$error' in value && + typeof (value as { $error: unknown }).$error === 'object' + ); +} + +/** + * Type guard to check if a value is a marshalled handle. + */ +export function isMarshalledHandle(value: unknown): value is MarshalledHandle { + return ( + value !== null && + typeof value === 'object' && + '$handle' in value && + '$type' in value + ); +} + +// ============================================================================ +// Handle +// ============================================================================ + +/** + * A typed handle to a .NET object in the ATS system. + * Handles are opaque references that can be passed to capabilities. + * + * @typeParam T - The ATS type ID (e.g., "Aspire.Hosting/IDistributedApplicationBuilder") + */ +export class Handle { + private readonly _handleId: string; + private readonly _typeId: T; + + constructor(marshalled: MarshalledHandle) { + this._handleId = marshalled.$handle; + this._typeId = marshalled.$type as T; + } + + /** The handle ID (instance number) */ + get $handle(): string { + return this._handleId; + } + + /** The ATS type ID */ + get $type(): T { + return this._typeId; + } + + /** Serialize for JSON-RPC transport */ + toJSON(): MarshalledHandle { + return { + $handle: this._handleId, + $type: this._typeId + }; + } + + /** String representation for debugging */ + toString(): string { + return `Handle<${this._typeId}>(${this._handleId})`; + } +} + +// ============================================================================ +// Handle Wrapper Registry +// ============================================================================ + +/** + * Factory function for creating typed wrapper instances from handles. + */ +export type HandleWrapperFactory = (handle: Handle, client: AspireClient) => unknown; + +/** + * Registry of handle wrapper factories by type ID. + * Generated code registers wrapper classes here so callback handles can be properly typed. + */ +const handleWrapperRegistry = new Map(); + +/** + * Register a wrapper factory for a type ID. + * Called by generated code to register wrapper classes. + */ +export function registerHandleWrapper(typeId: string, factory: HandleWrapperFactory): void { + handleWrapperRegistry.set(typeId, factory); +} + +/** + * Checks if a value is a marshalled handle and wraps it appropriately. + * Uses the wrapper registry to create typed wrapper instances when available. + * + * @param value - The value to potentially wrap + * @param client - Optional client for creating typed wrapper instances + */ +export function wrapIfHandle(value: unknown, client?: AspireClient): unknown { + if (value && typeof value === 'object') { + if (isMarshalledHandle(value)) { + const handle = new Handle(value); + const typeId = value.$type; + + // Try to find a registered wrapper factory for this type + if (typeId && client) { + const factory = handleWrapperRegistry.get(typeId); + if (factory) { + return factory(handle, client); + } + } + + return handle; + } + } + return value; +} + +// ============================================================================ +// Capability Error +// ============================================================================ + +/** + * Error thrown when an ATS capability invocation fails. + */ +export class CapabilityError extends Error { + constructor( + /** The structured error from the server */ + public readonly error: AtsError + ) { + super(error.message); + this.name = 'CapabilityError'; + } + + /** Machine-readable error code */ + get code(): string { + return this.error.code; + } + + /** The capability that failed (if applicable) */ + get capability(): string | undefined { + return this.error.capability; + } +} + +/** + * Error thrown when the AppHost script uses the generated SDK incorrectly. + */ +export class AppHostUsageError extends Error { + constructor(message: string) { + super(message); + this.name = 'AppHostUsageError'; + } +} + +function isPromiseLike(value: unknown): value is PromiseLike { + return ( + value !== null && + (typeof value === 'object' || typeof value === 'function') && + 'then' in value && + typeof (value as { then?: unknown }).then === 'function' + ); +} + +function validateCapabilityArgs( + capabilityId: string, + args?: Record +): void { + if (!args) { + return; + } + + const seen = new Set(); + + const validateValue = (value: unknown, path: string): void => { + if (value === null || value === undefined) { + return; + } + + if (isPromiseLike(value)) { + throw new AppHostUsageError( + `Argument '${path}' passed to capability '${capabilityId}' is a Promise-like value. ` + + `This usually means an async builder call was not awaited. ` + + `Did you forget 'await' on a call like builder.addPostgres(...) or resource.addDatabase(...)?` + ); + } + + if (typeof value !== 'object') { + return; + } + + if (seen.has(value)) { + return; + } + + seen.add(value); + + if (Array.isArray(value)) { + for (let i = 0; i < value.length; i++) { + validateValue(value[i], `${path}[${i}]`); + } + return; + } + + for (const [key, nestedValue] of Object.entries(value)) { + validateValue(nestedValue, `${path}.${key}`); + } + }; + + for (const [key, value] of Object.entries(args)) { + validateValue(value, key); + } +} + +// ============================================================================ +// Callback Registry +// ============================================================================ + +const callbackRegistry = new Map(); +let callbackIdCounter = 0; + +/** + * Register a callback function that can be invoked from the .NET side. + * Returns a callback ID that should be passed to methods accepting callbacks. + * + * .NET passes arguments as an object with positional keys: `{ p0: value0, p1: value1, ... }` + * This function automatically extracts positional parameters and wraps handles. + * + * @example + * // Single parameter callback + * const id = registerCallback((ctx) => console.log(ctx)); + * // .NET sends: { p0: { $handle: "...", $type: "..." } } + * // Callback receives: Handle instance + * + * @example + * // Multi-parameter callback + * const id = registerCallback((a, b) => console.log(a, b)); + * // .NET sends: { p0: "hello", p1: 42 } + * // Callback receives: "hello", 42 + */ +export function registerCallback( + callback: (...args: any[]) => TResult | Promise +): string { + const callbackId = `callback_${++callbackIdCounter}_${Date.now()}`; + + // Wrap the callback to handle .NET's positional argument format + const wrapper: CallbackFunction = async (args: unknown, client: AspireClient) => { + // .NET sends args as object { p0: value0, p1: value1, ... } + if (args && typeof args === 'object' && !Array.isArray(args)) { + const argObj = args as Record; + const argArray: unknown[] = []; + + // Extract positional parameters (p0, p1, p2, ...) + for (let i = 0; ; i++) { + const key = `p${i}`; + if (key in argObj) { + argArray.push(wrapIfHandle(argObj[key], client)); + } else { + break; + } + } + + if (argArray.length > 0) { + // Spread positional arguments to callback + const result = await callback(...argArray); + // DTO writeback protocol: when a void callback returns undefined, we + // return the original args object so the .NET host can detect property + // mutations made by the callback and apply them back to the original + // C# DTO objects. DTO args are plain JS objects (not Handle wrappers), + // so any property changes the callback made are reflected in args. + // + // Non-void callbacks (result !== undefined) return their actual result. + // The .NET side only activates writeback for void delegates whose + // parameters include [AspireDto] types — all other cases discard the + // returned args object, so the extra wire payload is harmless. + // + // IMPORTANT: callbacks that intentionally return undefined will also + // trigger this path. For non-void delegate types, the C# proxy uses + // a result-unmarshalling path (not writeback), so returning args will + // cause an unmarshal error. Void callbacks should never return a + // meaningful value; non-void callbacks should always return one. + return result !== undefined ? result : args; + } + + // No positional params found — nothing to write back + return await callback(); + } + + // Null/undefined - call with no args + if (args === null || args === undefined) { + return await callback(); + } + + // Primitive value - pass as single arg (shouldn't happen with current protocol) + return await callback(wrapIfHandle(args, client)); + }; + + callbackRegistry.set(callbackId, wrapper); + return callbackId; +} + +/** + * Unregister a callback by its ID. + */ +export function unregisterCallback(callbackId: string): boolean { + return callbackRegistry.delete(callbackId); +} + +/** + * Get the number of registered callbacks. + */ +export function getCallbackCount(): number { + return callbackRegistry.size; +} + +// ============================================================================ +// Cancellation Token Registry +// ============================================================================ + +/** + * Registry for cancellation tokens. + * Maps cancellation IDs to cleanup functions. + */ +const cancellationRegistry = new Map void>(); +let cancellationIdCounter = 0; + +/** + * A reference to the current AspireClient for sending cancel requests. + * Set by AspireClient.connect(). + */ +let currentClient: AspireClient | null = null; + +/** + * Register an AbortSignal for cancellation support. + * Returns a cancellation ID that should be passed to methods accepting CancellationToken. + * + * When the AbortSignal is aborted, sends a cancelToken request to the host. + * + * @param signal - The AbortSignal to register (optional) + * @returns The cancellation ID, or undefined if no signal provided + * + * @example + * const controller = new AbortController(); + * const id = registerCancellation(controller.signal); + * // Pass id to capability invocation + * // Later: controller.abort() will cancel the operation + */ +export function registerCancellation(signal?: AbortSignal): string | undefined { + if (!signal) { + return undefined; + } + + // Already aborted? Don't register + if (signal.aborted) { + return undefined; + } + + const cancellationId = `ct_${++cancellationIdCounter}_${Date.now()}`; + + // Set up the abort listener + const onAbort = () => { + // Send cancel request to host + if (currentClient?.connected) { + currentClient.cancelToken(cancellationId).catch(() => { + // Ignore errors - the operation may have already completed + }); + } + // Clean up the listener + cancellationRegistry.delete(cancellationId); + }; + + // Listen for abort + signal.addEventListener('abort', onAbort, { once: true }); + + // Store cleanup function + cancellationRegistry.set(cancellationId, () => { + signal.removeEventListener('abort', onAbort); + }); + + return cancellationId; +} + +/** + * Unregister a cancellation token by its ID. + * Call this when the operation completes to clean up resources. + * + * @param cancellationId - The cancellation ID to unregister + */ +export function unregisterCancellation(cancellationId: string | undefined): void { + if (!cancellationId) { + return; + } + + const cleanup = cancellationRegistry.get(cancellationId); + if (cleanup) { + cleanup(); + cancellationRegistry.delete(cancellationId); + } +} + +// ============================================================================ +// AspireClient (JSON-RPC Connection) +// ============================================================================ + +/** + * Client for connecting to the Aspire AppHost via socket/named pipe. + */ +export class AspireClient { + private connection: rpc.MessageConnection | null = null; + private socket: net.Socket | null = null; + private disconnectCallbacks: (() => void)[] = []; + private _pendingCalls = 0; + + constructor(private socketPath: string) { } + + /** + * Register a callback to be called when the connection is lost + */ + onDisconnect(callback: () => void): void { + this.disconnectCallbacks.push(callback); + } + + private notifyDisconnect(): void { + for (const callback of this.disconnectCallbacks) { + try { + callback(); + } catch { + // Ignore callback errors + } + } + } + + connect(timeoutMs: number = 5000): Promise { + return new Promise((resolve, reject) => { + const timeout = setTimeout(() => reject(new Error('Connection timeout')), timeoutMs); + + // On Windows, use named pipes; on Unix, use Unix domain sockets + const isWindows = process.platform === 'win32'; + const pipePath = isWindows ? `\\\\.\\pipe\\${this.socketPath}` : this.socketPath; + + this.socket = net.createConnection(pipePath); + + this.socket.once('error', (error: Error) => { + clearTimeout(timeout); + reject(error); + }); + + this.socket.once('connect', () => { + clearTimeout(timeout); + try { + const reader = new rpc.SocketMessageReader(this.socket!); + const writer = new rpc.SocketMessageWriter(this.socket!); + this.connection = rpc.createMessageConnection(reader, writer); + + this.connection.onClose(() => { + this.connection = null; + this.notifyDisconnect(); + }); + this.connection.onError((err: any) => console.error('JsonRpc connection error:', err)); + + // Handle callback invocations from the .NET side + this.connection.onRequest('invokeCallback', async (callbackId: string, args: unknown) => { + const callback = callbackRegistry.get(callbackId); + if (!callback) { + throw new Error(`Callback not found: ${callbackId}`); + } + try { + // The registered wrapper handles arg unpacking and handle wrapping + // Pass this client so handles can be wrapped with typed wrapper classes + return await Promise.resolve(callback(args, this)); + } catch (error) { + const message = error instanceof Error ? error.message : String(error); + throw new Error(`Callback execution failed: ${message}`); + } + }); + + this.connection.listen(); + + // Set the current client for cancellation registry + currentClient = this; + + resolve(); + } catch (e) { + reject(e); + } + }); + + this.socket.on('close', () => { + this.connection?.dispose(); + this.connection = null; + if (currentClient === this) { + currentClient = null; + } + this.notifyDisconnect(); + }); + }); + } + + ping(): Promise { + if (!this.connection) return Promise.reject(new Error('Not connected to AppHost')); + return this.connection.sendRequest('ping'); + } + + /** + * Cancel a CancellationToken by its ID. + * Called when an AbortSignal is aborted. + * + * @param tokenId - The token ID to cancel + * @returns True if the token was found and cancelled, false otherwise + */ + cancelToken(tokenId: string): Promise { + if (!this.connection) return Promise.reject(new Error('Not connected to AppHost')); + return this.connection.sendRequest('cancelToken', tokenId); + } + + /** + * Invoke an ATS capability by ID. + * + * Capabilities are operations exposed by [AspireExport] attributes. + * Results are automatically wrapped in Handle objects when applicable. + * + * @param capabilityId - The capability ID (e.g., "Aspire.Hosting/createBuilder") + * @param args - Arguments to pass to the capability + * @returns The capability result, wrapped as Handle if it's a handle type + * @throws CapabilityError if the capability fails + */ + async invokeCapability( + capabilityId: string, + args?: Record + ): Promise { + if (!this.connection) { + throw new Error('Not connected to AppHost'); + } + + validateCapabilityArgs(capabilityId, args); + + // Ref counting: The vscode-jsonrpc socket keeps Node's event loop alive. + // We ref() during RPC calls so the process doesn't exit mid-call, and + // unref() when idle so the process can exit naturally after all work completes. + if (this._pendingCalls === 0) { + this.socket?.ref(); + } + this._pendingCalls++; + + try { + const result = await this.connection.sendRequest( + 'invokeCapability', + capabilityId, + args ?? null + ); + + // Check for structured error response + if (isAtsError(result)) { + throw new CapabilityError(result.$error); + } + + // Wrap handles automatically + return wrapIfHandle(result, this) as T; + } finally { + this._pendingCalls--; + if (this._pendingCalls === 0) { + this.socket?.unref(); + } + } + } + + disconnect(): void { + try { this.connection?.dispose(); } finally { this.connection = null; } + try { this.socket?.end(); } finally { this.socket = null; } + } + + get connected(): boolean { + return this.connection !== null && this.socket !== null; + } +} diff --git a/playground/TypeScriptApps/AzureFunctionsSample/AppHost/apphost.run.json b/playground/TypeScriptApps/AzureFunctionsSample/AppHost/apphost.run.json new file mode 100644 index 00000000000..77427d26d0b --- /dev/null +++ b/playground/TypeScriptApps/AzureFunctionsSample/AppHost/apphost.run.json @@ -0,0 +1,11 @@ +{ + "profiles": { + "https": { + "applicationUrl": "https://localhost:10355;http://localhost:41182", + "environmentVariables": { + "ASPIRE_DASHBOARD_OTLP_ENDPOINT_URL": "https://localhost:23561", + "ASPIRE_RESOURCE_SERVICE_ENDPOINT_URL": "https://localhost:61715" + } + } + } +} \ No newline at end of file diff --git a/playground/TypeScriptApps/AzureFunctionsSample/AppHost/apphost.ts b/playground/TypeScriptApps/AzureFunctionsSample/AppHost/apphost.ts new file mode 100644 index 00000000000..fa36104af58 --- /dev/null +++ b/playground/TypeScriptApps/AzureFunctionsSample/AppHost/apphost.ts @@ -0,0 +1,39 @@ +// Aspire TypeScript AppHost - Azure Functions E2E (TypeScript) +// For more information, see: https://aspire.dev + +import { createBuilder } from './.modules/aspire.js'; + +const builder = await createBuilder(); + +// Azure Storage with emulator (queues + blobs) +const storage = builder.addAzureStorage("storage").runAsEmulator(); +const queue = await storage.addQueues("queue"); +const blob = await storage.addBlobs("blob"); +const myBlobContainer = await storage.addBlobContainer("myblobcontainer"); + +// Azure Event Hubs with emulator +const eventHub = await builder.addAzureEventHubs("eventhubs") + .runAsEmulator() + .addHub("myhub"); + +// TypeScript Azure Functions app (Node.js v4 programming model) +const funcApp = await builder + .addJavaScriptApp("funcapp", "../TypeScriptFunctions", { runScriptName: "start" }) + .withHttpEndpoint({ targetPort: 7071 }) + .withExternalHttpEndpoints() + .withReference(queue).waitFor(queue) + .withReference(blob).waitFor(blob) + .withReference(myBlobContainer).waitFor(myBlobContainer) + .withReference(eventHub).waitFor(eventHub); + +// TypeScript API service (Express) +await builder + .addJavaScriptApp("apiservice", "../TypeScriptApiService", { runScriptName: "dev" }) + .withHttpEndpoint({ env: "PORT" }) + .withExternalHttpEndpoints() + .withReference(queue) + .withReference(blob) + .withReference(eventHub).waitFor(eventHub) + .withServiceReference(funcApp).waitFor(funcApp); + +await builder.build().run(); diff --git a/playground/TypeScriptApps/AzureFunctionsSample/AppHost/package-lock.json b/playground/TypeScriptApps/AzureFunctionsSample/AppHost/package-lock.json new file mode 100644 index 00000000000..b4a44fdaddd --- /dev/null +++ b/playground/TypeScriptApps/AzureFunctionsSample/AppHost/package-lock.json @@ -0,0 +1,962 @@ +{ + "name": "azurefunctionsendtoendts", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "azurefunctionsendtoendts", + "version": "1.0.0", + "dependencies": { + "vscode-jsonrpc": "^8.2.0" + }, + "devDependencies": { + "@types/node": "^20.0.0", + "nodemon": "^3.1.11", + "tsx": "^4.19.0", + "typescript": "^5.3.0" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.3.tgz", + "integrity": "sha512-9fJMTNFTWZMh5qwrBItuziu834eOCUcEqymSH7pY+zoMVEZg3gcPuBNxH1EvfVYe9h0x/Ptw8KBzv7qxb7l8dg==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.3.tgz", + "integrity": "sha512-i5D1hPY7GIQmXlXhs2w8AWHhenb00+GxjxRncS2ZM7YNVGNfaMxgzSGuO8o8SJzRc/oZwU2bcScvVERk03QhzA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.3.tgz", + "integrity": "sha512-YdghPYUmj/FX2SYKJ0OZxf+iaKgMsKHVPF1MAq/P8WirnSpCStzKJFjOjzsW0QQ7oIAiccHdcqjbHmJxRb/dmg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.3.tgz", + "integrity": "sha512-IN/0BNTkHtk8lkOM8JWAYFg4ORxBkZQf9zXiEOfERX/CzxW3Vg1ewAhU7QSWQpVIzTW+b8Xy+lGzdYXV6UZObQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.3.tgz", + "integrity": "sha512-Re491k7ByTVRy0t3EKWajdLIr0gz2kKKfzafkth4Q8A5n1xTHrkqZgLLjFEHVD+AXdUGgQMq+Godfq45mGpCKg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.3.tgz", + "integrity": "sha512-vHk/hA7/1AckjGzRqi6wbo+jaShzRowYip6rt6q7VYEDX4LEy1pZfDpdxCBnGtl+A5zq8iXDcyuxwtv3hNtHFg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.3.tgz", + "integrity": "sha512-ipTYM2fjt3kQAYOvo6vcxJx3nBYAzPjgTCk7QEgZG8AUO3ydUhvelmhrbOheMnGOlaSFUoHXB6un+A7q4ygY9w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.3.tgz", + "integrity": "sha512-dDk0X87T7mI6U3K9VjWtHOXqwAMJBNN2r7bejDsc+j03SEjtD9HrOl8gVFByeM0aJksoUuUVU9TBaZa2rgj0oA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.3.tgz", + "integrity": "sha512-s6nPv2QkSupJwLYyfS+gwdirm0ukyTFNl3KTgZEAiJDd+iHZcbTPPcWCcRYH+WlNbwChgH2QkE9NSlNrMT8Gfw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.3.tgz", + "integrity": "sha512-sZOuFz/xWnZ4KH3YfFrKCf1WyPZHakVzTiqji3WDc0BCl2kBwiJLCXpzLzUBLgmp4veFZdvN5ChW4Eq/8Fc2Fg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.3.tgz", + "integrity": "sha512-yGlQYjdxtLdh0a3jHjuwOrxQjOZYD/C9PfdbgJJF3TIZWnm/tMd/RcNiLngiu4iwcBAOezdnSLAwQDPqTmtTYg==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.3.tgz", + "integrity": "sha512-WO60Sn8ly3gtzhyjATDgieJNet/KqsDlX5nRC5Y3oTFcS1l0KWba+SEa9Ja1GfDqSF1z6hif/SkpQJbL63cgOA==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.3.tgz", + "integrity": "sha512-APsymYA6sGcZ4pD6k+UxbDjOFSvPWyZhjaiPyl/f79xKxwTnrn5QUnXR5prvetuaSMsb4jgeHewIDCIWljrSxw==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.3.tgz", + "integrity": "sha512-eizBnTeBefojtDb9nSh4vvVQ3V9Qf9Df01PfawPcRzJH4gFSgrObw+LveUyDoKU3kxi5+9RJTCWlj4FjYXVPEA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.3.tgz", + "integrity": "sha512-3Emwh0r5wmfm3ssTWRQSyVhbOHvqegUDRd0WhmXKX2mkHJe1SFCMJhagUleMq+Uci34wLSipf8Lagt4LlpRFWQ==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.3.tgz", + "integrity": "sha512-pBHUx9LzXWBc7MFIEEL0yD/ZVtNgLytvx60gES28GcWMqil8ElCYR4kvbV2BDqsHOvVDRrOxGySBM9Fcv744hw==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.3.tgz", + "integrity": "sha512-Czi8yzXUWIQYAtL/2y6vogER8pvcsOsk5cpwL4Gk5nJqH5UZiVByIY8Eorm5R13gq+DQKYg0+JyQoytLQas4dA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.3.tgz", + "integrity": "sha512-sDpk0RgmTCR/5HguIZa9n9u+HVKf40fbEUt+iTzSnCaGvY9kFP0YKBWZtJaraonFnqef5SlJ8/TiPAxzyS+UoA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.3.tgz", + "integrity": "sha512-P14lFKJl/DdaE00LItAukUdZO5iqNH7+PjoBm+fLQjtxfcfFE20Xf5CrLsmZdq5LFFZzb5JMZ9grUwvtVYzjiA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.3.tgz", + "integrity": "sha512-AIcMP77AvirGbRl/UZFTq5hjXK+2wC7qFRGoHSDrZ5v5b8DK/GYpXW3CPRL53NkvDqb9D+alBiC/dV0Fb7eJcw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.3.tgz", + "integrity": "sha512-DnW2sRrBzA+YnE70LKqnM3P+z8vehfJWHXECbwBmH/CU51z6FiqTQTHFenPlHmo3a8UgpLyH3PT+87OViOh1AQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.3.tgz", + "integrity": "sha512-NinAEgr/etERPTsZJ7aEZQvvg/A6IsZG/LgZy+81wON2huV7SrK3e63dU0XhyZP4RKGyTm7aOgmQk0bGp0fy2g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.3.tgz", + "integrity": "sha512-PanZ+nEz+eWoBJ8/f8HKxTTD172SKwdXebZ0ndd953gt1HRBbhMsaNqjTyYLGLPdoWHy4zLU7bDVJztF5f3BHA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.3.tgz", + "integrity": "sha512-B2t59lWWYrbRDw/tjiWOuzSsFh1Y/E95ofKz7rIVYSQkUYBjfSgf6oeYPNWHToFRr2zx52JKApIcAS/D5TUBnA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.3.tgz", + "integrity": "sha512-QLKSFeXNS8+tHW7tZpMtjlNb7HKau0QDpwm49u0vUp9y1WOF+PEzkU84y9GqYaAVW8aH8f3GcBck26jh54cX4Q==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.3.tgz", + "integrity": "sha512-4uJGhsxuptu3OcpVAzli+/gWusVGwZZHTlS63hh++ehExkVT8SgiEf7/uC/PclrPPkLhZqGgCTjd0VWLo6xMqA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@types/node": { + "version": "20.19.37", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.37.tgz", + "integrity": "sha512-8kzdPJ3FsNsVIurqBs7oodNnCEVbni9yUEkaHbgptDACOPW04jimGagZ51E6+lXUwJjgnBw+hyko/lkFWCldqw==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~6.21.0" + } + }, + "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/balanced-match": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", + "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "18 || 20 || >=22" + } + }, + "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/brace-expansion": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.4.tgz", + "integrity": "sha512-h+DEnpVvxmfVefa4jFbCf5HdH5YMDXRsmKflpf1pILZWRFlTbJpxeU55nJl4Smt5HQaGzg1o6RHFPJaOqnmBDg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^4.0.2" + }, + "engines": { + "node": "18 || 20 || >=22" + } + }, + "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/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/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/esbuild": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.3.tgz", + "integrity": "sha512-8VwMnyGCONIs6cWue2IdpHxHnAjzxnw2Zr7MkVxB2vjmQ2ivqGFb4LEG3SMnv0Gb2F/G/2yA8zUaiL1gywDCCg==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.27.3", + "@esbuild/android-arm": "0.27.3", + "@esbuild/android-arm64": "0.27.3", + "@esbuild/android-x64": "0.27.3", + "@esbuild/darwin-arm64": "0.27.3", + "@esbuild/darwin-x64": "0.27.3", + "@esbuild/freebsd-arm64": "0.27.3", + "@esbuild/freebsd-x64": "0.27.3", + "@esbuild/linux-arm": "0.27.3", + "@esbuild/linux-arm64": "0.27.3", + "@esbuild/linux-ia32": "0.27.3", + "@esbuild/linux-loong64": "0.27.3", + "@esbuild/linux-mips64el": "0.27.3", + "@esbuild/linux-ppc64": "0.27.3", + "@esbuild/linux-riscv64": "0.27.3", + "@esbuild/linux-s390x": "0.27.3", + "@esbuild/linux-x64": "0.27.3", + "@esbuild/netbsd-arm64": "0.27.3", + "@esbuild/netbsd-x64": "0.27.3", + "@esbuild/openbsd-arm64": "0.27.3", + "@esbuild/openbsd-x64": "0.27.3", + "@esbuild/openharmony-arm64": "0.27.3", + "@esbuild/sunos-x64": "0.27.3", + "@esbuild/win32-arm64": "0.27.3", + "@esbuild/win32-ia32": "0.27.3", + "@esbuild/win32-x64": "0.27.3" + } + }, + "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/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/get-tsconfig": { + "version": "4.13.6", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.13.6.tgz", + "integrity": "sha512-shZT/QMiSHc/YBLxxOkMtgSid5HFoauqCE3/exfsEcwg1WkeqjG+V40yBbBrsD+jW2HDXcs28xOfcbm2jI8Ddw==", + "dev": true, + "license": "MIT", + "dependencies": { + "resolve-pkg-maps": "^1.0.0" + }, + "funding": { + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" + } + }, + "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/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/ignore-by-default": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", + "integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==", + "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-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-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/minimatch": { + "version": "10.2.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.4.tgz", + "integrity": "sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "brace-expansion": "^5.0.2" + }, + "engines": { + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "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/nodemon": { + "version": "3.1.14", + "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.1.14.tgz", + "integrity": "sha512-jakjZi93UtB3jHMWsXL68FXSAosbLfY0In5gtKq3niLSkrWznrVBzXFNOEMJUfc9+Ke7SHWoAZsiMkNP3vq6Jw==", + "dev": true, + "license": "MIT", + "dependencies": { + "chokidar": "^3.5.2", + "debug": "^4", + "ignore-by-default": "^1.0.1", + "minimatch": "^10.2.1", + "pstree.remy": "^1.1.8", + "semver": "^7.5.3", + "simple-update-notifier": "^2.0.0", + "supports-color": "^5.5.0", + "touch": "^3.1.0", + "undefsafe": "^2.0.5" + }, + "bin": { + "nodemon": "bin/nodemon.js" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/nodemon" + } + }, + "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/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/pstree.remy": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz", + "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==", + "dev": true, + "license": "MIT" + }, + "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/resolve-pkg-maps": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", + "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" + } + }, + "node_modules/semver": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", + "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/simple-update-notifier": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-2.0.0.tgz", + "integrity": "sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "semver": "^7.5.3" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "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/touch": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.1.tgz", + "integrity": "sha512-r0eojU4bI8MnHr8c5bNo7lJDdI2qXlWWJk6a9EAFG7vbhTjElYhBVS3/miuE0uOuoLdb8Mc/rVfsmm6eo5o9GA==", + "dev": true, + "license": "ISC", + "bin": { + "nodetouch": "bin/nodetouch.js" + } + }, + "node_modules/tsx": { + "version": "4.21.0", + "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.21.0.tgz", + "integrity": "sha512-5C1sg4USs1lfG0GFb2RLXsdpXqBSEhAaA/0kPL01wxzpMqLILNxIxIOKiILz+cdg/pLnOUxFYOR5yhHU666wbw==", + "dev": true, + "license": "MIT", + "dependencies": { + "esbuild": "~0.27.0", + "get-tsconfig": "^4.7.5" + }, + "bin": { + "tsx": "dist/cli.mjs" + }, + "engines": { + "node": ">=18.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + } + }, + "node_modules/typescript": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/undefsafe": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz", + "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==", + "dev": true, + "license": "MIT" + }, + "node_modules/undici-types": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", + "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/vscode-jsonrpc": { + "version": "8.2.1", + "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-8.2.1.tgz", + "integrity": "sha512-kdjOSJ2lLIn7r1rtrMbbNCHjyMPfRnowdKjBQ+mGq6NAW5QY2bEZC/khaC5OR8svbbjvLEaIXkOq45e2X9BIbQ==", + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + } + } +} diff --git a/playground/TypeScriptApps/AzureFunctionsSample/AppHost/package.json b/playground/TypeScriptApps/AzureFunctionsSample/AppHost/package.json new file mode 100644 index 00000000000..53411a60a9c --- /dev/null +++ b/playground/TypeScriptApps/AzureFunctionsSample/AppHost/package.json @@ -0,0 +1,19 @@ +{ + "name": "azurefunctionsendtoendts", + "version": "1.0.0", + "type": "module", + "scripts": { + "start": "aspire run", + "build": "tsc", + "dev": "tsc --watch" + }, + "dependencies": { + "vscode-jsonrpc": "^8.2.0" + }, + "devDependencies": { + "@types/node": "^20.0.0", + "nodemon": "^3.1.11", + "tsx": "^4.19.0", + "typescript": "^5.3.0" + } +} \ No newline at end of file diff --git a/playground/TypeScriptApps/AzureFunctionsSample/AppHost/tsconfig.json b/playground/TypeScriptApps/AzureFunctionsSample/AppHost/tsconfig.json new file mode 100644 index 00000000000..edf7302cc25 --- /dev/null +++ b/playground/TypeScriptApps/AzureFunctionsSample/AppHost/tsconfig.json @@ -0,0 +1,15 @@ +{ + "compilerOptions": { + "target": "ES2022", + "module": "NodeNext", + "moduleResolution": "NodeNext", + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true, + "strict": true, + "skipLibCheck": true, + "outDir": "./dist", + "rootDir": "." + }, + "include": ["apphost.ts", ".modules/**/*.ts"], + "exclude": ["node_modules"] +} \ No newline at end of file diff --git a/playground/TypeScriptApps/AzureFunctionsSample/TypeScriptApiService/package-lock.json b/playground/TypeScriptApps/AzureFunctionsSample/TypeScriptApiService/package-lock.json new file mode 100644 index 00000000000..25856e7cf48 --- /dev/null +++ b/playground/TypeScriptApps/AzureFunctionsSample/TypeScriptApiService/package-lock.json @@ -0,0 +1,2379 @@ +{ + "name": "typescript-api-service", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "typescript-api-service", + "version": "1.0.0", + "dependencies": { + "@azure/event-hubs": "^6.0.3", + "@azure/storage-blob": "^12.31.0", + "@azure/storage-queue": "^12.29.0", + "express": "^4.21.0" + }, + "devDependencies": { + "@types/express": "^4.17.21", + "@types/node": "^20.0.0", + "tsx": "^4.19.0", + "typescript": "^5.3.0" + } + }, + "node_modules/@azure/abort-controller": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@azure/abort-controller/-/abort-controller-2.1.2.tgz", + "integrity": "sha512-nBrLsEWm4J2u5LpAPjxADTlq3trDgVZZXHNKabeXZtpq3d3AbN/KGO82R87rdDz5/lYB024rtEf10/q0urNgsA==", + "license": "MIT", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@azure/core-amqp": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/@azure/core-amqp/-/core-amqp-4.4.1.tgz", + "integrity": "sha512-eiVwGOMpHWPS6YsX0kjW4rfH+f0Pb5L2EKNDbuXldVkuFKSEfROdl81xHLsMAl5PP5wiiTjErcMcKsJqwyaRqw==", + "license": "MIT", + "dependencies": { + "@azure/abort-controller": "^2.1.2", + "@azure/core-auth": "^1.10.0", + "@azure/core-util": "^1.13.0", + "@azure/logger": "^1.3.0", + "buffer": "^6.0.3", + "events": "^3.3.0", + "process": "^0.11.10", + "rhea": "^3.0.0", + "rhea-promise": "^3.0.0", + "tslib": "^2.6.2", + "util": "^0.12.5" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@azure/core-auth": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/@azure/core-auth/-/core-auth-1.10.1.tgz", + "integrity": "sha512-ykRMW8PjVAn+RS6ww5cmK9U2CyH9p4Q88YJwvUslfuMmN98w/2rdGRLPqJYObapBCdzBVeDgYWdJnFPFb7qzpg==", + "license": "MIT", + "dependencies": { + "@azure/abort-controller": "^2.1.2", + "@azure/core-util": "^1.13.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@azure/core-client": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/@azure/core-client/-/core-client-1.10.1.tgz", + "integrity": "sha512-Nh5PhEOeY6PrnxNPsEHRr9eimxLwgLlpmguQaHKBinFYA/RU9+kOYVOQqOrTsCL+KSxrLLl1gD8Dk5BFW/7l/w==", + "license": "MIT", + "dependencies": { + "@azure/abort-controller": "^2.1.2", + "@azure/core-auth": "^1.10.0", + "@azure/core-rest-pipeline": "^1.22.0", + "@azure/core-tracing": "^1.3.0", + "@azure/core-util": "^1.13.0", + "@azure/logger": "^1.3.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@azure/core-http-compat": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/@azure/core-http-compat/-/core-http-compat-2.3.2.tgz", + "integrity": "sha512-Tf6ltdKzOJEgxZeWLCjMxrxbodB/ZeCbzzA1A2qHbhzAjzjHoBVSUeSl/baT/oHAxhc4qdqVaDKnc2+iE932gw==", + "license": "MIT", + "dependencies": { + "@azure/abort-controller": "^2.1.2" + }, + "engines": { + "node": ">=20.0.0" + }, + "peerDependencies": { + "@azure/core-client": "^1.10.0", + "@azure/core-rest-pipeline": "^1.22.0" + } + }, + "node_modules/@azure/core-lro": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/@azure/core-lro/-/core-lro-2.7.2.tgz", + "integrity": "sha512-0YIpccoX8m/k00O7mDDMdJpbr6mf1yWo2dfmxt5A8XVZVVMz2SSKaEbMCeJRvgQ0IaSlqhjT47p4hVIRRy90xw==", + "license": "MIT", + "dependencies": { + "@azure/abort-controller": "^2.0.0", + "@azure/core-util": "^1.2.0", + "@azure/logger": "^1.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@azure/core-paging": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/@azure/core-paging/-/core-paging-1.6.2.tgz", + "integrity": "sha512-YKWi9YuCU04B55h25cnOYZHxXYtEvQEbKST5vqRga7hWY9ydd3FZHdeQF8pyh+acWZvppw13M/LMGx0LABUVMA==", + "license": "MIT", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@azure/core-rest-pipeline": { + "version": "1.23.0", + "resolved": "https://registry.npmjs.org/@azure/core-rest-pipeline/-/core-rest-pipeline-1.23.0.tgz", + "integrity": "sha512-Evs1INHo+jUjwHi1T6SG6Ua/LHOQBCLuKEEE6efIpt4ZOoNonaT1kP32GoOcdNDbfqsD2445CPri3MubBy5DEQ==", + "license": "MIT", + "dependencies": { + "@azure/abort-controller": "^2.1.2", + "@azure/core-auth": "^1.10.0", + "@azure/core-tracing": "^1.3.0", + "@azure/core-util": "^1.13.0", + "@azure/logger": "^1.3.0", + "@typespec/ts-http-runtime": "^0.3.4", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@azure/core-tracing": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@azure/core-tracing/-/core-tracing-1.3.1.tgz", + "integrity": "sha512-9MWKevR7Hz8kNzzPLfX4EAtGM2b8mr50HPDBvio96bURP/9C+HjdH3sBlLSNNrvRAr5/k/svoH457gB5IKpmwQ==", + "license": "MIT", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@azure/core-util": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/@azure/core-util/-/core-util-1.13.1.tgz", + "integrity": "sha512-XPArKLzsvl0Hf0CaGyKHUyVgF7oDnhKoP85Xv6M4StF/1AhfORhZudHtOyf2s+FcbuQ9dPRAjB8J2KvRRMUK2A==", + "license": "MIT", + "dependencies": { + "@azure/abort-controller": "^2.1.2", + "@typespec/ts-http-runtime": "^0.3.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@azure/core-xml": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@azure/core-xml/-/core-xml-1.5.0.tgz", + "integrity": "sha512-D/sdlJBMJfx7gqoj66PKVmhDDaU6TKA49ptcolxdas29X7AfvLTmfAGLjAcIMBK7UZ2o4lygHIqVckOlQU3xWw==", + "license": "MIT", + "dependencies": { + "fast-xml-parser": "^5.0.7", + "tslib": "^2.8.1" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@azure/event-hubs": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/@azure/event-hubs/-/event-hubs-6.0.3.tgz", + "integrity": "sha512-mMU8192XGCSaTKwr9MZuqAbX+aikcBh8wlp2icl/5mRc6kI4qVS8LIkkskHrvtzTugrvbVfop7musif5JYp+vg==", + "license": "MIT", + "dependencies": { + "@azure/abort-controller": "^2.1.2", + "@azure/core-amqp": "^4.3.2", + "@azure/core-auth": "^1.3.0", + "@azure/core-tracing": "^1.1.2", + "@azure/core-util": "^1.9.1", + "@azure/logger": "^1.1.4", + "buffer": "^6.0.3", + "is-buffer": "^2.0.5", + "process": "^0.11.10", + "rhea-promise": "^3.0.0", + "tslib": "^2.8.1", + "util": "^0.12.5" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@azure/logger": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@azure/logger/-/logger-1.3.0.tgz", + "integrity": "sha512-fCqPIfOcLE+CGqGPd66c8bZpwAji98tZ4JI9i/mlTNTlsIWslCfpg48s/ypyLxZTump5sypjrKn2/kY7q8oAbA==", + "license": "MIT", + "dependencies": { + "@typespec/ts-http-runtime": "^0.3.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@azure/storage-blob": { + "version": "12.31.0", + "resolved": "https://registry.npmjs.org/@azure/storage-blob/-/storage-blob-12.31.0.tgz", + "integrity": "sha512-DBgNv10aCSxopt92DkTDD0o9xScXeBqPKGmR50FPZQaEcH4JLQ+GEOGEDv19V5BMkB7kxr+m4h6il/cCDPvmHg==", + "license": "MIT", + "dependencies": { + "@azure/abort-controller": "^2.1.2", + "@azure/core-auth": "^1.9.0", + "@azure/core-client": "^1.9.3", + "@azure/core-http-compat": "^2.2.0", + "@azure/core-lro": "^2.2.0", + "@azure/core-paging": "^1.6.2", + "@azure/core-rest-pipeline": "^1.19.1", + "@azure/core-tracing": "^1.2.0", + "@azure/core-util": "^1.11.0", + "@azure/core-xml": "^1.4.5", + "@azure/logger": "^1.1.4", + "@azure/storage-common": "^12.3.0", + "events": "^3.0.0", + "tslib": "^2.8.1" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@azure/storage-common": { + "version": "12.3.0", + "resolved": "https://registry.npmjs.org/@azure/storage-common/-/storage-common-12.3.0.tgz", + "integrity": "sha512-/OFHhy86aG5Pe8dP5tsp+BuJ25JOAl9yaMU3WZbkeoiFMHFtJ7tu5ili7qEdBXNW9G5lDB19trwyI6V49F/8iQ==", + "license": "MIT", + "dependencies": { + "@azure/abort-controller": "^2.1.2", + "@azure/core-auth": "^1.9.0", + "@azure/core-http-compat": "^2.2.0", + "@azure/core-rest-pipeline": "^1.19.1", + "@azure/core-tracing": "^1.2.0", + "@azure/core-util": "^1.11.0", + "@azure/logger": "^1.1.4", + "events": "^3.3.0", + "tslib": "^2.8.1" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@azure/storage-queue": { + "version": "12.29.0", + "resolved": "https://registry.npmjs.org/@azure/storage-queue/-/storage-queue-12.29.0.tgz", + "integrity": "sha512-p02H+TbPQWSI/SQ4CG+luoDvpenM+4837NARmOE4oPNOR5vAq7qRyeX72ffyYL2YLnkcyxETh28/bp/TiVIM+g==", + "license": "MIT", + "dependencies": { + "@azure/abort-controller": "^2.1.2", + "@azure/core-auth": "^1.9.0", + "@azure/core-client": "^1.9.3", + "@azure/core-http-compat": "^2.0.0", + "@azure/core-paging": "^1.6.2", + "@azure/core-rest-pipeline": "^1.19.1", + "@azure/core-tracing": "^1.2.0", + "@azure/core-util": "^1.11.0", + "@azure/core-xml": "^1.4.3", + "@azure/logger": "^1.1.4", + "@azure/storage-common": "^12.2.0", + "tslib": "^2.8.1" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.3.tgz", + "integrity": "sha512-9fJMTNFTWZMh5qwrBItuziu834eOCUcEqymSH7pY+zoMVEZg3gcPuBNxH1EvfVYe9h0x/Ptw8KBzv7qxb7l8dg==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.3.tgz", + "integrity": "sha512-i5D1hPY7GIQmXlXhs2w8AWHhenb00+GxjxRncS2ZM7YNVGNfaMxgzSGuO8o8SJzRc/oZwU2bcScvVERk03QhzA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.3.tgz", + "integrity": "sha512-YdghPYUmj/FX2SYKJ0OZxf+iaKgMsKHVPF1MAq/P8WirnSpCStzKJFjOjzsW0QQ7oIAiccHdcqjbHmJxRb/dmg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.3.tgz", + "integrity": "sha512-IN/0BNTkHtk8lkOM8JWAYFg4ORxBkZQf9zXiEOfERX/CzxW3Vg1ewAhU7QSWQpVIzTW+b8Xy+lGzdYXV6UZObQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.3.tgz", + "integrity": "sha512-Re491k7ByTVRy0t3EKWajdLIr0gz2kKKfzafkth4Q8A5n1xTHrkqZgLLjFEHVD+AXdUGgQMq+Godfq45mGpCKg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.3.tgz", + "integrity": "sha512-vHk/hA7/1AckjGzRqi6wbo+jaShzRowYip6rt6q7VYEDX4LEy1pZfDpdxCBnGtl+A5zq8iXDcyuxwtv3hNtHFg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.3.tgz", + "integrity": "sha512-ipTYM2fjt3kQAYOvo6vcxJx3nBYAzPjgTCk7QEgZG8AUO3ydUhvelmhrbOheMnGOlaSFUoHXB6un+A7q4ygY9w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.3.tgz", + "integrity": "sha512-dDk0X87T7mI6U3K9VjWtHOXqwAMJBNN2r7bejDsc+j03SEjtD9HrOl8gVFByeM0aJksoUuUVU9TBaZa2rgj0oA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.3.tgz", + "integrity": "sha512-s6nPv2QkSupJwLYyfS+gwdirm0ukyTFNl3KTgZEAiJDd+iHZcbTPPcWCcRYH+WlNbwChgH2QkE9NSlNrMT8Gfw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.3.tgz", + "integrity": "sha512-sZOuFz/xWnZ4KH3YfFrKCf1WyPZHakVzTiqji3WDc0BCl2kBwiJLCXpzLzUBLgmp4veFZdvN5ChW4Eq/8Fc2Fg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.3.tgz", + "integrity": "sha512-yGlQYjdxtLdh0a3jHjuwOrxQjOZYD/C9PfdbgJJF3TIZWnm/tMd/RcNiLngiu4iwcBAOezdnSLAwQDPqTmtTYg==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.3.tgz", + "integrity": "sha512-WO60Sn8ly3gtzhyjATDgieJNet/KqsDlX5nRC5Y3oTFcS1l0KWba+SEa9Ja1GfDqSF1z6hif/SkpQJbL63cgOA==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.3.tgz", + "integrity": "sha512-APsymYA6sGcZ4pD6k+UxbDjOFSvPWyZhjaiPyl/f79xKxwTnrn5QUnXR5prvetuaSMsb4jgeHewIDCIWljrSxw==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.3.tgz", + "integrity": "sha512-eizBnTeBefojtDb9nSh4vvVQ3V9Qf9Df01PfawPcRzJH4gFSgrObw+LveUyDoKU3kxi5+9RJTCWlj4FjYXVPEA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.3.tgz", + "integrity": "sha512-3Emwh0r5wmfm3ssTWRQSyVhbOHvqegUDRd0WhmXKX2mkHJe1SFCMJhagUleMq+Uci34wLSipf8Lagt4LlpRFWQ==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.3.tgz", + "integrity": "sha512-pBHUx9LzXWBc7MFIEEL0yD/ZVtNgLytvx60gES28GcWMqil8ElCYR4kvbV2BDqsHOvVDRrOxGySBM9Fcv744hw==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.3.tgz", + "integrity": "sha512-Czi8yzXUWIQYAtL/2y6vogER8pvcsOsk5cpwL4Gk5nJqH5UZiVByIY8Eorm5R13gq+DQKYg0+JyQoytLQas4dA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.3.tgz", + "integrity": "sha512-sDpk0RgmTCR/5HguIZa9n9u+HVKf40fbEUt+iTzSnCaGvY9kFP0YKBWZtJaraonFnqef5SlJ8/TiPAxzyS+UoA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.3.tgz", + "integrity": "sha512-P14lFKJl/DdaE00LItAukUdZO5iqNH7+PjoBm+fLQjtxfcfFE20Xf5CrLsmZdq5LFFZzb5JMZ9grUwvtVYzjiA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.3.tgz", + "integrity": "sha512-AIcMP77AvirGbRl/UZFTq5hjXK+2wC7qFRGoHSDrZ5v5b8DK/GYpXW3CPRL53NkvDqb9D+alBiC/dV0Fb7eJcw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.3.tgz", + "integrity": "sha512-DnW2sRrBzA+YnE70LKqnM3P+z8vehfJWHXECbwBmH/CU51z6FiqTQTHFenPlHmo3a8UgpLyH3PT+87OViOh1AQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.3.tgz", + "integrity": "sha512-NinAEgr/etERPTsZJ7aEZQvvg/A6IsZG/LgZy+81wON2huV7SrK3e63dU0XhyZP4RKGyTm7aOgmQk0bGp0fy2g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.3.tgz", + "integrity": "sha512-PanZ+nEz+eWoBJ8/f8HKxTTD172SKwdXebZ0ndd953gt1HRBbhMsaNqjTyYLGLPdoWHy4zLU7bDVJztF5f3BHA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.3.tgz", + "integrity": "sha512-B2t59lWWYrbRDw/tjiWOuzSsFh1Y/E95ofKz7rIVYSQkUYBjfSgf6oeYPNWHToFRr2zx52JKApIcAS/D5TUBnA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.3.tgz", + "integrity": "sha512-QLKSFeXNS8+tHW7tZpMtjlNb7HKau0QDpwm49u0vUp9y1WOF+PEzkU84y9GqYaAVW8aH8f3GcBck26jh54cX4Q==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.3.tgz", + "integrity": "sha512-4uJGhsxuptu3OcpVAzli+/gWusVGwZZHTlS63hh++ehExkVT8SgiEf7/uC/PclrPPkLhZqGgCTjd0VWLo6xMqA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@types/body-parser": { + "version": "1.19.6", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.6.tgz", + "integrity": "sha512-HLFeCYgz89uk22N5Qg3dvGvsv46B8GLvKKo1zKG4NybA8U2DiEO3w9lqGg29t/tfLRJpJ6iQxnVw4OnB7MoM9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/connect": "*", + "@types/node": "*" + } + }, + "node_modules/@types/connect": { + "version": "3.4.38", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", + "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/express": { + "version": "4.17.25", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.25.tgz", + "integrity": "sha512-dVd04UKsfpINUnK0yBoYHDF3xu7xVH4BuDotC/xGuycx4CgbP48X/KF/586bcObxT0HENHXEU8Nqtu6NR+eKhw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "^4.17.33", + "@types/qs": "*", + "@types/serve-static": "^1" + } + }, + "node_modules/@types/express-serve-static-core": { + "version": "4.19.8", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.8.tgz", + "integrity": "sha512-02S5fmqeoKzVZCHPZid4b8JH2eM5HzQLZWN2FohQEy/0eXTq8VXZfSN6Pcr3F6N9R/vNrj7cpgbhjie6m/1tCA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*", + "@types/send": "*" + } + }, + "node_modules/@types/http-errors": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.5.tgz", + "integrity": "sha512-r8Tayk8HJnX0FztbZN7oVqGccWgw98T/0neJphO91KkmOzug1KkofZURD4UaD5uH8AqcFLfdPErnBod0u71/qg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/mime": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", + "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "20.19.37", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.37.tgz", + "integrity": "sha512-8kzdPJ3FsNsVIurqBs7oodNnCEVbni9yUEkaHbgptDACOPW04jimGagZ51E6+lXUwJjgnBw+hyko/lkFWCldqw==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~6.21.0" + } + }, + "node_modules/@types/qs": { + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.15.0.tgz", + "integrity": "sha512-JawvT8iBVWpzTrz3EGw9BTQFg3BQNmwERdKE22vlTxawwtbyUSlMppvZYKLZzB5zgACXdXxbD3m1bXaMqP/9ow==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/range-parser": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", + "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/send": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@types/send/-/send-1.2.1.tgz", + "integrity": "sha512-arsCikDvlU99zl1g69TcAB3mzZPpxgw0UQnaHeC1Nwb015xp8bknZv5rIfri9xTOcMuaVgvabfIRA7PSZVuZIQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/serve-static": { + "version": "1.15.10", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.10.tgz", + "integrity": "sha512-tRs1dB+g8Itk72rlSI2ZrW6vZg0YrLI81iQSTkMmOqnqCaNr/8Ek4VwWcN5vZgCYWbg/JJSGBlUaYGAOP73qBw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/http-errors": "*", + "@types/node": "*", + "@types/send": "<1" + } + }, + "node_modules/@types/serve-static/node_modules/@types/send": { + "version": "0.17.6", + "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.6.tgz", + "integrity": "sha512-Uqt8rPBE8SY0RK8JB1EzVOIZ32uqy8HwdxCnoCOsYrvnswqmFZ/k+9Ikidlk/ImhsdvBsloHbAlewb2IEBV/Og==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/mime": "^1", + "@types/node": "*" + } + }, + "node_modules/@typespec/ts-http-runtime": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/@typespec/ts-http-runtime/-/ts-http-runtime-0.3.4.tgz", + "integrity": "sha512-CI0NhTrz4EBaa0U+HaaUZrJhPoso8sG7ZFya8uQoBA57fjzrjRSv87ekCjLZOFExN+gXE/z0xuN2QfH4H2HrLQ==", + "license": "MIT", + "dependencies": { + "http-proxy-agent": "^7.0.0", + "https-proxy-agent": "^7.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "license": "MIT", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/agent-base": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", + "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==", + "license": "MIT", + "engines": { + "node": ">= 14" + } + }, + "node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", + "license": "MIT" + }, + "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==", + "license": "MIT", + "dependencies": { + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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==", + "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/body-parser": { + "version": "1.20.4", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.4.tgz", + "integrity": "sha512-ZTgYYLMOXY9qKU/57FAo8F+HA2dGX7bqGc71txDRC1rS4frdFI5R7NhluHxH6M0YItAP0sHB4uqAOcYKxO6uGA==", + "license": "MIT", + "dependencies": { + "bytes": "~3.1.2", + "content-type": "~1.0.5", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "~1.2.0", + "http-errors": "~2.0.1", + "iconv-lite": "~0.4.24", + "on-finished": "~2.4.1", + "qs": "~6.14.0", + "raw-body": "~2.5.3", + "type-is": "~1.6.18", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "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", + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "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==", + "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==", + "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==", + "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/content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "license": "MIT", + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", + "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.7.tgz", + "integrity": "sha512-NXdYc3dLr47pBkpUCHtKSwIOQXLVn8dZEuywboCOJY/osA0wFSLlSawr3KN8qXJEyX66FcONTH8EIlVuK0yyFA==", + "license": "MIT" + }, + "node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "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==", + "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/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "license": "MIT", + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "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==", + "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/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", + "license": "MIT" + }, + "node_modules/encodeurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "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==", + "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==", + "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==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/esbuild": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.3.tgz", + "integrity": "sha512-8VwMnyGCONIs6cWue2IdpHxHnAjzxnw2Zr7MkVxB2vjmQ2ivqGFb4LEG3SMnv0Gb2F/G/2yA8zUaiL1gywDCCg==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.27.3", + "@esbuild/android-arm": "0.27.3", + "@esbuild/android-arm64": "0.27.3", + "@esbuild/android-x64": "0.27.3", + "@esbuild/darwin-arm64": "0.27.3", + "@esbuild/darwin-x64": "0.27.3", + "@esbuild/freebsd-arm64": "0.27.3", + "@esbuild/freebsd-x64": "0.27.3", + "@esbuild/linux-arm": "0.27.3", + "@esbuild/linux-arm64": "0.27.3", + "@esbuild/linux-ia32": "0.27.3", + "@esbuild/linux-loong64": "0.27.3", + "@esbuild/linux-mips64el": "0.27.3", + "@esbuild/linux-ppc64": "0.27.3", + "@esbuild/linux-riscv64": "0.27.3", + "@esbuild/linux-s390x": "0.27.3", + "@esbuild/linux-x64": "0.27.3", + "@esbuild/netbsd-arm64": "0.27.3", + "@esbuild/netbsd-x64": "0.27.3", + "@esbuild/openbsd-arm64": "0.27.3", + "@esbuild/openbsd-x64": "0.27.3", + "@esbuild/openharmony-arm64": "0.27.3", + "@esbuild/sunos-x64": "0.27.3", + "@esbuild/win32-arm64": "0.27.3", + "@esbuild/win32-ia32": "0.27.3", + "@esbuild/win32-x64": "0.27.3" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "license": "MIT" + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "license": "MIT", + "engines": { + "node": ">=0.8.x" + } + }, + "node_modules/express": { + "version": "4.22.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.22.1.tgz", + "integrity": "sha512-F2X8g9P1X7uCPZMA3MVf9wcTqlyNp7IhH5qPCI0izhaOIYXaW9L535tGA3qmjRzpH+bZczqq7hVKxTR4NWnu+g==", + "license": "MIT", + "dependencies": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "~1.20.3", + "content-disposition": "~0.5.4", + "content-type": "~1.0.4", + "cookie": "~0.7.1", + "cookie-signature": "~1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "~1.3.1", + "fresh": "~0.5.2", + "http-errors": "~2.0.0", + "merge-descriptors": "1.0.3", + "methods": "~1.1.2", + "on-finished": "~2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "~0.1.12", + "proxy-addr": "~2.0.7", + "qs": "~6.14.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "~0.19.0", + "serve-static": "~1.16.2", + "setprototypeof": "1.2.0", + "statuses": "~2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/fast-xml-builder": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/fast-xml-builder/-/fast-xml-builder-1.1.2.tgz", + "integrity": "sha512-NJAmiuVaJEjVa7TjLZKlYd7RqmzOC91EtPFXHvlTcqBVo50Qh7XV5IwvXi1c7NRz2Q/majGX9YLcwJtWgHjtkA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT", + "dependencies": { + "path-expression-matcher": "^1.1.3" + } + }, + "node_modules/fast-xml-parser": { + "version": "5.5.3", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-5.5.3.tgz", + "integrity": "sha512-Ymnuefk6VzAhT3SxLzVUw+nMio/wB1NGypHkgetwtXcK1JfryaHk4DWQFGVwQ9XgzyS5iRZ7C2ZGI4AMsdMZ6A==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT", + "dependencies": { + "fast-xml-builder": "^1.1.2", + "path-expression-matcher": "^1.1.3", + "strnum": "^2.1.2" + }, + "bin": { + "fxparser": "src/cli/cli.js" + } + }, + "node_modules/finalhandler": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.2.tgz", + "integrity": "sha512-aA4RyPcd3badbdABGDuTXCMTtOneUCAYH/gxoYRTZlIJdF0YPWuGqiAsIrhNnnqdXGswYk6dGujem4w80UJFhg==", + "license": "MIT", + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "on-finished": "~2.4.1", + "parseurl": "~1.3.3", + "statuses": "~2.0.2", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/for-each": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz", + "integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==", + "license": "MIT", + "dependencies": { + "is-callable": "^1.2.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "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==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/generator-function": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/generator-function/-/generator-function-2.0.1.tgz", + "integrity": "sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "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==", + "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==", + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/get-tsconfig": { + "version": "4.13.6", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.13.6.tgz", + "integrity": "sha512-shZT/QMiSHc/YBLxxOkMtgSid5HFoauqCE3/exfsEcwg1WkeqjG+V40yBbBrsD+jW2HDXcs28xOfcbm2jI8Ddw==", + "dev": true, + "license": "MIT", + "dependencies": { + "resolve-pkg-maps": "^1.0.0" + }, + "funding": { + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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==", + "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==", + "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==", + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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/http-errors": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz", + "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==", + "license": "MIT", + "dependencies": { + "depd": "~2.0.0", + "inherits": "~2.0.4", + "setprototypeof": "~1.2.0", + "statuses": "~2.0.2", + "toidentifier": "~1.0.1" + }, + "engines": { + "node": ">= 0.8" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/http-proxy-agent": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", + "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.0", + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/http-proxy-agent/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/http-proxy-agent/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/https-proxy-agent": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", + "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/https-proxy-agent/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/https-proxy-agent/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/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "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/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/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "license": "MIT", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/is-arguments": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.2.0.tgz", + "integrity": "sha512-7bVbi0huj/wrIAOzb8U1aszg9kdi3KN/CyU19CTI7tAoZYEZoL9yCDXpbXN+uPsuWnP02cyug1gleqq+TU+YCA==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-buffer": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz", + "integrity": "sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==", + "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", + "engines": { + "node": ">=4" + } + }, + "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==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-generator-function": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.2.tgz", + "integrity": "sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.4", + "generator-function": "^2.0.0", + "get-proto": "^1.0.1", + "has-tostringtag": "^1.0.2", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-regex": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz", + "integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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==", + "license": "MIT", + "dependencies": { + "which-typed-array": "^1.1.16" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/merge-descriptors": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", + "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "license": "MIT", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "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/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, + "node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "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==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "license": "MIT", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/path-expression-matcher": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/path-expression-matcher/-/path-expression-matcher-1.1.3.tgz", + "integrity": "sha512-qdVgY8KXmVdJZRSS1JdEPOKPdTiEK/pi0RkcT2sw1RhXxohdujUlJFPuS1TSkevZ9vzd3ZlL7ULl1MHGTApKzQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/path-to-regexp": { + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz", + "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==", + "license": "MIT" + }, + "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==", + "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==", + "license": "MIT", + "engines": { + "node": ">= 0.6.0" + } + }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "license": "MIT", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/qs": { + "version": "6.14.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.2.tgz", + "integrity": "sha512-V/yCWTTF7VJ9hIh18Ugr2zhJMP01MY7c5kh4J870L7imm6/DIzBsNLTXzMwUA3yZ5b/KBqLx8Kp3uRvd7xSe3Q==", + "license": "BSD-3-Clause", + "dependencies": { + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "2.5.3", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.3.tgz", + "integrity": "sha512-s4VSOf6yN0rvbRZGxs8Om5CWj6seneMwK3oDb4lWDH0UPhWcxwOWw5+qk24bxq87szX1ydrwylIOp2uG1ojUpA==", + "license": "MIT", + "dependencies": { + "bytes": "~3.1.2", + "http-errors": "~2.0.1", + "iconv-lite": "~0.4.24", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/resolve-pkg-maps": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", + "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" + } + }, + "node_modules/rhea": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/rhea/-/rhea-3.0.4.tgz", + "integrity": "sha512-n3kw8syCdrsfJ72w3rohpoHHlmv/RZZEP9VY5BVjjo0sEGIt4YSKypBgaiA+OUSgJAzLjOECYecsclG5xbYtZw==", + "license": "Apache-2.0", + "dependencies": { + "debug": "^4.3.3" + } + }, + "node_modules/rhea-promise": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/rhea-promise/-/rhea-promise-3.0.3.tgz", + "integrity": "sha512-a875P5YcMkePSTEWMsnmCQS7Y4v/XvIw7ZoMtJxqtQRZsqSA6PsZxuz4vktyRykPuUgdNsA6F84dS3iEXZoYnQ==", + "license": "Apache-2.0", + "dependencies": { + "debug": "^4.0.0", + "rhea": "^3.0.0", + "tslib": "^2.6.0" + } + }, + "node_modules/rhea-promise/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/rhea-promise/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/rhea/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/rhea/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/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==", + "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/safe-regex-test": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz", + "integrity": "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "is-regex": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "license": "MIT" + }, + "node_modules/send": { + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/send/-/send-0.19.2.tgz", + "integrity": "sha512-VMbMxbDeehAxpOtWJXlcUS5E8iXh6QmN+BkRX1GARS3wRaXEEgzCcB10gTQazO42tpNIya8xIyNx8fll1OFPrg==", + "license": "MIT", + "dependencies": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "~0.5.2", + "http-errors": "~2.0.1", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "~2.4.1", + "range-parser": "~1.2.1", + "statuses": "~2.0.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/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/serve-static": { + "version": "1.16.3", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.3.tgz", + "integrity": "sha512-x0RTqQel6g5SY7Lg6ZreMmsOzncHFU7nhnRWkKgWuMTu5NN0DR5oruckMqRvacAN9d5w6ARnRBXl9xhDCgfMeA==", + "license": "MIT", + "dependencies": { + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "~0.19.1" + }, + "engines": { + "node": ">= 0.8.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==", + "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/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "license": "ISC" + }, + "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==", + "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==", + "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==", + "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==", + "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/statuses": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", + "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/strnum": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/strnum/-/strnum-2.2.0.tgz", + "integrity": "sha512-Y7Bj8XyJxnPAORMZj/xltsfo55uOiyHcU2tnAVzHUnSJR/KsEX+9RoDeXEnsXtl/CX4fAcrt64gZ13aGaWPeBg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT" + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "license": "MIT", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, + "node_modules/tsx": { + "version": "4.21.0", + "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.21.0.tgz", + "integrity": "sha512-5C1sg4USs1lfG0GFb2RLXsdpXqBSEhAaA/0kPL01wxzpMqLILNxIxIOKiILz+cdg/pLnOUxFYOR5yhHU666wbw==", + "dev": true, + "license": "MIT", + "dependencies": { + "esbuild": "~0.27.0", + "get-tsconfig": "^4.7.5" + }, + "bin": { + "tsx": "dist/cli.mjs" + }, + "engines": { + "node": ">=18.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + } + }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "license": "MIT", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/typescript": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "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://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", + "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/util": { + "version": "0.12.5", + "resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz", + "integrity": "sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "is-arguments": "^1.0.4", + "is-generator-function": "^1.0.7", + "is-typed-array": "^1.1.3", + "which-typed-array": "^1.1.2" + } + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "license": "MIT", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/which-typed-array": { + "version": "1.1.20", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.20.tgz", + "integrity": "sha512-LYfpUkmqwl0h9A2HL09Mms427Q1RZWuOHsukfVcKRq9q95iQxdw0ix1JQrqbcDR9PH1QDwf5Qo8OZb5lksZ8Xg==", + "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" + } + } + } +} diff --git a/playground/TypeScriptApps/AzureFunctionsSample/TypeScriptApiService/package.json b/playground/TypeScriptApps/AzureFunctionsSample/TypeScriptApiService/package.json new file mode 100644 index 00000000000..8f3caf42f18 --- /dev/null +++ b/playground/TypeScriptApps/AzureFunctionsSample/TypeScriptApiService/package.json @@ -0,0 +1,23 @@ +{ + "name": "typescript-api-service", + "version": "1.0.0", + "description": "TypeScript API service for Azure Functions E2E sample", + "type": "module", + "scripts": { + "start": "tsx src/app.ts", + "dev": "tsx watch src/app.ts", + "build": "tsc" + }, + "dependencies": { + "express": "^4.21.0", + "@azure/storage-queue": "^12.29.0", + "@azure/storage-blob": "^12.31.0", + "@azure/event-hubs": "^6.0.3" + }, + "devDependencies": { + "@types/express": "^4.17.21", + "@types/node": "^20.0.0", + "tsx": "^4.19.0", + "typescript": "^5.3.0" + } +} diff --git a/playground/TypeScriptApps/AzureFunctionsSample/TypeScriptApiService/src/app.ts b/playground/TypeScriptApps/AzureFunctionsSample/TypeScriptApiService/src/app.ts new file mode 100644 index 00000000000..5980b4bf465 --- /dev/null +++ b/playground/TypeScriptApps/AzureFunctionsSample/TypeScriptApiService/src/app.ts @@ -0,0 +1,78 @@ +import express from "express"; +import { QueueServiceClient } from "@azure/storage-queue"; +import { BlobServiceClient } from "@azure/storage-blob"; +import { EventHubProducerClient } from "@azure/event-hubs"; +import crypto from "crypto"; + +const app = express(); +const port = parseInt(process.env["PORT"] || "3000"); + +function randomString(length: number): string { + const chars = "abcdefghijklmnopqrstuvwxyz"; + return Array.from(crypto.randomBytes(length)) + .map((b) => chars[b % chars.length]) + .join(""); +} + +app.get("/publish/asq", async (_req, res) => { + try { + const connectionString = process.env["ConnectionStrings__queue"] || ""; + const client = QueueServiceClient.fromConnectionString(connectionString); + const queue = client.getQueueClient("queue"); + await queue.createIfNotExists(); + const data = Buffer.from("Hello, World!").toString("base64"); + await queue.sendMessage(data); + res.send("Message sent to Azure Storage Queue."); + } catch (err) { + res.status(500).send(`Error publishing to queue: ${err}`); + } +}); + +app.get("/publish/blob", async (_req, res) => { + try { + const connectionString = process.env["ConnectionStrings__blob"] || ""; + const client = BlobServiceClient.fromConnectionString(connectionString); + const container = client.getContainerClient("myblobcontainer"); + await container.createIfNotExists(); + + const entry = { id: crypto.randomUUID(), text: randomString(20) }; + const content = JSON.stringify(entry); + const blob = container.getBlockBlobClient(entry.id); + await blob.upload(content, content.length); + + res.send("String uploaded to Azure Storage Blobs."); + } catch (err) { + res.status(500).send(`Error uploading blob: ${err}`); + } +}); + +app.get("/publish/eventhubs", async (_req, res) => { + try { + const connectionString = process.env["ConnectionStrings__myhub"] || ""; + const client = new EventHubProducerClient(connectionString, "myhub"); + const batch = await client.createBatch(); + batch.tryAdd({ body: randomString(20) }); + await client.sendBatch(batch); + await client.close(); + res.send("Message sent to Azure Event Hubs."); + } catch (err) { + res.status(500).send(`Error publishing to Event Hubs: ${err}`); + } +}); + +app.get("/", async (_req, res) => { + try { + const funcAppUrl = + process.env["services__funcapp__http__0"] || + "http://localhost:7071"; + const response = await fetch(`${funcAppUrl}/api/httpTrigger?name=Aspire`); + const text = await response.text(); + res.send(text); + } catch (err) { + res.status(500).send(`Error calling function: ${err}`); + } +}); + +app.listen(port, () => { + console.log(`API service listening on port ${port}`); +}); diff --git a/playground/TypeScriptApps/AzureFunctionsSample/TypeScriptApiService/tsconfig.json b/playground/TypeScriptApps/AzureFunctionsSample/TypeScriptApiService/tsconfig.json new file mode 100644 index 00000000000..de188ce8faf --- /dev/null +++ b/playground/TypeScriptApps/AzureFunctionsSample/TypeScriptApiService/tsconfig.json @@ -0,0 +1,13 @@ +{ + "compilerOptions": { + "module": "Node16", + "target": "ES2022", + "outDir": "dist", + "rootDir": "src", + "sourceMap": true, + "strict": true, + "esModuleInterop": true, + "moduleResolution": "Node16" + }, + "include": ["src"] +} diff --git a/playground/TypeScriptApps/AzureFunctionsSample/TypeScriptFunctions/host.json b/playground/TypeScriptApps/AzureFunctionsSample/TypeScriptFunctions/host.json new file mode 100644 index 00000000000..4162ab5c171 --- /dev/null +++ b/playground/TypeScriptApps/AzureFunctionsSample/TypeScriptFunctions/host.json @@ -0,0 +1,13 @@ +{ + "version": "2.0", + "logging": { + "applicationInsights": { + "samplingSettings": { + "isEnabled": true, + "excludedTypes": "Request" + }, + "enableLiveMetricsFilters": true + } + }, + "telemetryMode": "openTelemetry" +} diff --git a/playground/TypeScriptApps/AzureFunctionsSample/TypeScriptFunctions/package-lock.json b/playground/TypeScriptApps/AzureFunctionsSample/TypeScriptFunctions/package-lock.json new file mode 100644 index 00000000000..94ef48e298a --- /dev/null +++ b/playground/TypeScriptApps/AzureFunctionsSample/TypeScriptFunctions/package-lock.json @@ -0,0 +1,81 @@ +{ + "name": "azure-functions-typescript", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "azure-functions-typescript", + "version": "1.0.0", + "dependencies": { + "@azure/functions": "^4.7.0" + }, + "devDependencies": { + "@types/node": "^20.0.0", + "typescript": "^5.3.0" + } + }, + "node_modules/@azure/functions": { + "version": "4.11.2", + "resolved": "https://registry.npmjs.org/@azure/functions/-/functions-4.11.2.tgz", + "integrity": "sha512-U7qpPo0pUxDfdP3Q8gO5GLtust94nh8+RtIUvEKE4qU9yuDhL2vU1zzanuzkaV2j/TFv+EEmN8QDtchAgpeffw==", + "license": "MIT", + "dependencies": { + "@azure/functions-extensions-base": "0.2.0", + "cookie": "^0.7.0" + }, + "engines": { + "node": ">=20.0" + } + }, + "node_modules/@azure/functions-extensions-base": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@azure/functions-extensions-base/-/functions-extensions-base-0.2.0.tgz", + "integrity": "sha512-ncCkHBNQYJa93dBIh+toH0v1iSgCzSo9tr94s6SMBe7DPWREkaWh8cq33A5P4rPSFX1g5W+3SPvIzDr/6/VOWQ==", + "license": "MIT", + "engines": { + "node": ">=18.0" + } + }, + "node_modules/@types/node": { + "version": "20.19.37", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.37.tgz", + "integrity": "sha512-8kzdPJ3FsNsVIurqBs7oodNnCEVbni9yUEkaHbgptDACOPW04jimGagZ51E6+lXUwJjgnBw+hyko/lkFWCldqw==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~6.21.0" + } + }, + "node_modules/cookie": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", + "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/typescript": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "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://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", + "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", + "dev": true, + "license": "MIT" + } + } +} diff --git a/playground/TypeScriptApps/AzureFunctionsSample/TypeScriptFunctions/package.json b/playground/TypeScriptApps/AzureFunctionsSample/TypeScriptFunctions/package.json new file mode 100644 index 00000000000..beef5044df6 --- /dev/null +++ b/playground/TypeScriptApps/AzureFunctionsSample/TypeScriptFunctions/package.json @@ -0,0 +1,19 @@ +{ + "name": "azure-functions-typescript", + "version": "1.0.0", + "description": "Azure Functions TypeScript E2E sample for Aspire", + "main": "dist/src/index.js", + "scripts": { + "build": "tsc", + "watch": "tsc -w", + "prestart": "npm run build", + "start": "func start" + }, + "dependencies": { + "@azure/functions": "^4.7.0" + }, + "devDependencies": { + "@types/node": "^20.0.0", + "typescript": "^5.3.0" + } +} diff --git a/playground/TypeScriptApps/AzureFunctionsSample/TypeScriptFunctions/src/functions/blobTrigger.ts b/playground/TypeScriptApps/AzureFunctionsSample/TypeScriptFunctions/src/functions/blobTrigger.ts new file mode 100644 index 00000000000..960bf803c06 --- /dev/null +++ b/playground/TypeScriptApps/AzureFunctionsSample/TypeScriptFunctions/src/functions/blobTrigger.ts @@ -0,0 +1,21 @@ +import { app, InvocationContext, output } from "@azure/functions"; + +const blobOutput = output.storageBlob({ + connection: "blob", + path: "test-files/{name}.txt", +}); + +export async function blobTrigger(blob: Buffer, context: InvocationContext): Promise { + const blobName = context.triggerMetadata?.name as string; + context.log(`Blob trigger function invoked for 'myblobcontainer/${blobName}' with size ${blob.length} bytes`); + + const content = blob.toString(); + context.extraOutputs.set(blobOutput, content.toUpperCase()); +} + +app.storageBlob("blobTrigger", { + path: "myblobcontainer/{name}", + connection: "blob", + extraOutputs: [blobOutput], + handler: blobTrigger, +}); diff --git a/playground/TypeScriptApps/AzureFunctionsSample/TypeScriptFunctions/src/functions/eventHubTrigger.ts b/playground/TypeScriptApps/AzureFunctionsSample/TypeScriptFunctions/src/functions/eventHubTrigger.ts new file mode 100644 index 00000000000..ddc3d1c0b52 --- /dev/null +++ b/playground/TypeScriptApps/AzureFunctionsSample/TypeScriptFunctions/src/functions/eventHubTrigger.ts @@ -0,0 +1,15 @@ +import { app, InvocationContext } from "@azure/functions"; + +export async function eventHubTrigger(messages: unknown[], context: InvocationContext): Promise { + context.log(`EventHub trigger function processed ${messages.length} messages`); + for (const message of messages) { + context.log("EventHub message:", message); + } +} + +app.eventHub("eventHubTrigger", { + connection: "myhub", + eventHubName: "myhub", + cardinality: "many", + handler: eventHubTrigger, +}); diff --git a/playground/TypeScriptApps/AzureFunctionsSample/TypeScriptFunctions/src/functions/httpTrigger.ts b/playground/TypeScriptApps/AzureFunctionsSample/TypeScriptFunctions/src/functions/httpTrigger.ts new file mode 100644 index 00000000000..a11c6c06796 --- /dev/null +++ b/playground/TypeScriptApps/AzureFunctionsSample/TypeScriptFunctions/src/functions/httpTrigger.ts @@ -0,0 +1,17 @@ +import { app, HttpRequest, HttpResponseInit, InvocationContext } from "@azure/functions"; + +export async function httpTrigger(request: HttpRequest, context: InvocationContext): Promise { + context.log("HTTP trigger function processed a request."); + + const name = request.query.get("name") || (await request.text()) || "World"; + + return { + body: `Hello, ${name}! This is an Aspire-hosted Azure Functions TypeScript app.` + }; +} + +app.http("httpTrigger", { + methods: ["GET", "POST"], + authLevel: "anonymous", + handler: httpTrigger, +}); diff --git a/playground/TypeScriptApps/AzureFunctionsSample/TypeScriptFunctions/src/functions/queueTrigger.ts b/playground/TypeScriptApps/AzureFunctionsSample/TypeScriptFunctions/src/functions/queueTrigger.ts new file mode 100644 index 00000000000..d1e961fa1d7 --- /dev/null +++ b/playground/TypeScriptApps/AzureFunctionsSample/TypeScriptFunctions/src/functions/queueTrigger.ts @@ -0,0 +1,11 @@ +import { app, InvocationContext } from "@azure/functions"; + +export async function queueTrigger(queueItem: unknown, context: InvocationContext): Promise { + context.log("Queue trigger function processed:", queueItem); +} + +app.storageQueue("queueTrigger", { + queueName: "queue", + connection: "queue", + handler: queueTrigger, +}); diff --git a/playground/TypeScriptApps/AzureFunctionsSample/TypeScriptFunctions/src/index.ts b/playground/TypeScriptApps/AzureFunctionsSample/TypeScriptFunctions/src/index.ts new file mode 100644 index 00000000000..94c3a327043 --- /dev/null +++ b/playground/TypeScriptApps/AzureFunctionsSample/TypeScriptFunctions/src/index.ts @@ -0,0 +1,5 @@ +// Import and register all function modules +import "./functions/httpTrigger.js"; +import "./functions/queueTrigger.js"; +import "./functions/blobTrigger.js"; +import "./functions/eventHubTrigger.js"; diff --git a/playground/TypeScriptApps/AzureFunctionsSample/TypeScriptFunctions/tsconfig.json b/playground/TypeScriptApps/AzureFunctionsSample/TypeScriptFunctions/tsconfig.json new file mode 100644 index 00000000000..7348d306890 --- /dev/null +++ b/playground/TypeScriptApps/AzureFunctionsSample/TypeScriptFunctions/tsconfig.json @@ -0,0 +1,11 @@ +{ + "compilerOptions": { + "module": "Node16", + "target": "ES2022", + "outDir": "dist", + "rootDir": ".", + "sourceMap": true, + "strict": true, + "esModuleInterop": true + } +} diff --git a/src/Aspire.Cli/Certificates/CertificateGeneration/WindowsCertificateManager.cs b/src/Aspire.Cli/Certificates/CertificateGeneration/WindowsCertificateManager.cs index b06626256a0..df5a068a09a 100644 --- a/src/Aspire.Cli/Certificates/CertificateGeneration/WindowsCertificateManager.cs +++ b/src/Aspire.Cli/Certificates/CertificateGeneration/WindowsCertificateManager.cs @@ -13,6 +13,9 @@ namespace Microsoft.AspNetCore.Certificates.Generation; [SupportedOSPlatform("windows")] internal sealed class WindowsCertificateManager : CertificateManager { + /// Win32 ERROR_CANCELLED (0x4C7) encoded as an HRESULT (0x800704C7). + /// Thrown when the user dismisses the Windows certificate-store security dialog. + private const int UserCancelledHResult = unchecked((int)0x800704C7); private const int UserCancelledErrorCode = 1223; public WindowsCertificateManager(ILogger logger) : base(logger) @@ -89,7 +92,7 @@ protected override TrustLevel TrustCertificateCore(X509Certificate2 certificate) store.Add(publicCertificate); return TrustLevel.Full; } - catch (CryptographicException exception) when (exception.HResult == UserCancelledErrorCode) + catch (CryptographicException exception) when (exception.HResult == UserCancelledHResult || exception.HResult == UserCancelledErrorCode) { Log.WindowsCertificateTrustCanceled(); throw new UserCancelledTrustException(); diff --git a/src/Aspire.Cli/Certificates/CertificateHelpers.cs b/src/Aspire.Cli/Certificates/CertificateHelpers.cs new file mode 100644 index 00000000000..3eb4d185626 --- /dev/null +++ b/src/Aspire.Cli/Certificates/CertificateHelpers.cs @@ -0,0 +1,82 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using System.Text.RegularExpressions; +using Microsoft.AspNetCore.Certificates.Generation; + +namespace Aspire.Cli.Certificates; + +/// +/// Shared helper methods for certificate operations. +/// +internal static partial class CertificateHelpers +{ + /// + /// Determines whether the specified represents a successful trust operation. + /// + /// The result to evaluate. + /// if the result represents success; otherwise, . + internal static bool IsSuccessfulTrustResult(EnsureCertificateResult result) => + result is EnsureCertificateResult.Succeeded + or EnsureCertificateResult.ValidCertificatePresent + or EnsureCertificateResult.ExistingHttpsCertificateTrusted + or EnsureCertificateResult.NewHttpsCertificateTrusted; + + /// + /// Tries to detect the OpenSSL directory by running 'openssl version -d'. + /// Parses the OPENSSLDIR value from the output (e.g. OPENSSLDIR: "/usr/lib/ssl"). + /// + /// The detected OpenSSL directory path if successful. + /// if the directory was detected; otherwise, . + internal static bool TryGetOpenSslDirectory([NotNullWhen(true)] out string? openSslDir) + { + openSslDir = null; + + try + { + var processInfo = new ProcessStartInfo("openssl", "version -d") + { + RedirectStandardOutput = true, + RedirectStandardError = true, + UseShellExecute = false, + CreateNoWindow = true + }; + + using var process = Process.Start(processInfo); + if (process is null) + { + return false; + } + + var stdout = process.StandardOutput.ReadToEnd(); + if (!process.WaitForExit(TimeSpan.FromSeconds(5))) + { + return false; + } + + if (process.ExitCode != 0) + { + return false; + } + + var match = OpenSslVersionRegex().Match(stdout); + if (!match.Success) + { + return false; + } + + openSslDir = match.Groups[1].Value; + return true; + } + catch + { + // openssl may not be installed — silently fail + return false; + } + } + + [GeneratedRegex("OPENSSLDIR:\\s*\"([^\"]+)\"")] + internal static partial Regex OpenSslVersionRegex(); +} diff --git a/src/Aspire.Cli/Certificates/CertificateService.cs b/src/Aspire.Cli/Certificates/CertificateService.cs index f24e89d0dc3..5db5f72e53a 100644 --- a/src/Aspire.Cli/Certificates/CertificateService.cs +++ b/src/Aspire.Cli/Certificates/CertificateService.cs @@ -2,15 +2,12 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Diagnostics; -using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.Runtime.InteropServices; -using System.Text.RegularExpressions; -using Aspire.Cli.DotNet; using Aspire.Cli.Interaction; using Aspire.Cli.Resources; using Aspire.Cli.Telemetry; -using Aspire.Cli.Utils; +using Microsoft.AspNetCore.Certificates.Generation; namespace Aspire.Cli.Certificates; @@ -31,7 +28,7 @@ internal interface ICertificateService Task EnsureCertificatesTrustedAsync(CancellationToken cancellationToken); } -internal sealed partial class CertificateService( +internal sealed class CertificateService( ICertificateToolRunner certificateToolRunner, IInteractionService interactionService, AspireCliTelemetry telemetry) : ICertificateService @@ -58,11 +55,10 @@ public async Task EnsureCertificatesTrustedAsyn using var activity = telemetry.StartDiagnosticActivity(kind: ActivityKind.Client); var environmentVariables = new Dictionary(); - var ensureCertificateCollector = new OutputCollector(); // Use the machine-readable check (available in .NET 10 SDK which is the minimum required) - var trustResult = await CheckMachineReadableAsync(ensureCertificateCollector, cancellationToken); - await HandleMachineReadableTrustAsync(trustResult, ensureCertificateCollector, environmentVariables, cancellationToken); + var trustResult = await CheckMachineReadableAsync(); + await HandleMachineReadableTrustAsync(trustResult, environmentVariables); return new EnsureCertificatesTrustedResult { @@ -70,35 +66,19 @@ public async Task EnsureCertificatesTrustedAsyn }; } - private async Task CheckMachineReadableAsync( - OutputCollector collector, - CancellationToken cancellationToken) + private async Task CheckMachineReadableAsync() { - var options = new DotNetCliRunnerInvocationOptions - { - StandardOutputCallback = collector.AppendOutput, - StandardErrorCallback = collector.AppendError, - }; - - var (_, result) = await interactionService.ShowStatusAsync( + var result = await interactionService.ShowStatusAsync( InteractionServiceStrings.CheckingCertificates, - async () => await certificateToolRunner.CheckHttpCertificateMachineReadableAsync(options, cancellationToken), + () => Task.FromResult(certificateToolRunner.CheckHttpCertificate()), emoji: KnownEmojis.LockedWithKey); - // Return the result or a default "no certificates" result - return result ?? new CertificateTrustResult - { - HasCertificates = false, - TrustLevel = null, - Certificates = [] - }; + return result; } private async Task HandleMachineReadableTrustAsync( CertificateTrustResult trustResult, - OutputCollector collector, - Dictionary environmentVariables, - CancellationToken cancellationToken) + Dictionary environmentVariables) { // If fully trusted, nothing more to do if (trustResult.IsFullyTrusted) @@ -109,35 +89,22 @@ private async Task HandleMachineReadableTrustAsync( // If not trusted at all, run the trust operation if (trustResult.IsNotTrusted) { - var options = new DotNetCliRunnerInvocationOptions - { - StandardOutputCallback = collector.AppendOutput, - StandardErrorCallback = collector.AppendError, - }; - - var trustExitCode = await interactionService.ShowStatusAsync( + var trustResultCode = await interactionService.ShowStatusAsync( InteractionServiceStrings.TrustingCertificates, - () => certificateToolRunner.TrustHttpCertificateAsync(options, cancellationToken), + () => Task.FromResult(certificateToolRunner.TrustHttpCertificate()), emoji: KnownEmojis.LockedWithKey); - if (trustExitCode != 0) + if (trustResultCode == EnsureCertificateResult.UserCancelledTrustStep) { - interactionService.DisplayLines(collector.GetLines()); - interactionService.DisplayMessage(KnownEmojis.Warning, string.Format(CultureInfo.CurrentCulture, ErrorStrings.CertificatesMayNotBeFullyTrusted, trustExitCode)); + interactionService.DisplayMessage(KnownEmojis.Warning, CertificatesCommandStrings.TrustCancelled); } - - // Re-check trust status after trust operation - var recheckOptions = new DotNetCliRunnerInvocationOptions - { - StandardOutputCallback = collector.AppendOutput, - StandardErrorCallback = collector.AppendError, - }; - - var (_, recheckResult) = await certificateToolRunner.CheckHttpCertificateMachineReadableAsync(recheckOptions, cancellationToken); - if (recheckResult is not null) + else if (!CertificateHelpers.IsSuccessfulTrustResult(trustResultCode)) { - trustResult = recheckResult; + interactionService.DisplayMessage(KnownEmojis.Warning, string.Format(CultureInfo.CurrentCulture, ErrorStrings.CertificatesMayNotBeFullyTrusted, trustResultCode)); } + + // Re-check trust status after trust operation + trustResult = certificateToolRunner.CheckHttpCertificate(); } // If partially trusted (either initially or after trust), configure SSL_CERT_DIR on Linux @@ -174,9 +141,13 @@ private static void ConfigureSslCertDir(Dictionary environmentVa // Query OpenSSL to get its configured certificate directory. var systemCertDirs = new List(); - if (TryGetOpenSslCertsDirectory(out var openSslCertsDir)) + if (CertificateHelpers.TryGetOpenSslDirectory(out var openSslDir)) { - systemCertDirs.Add(openSslCertsDir); + var openSslCertsDir = Path.Combine(openSslDir, "certs"); + if (Directory.Exists(openSslCertsDir)) + { + systemCertDirs.Add(openSslCertsDir); + } } else { @@ -198,70 +169,8 @@ private static void ConfigureSslCertDir(Dictionary environmentVa } } - /// - /// Attempts to get the OpenSSL certificates directory by running 'openssl version -d'. - /// This is the same approach used by ASP.NET Core's certificate manager. - /// - /// The path to the OpenSSL certificates directory if found. - /// True if the OpenSSL certs directory was found, false otherwise. - private static bool TryGetOpenSslCertsDirectory([NotNullWhen(true)] out string? certsDir) - { - certsDir = null; - - try - { - var processInfo = new ProcessStartInfo("openssl", "version -d") - { - RedirectStandardOutput = true, - RedirectStandardError = true, - UseShellExecute = false, - CreateNoWindow = true - }; - - using var process = Process.Start(processInfo); - if (process is null) - { - return false; - } - - var stdout = process.StandardOutput.ReadToEnd(); - process.WaitForExit(TimeSpan.FromSeconds(5)); - - if (process.ExitCode != 0) - { - return false; - } - - // Parse output like: OPENSSLDIR: "/usr/lib/ssl" - var match = OpenSslVersionRegex().Match(stdout); - if (!match.Success) - { - return false; - } - - var openSslDir = match.Groups[1].Value; - certsDir = Path.Combine(openSslDir, "certs"); - - // Verify the directory exists - if (!Directory.Exists(certsDir)) - { - certsDir = null; - return false; - } - - return true; - } - catch - { - return false; - } - } - - [GeneratedRegex("OPENSSLDIR:\\s*\"([^\"]+)\"")] - private static partial Regex OpenSslVersionRegex(); } -public sealed class CertificateServiceException(string message) : Exception(message) +internal sealed class CertificateServiceException(string message) : Exception(message) { - } diff --git a/src/Aspire.Cli/Certificates/DevCertInfo.cs b/src/Aspire.Cli/Certificates/DevCertInfo.cs index b229c6d6c11..c1221896b88 100644 --- a/src/Aspire.Cli/Certificates/DevCertInfo.cs +++ b/src/Aspire.Cli/Certificates/DevCertInfo.cs @@ -1,78 +1,71 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System.Text.Json.Serialization; +using System.Diagnostics.CodeAnalysis; +using Microsoft.AspNetCore.Certificates.Generation; namespace Aspire.Cli.Certificates; /// -/// Represents information about a development certificate from `dotnet dev-certs https --check-trust-machine-readable`. +/// Represents information about an HTTPS development certificate. /// internal sealed class DevCertInfo { - [JsonPropertyName("Thumbprint")] public string? Thumbprint { get; set; } - [JsonPropertyName("Subject")] public string? Subject { get; set; } - [JsonPropertyName("X509SubjectAlternativeNameExtension")] public string[]? SubjectAlternativeNames { get; set; } - [JsonPropertyName("Version")] public int Version { get; set; } - [JsonPropertyName("ValidityNotBefore")] public DateTimeOffset ValidityNotBefore { get; set; } - [JsonPropertyName("ValidityNotAfter")] public DateTimeOffset ValidityNotAfter { get; set; } - [JsonPropertyName("IsHttpsDevelopmentCertificate")] public bool IsHttpsDevelopmentCertificate { get; set; } - [JsonPropertyName("IsExportable")] public bool IsExportable { get; set; } - [JsonPropertyName("TrustLevel")] - public string? TrustLevel { get; set; } + public CertificateManager.TrustLevel TrustLevel { get; set; } } /// -/// Represents the trust level of a development certificate. +/// The result of a certificate clean operation. /// -internal static class DevCertTrustLevel +internal sealed class CertificateCleanResult { /// - /// The certificate is fully trusted by all trust stores. + /// Gets whether the clean operation completed successfully. /// - public const string Full = "Full"; + [MemberNotNullWhen(false, nameof(ErrorMessage))] + public required bool Success { get; init; } /// - /// The certificate is partially trusted (e.g., SSL_CERT_DIR not configured on Linux). + /// Gets whether the operation was cancelled by the user. /// - public const string Partial = "Partial"; + public bool WasCancelled { get; init; } /// - /// The certificate is not trusted. + /// Gets the error message when the operation fails. /// - public const string None = "None"; + public string? ErrorMessage { get; init; } } /// -/// The result of checking certificate trust status using machine-readable output. +/// The result of checking certificate trust status. /// internal sealed class CertificateTrustResult { /// - /// Gets whether any certificate information was returned. + /// Gets whether any valid certificate was found. /// public required bool HasCertificates { get; init; } /// /// Gets the trust level of the highest versioned valid certificate. /// - public required string? TrustLevel { get; init; } + public required CertificateManager.TrustLevel? TrustLevel { get; init; } /// /// Gets all certificate information returned by the check. @@ -82,15 +75,15 @@ internal sealed class CertificateTrustResult /// /// Gets whether the certificate is fully trusted. /// - public bool IsFullyTrusted => string.Equals(TrustLevel, DevCertTrustLevel.Full, StringComparison.OrdinalIgnoreCase); + public bool IsFullyTrusted => TrustLevel == CertificateManager.TrustLevel.Full; /// /// Gets whether the certificate is partially trusted. /// - public bool IsPartiallyTrusted => string.Equals(TrustLevel, DevCertTrustLevel.Partial, StringComparison.OrdinalIgnoreCase); + public bool IsPartiallyTrusted => TrustLevel == CertificateManager.TrustLevel.Partial; /// /// Gets whether the certificate is not trusted at all. /// - public bool IsNotTrusted => !HasCertificates || string.Equals(TrustLevel, DevCertTrustLevel.None, StringComparison.OrdinalIgnoreCase); + public bool IsNotTrusted => !HasCertificates || TrustLevel == CertificateManager.TrustLevel.None; } diff --git a/src/Aspire.Cli/Certificates/ICertificateToolRunner.cs b/src/Aspire.Cli/Certificates/ICertificateToolRunner.cs index 4831ac5d1bf..f800927769e 100644 --- a/src/Aspire.Cli/Certificates/ICertificateToolRunner.cs +++ b/src/Aspire.Cli/Certificates/ICertificateToolRunner.cs @@ -1,7 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using Aspire.Cli.DotNet; +using Microsoft.AspNetCore.Certificates.Generation; namespace Aspire.Cli.Certificates; @@ -11,16 +11,17 @@ namespace Aspire.Cli.Certificates; internal interface ICertificateToolRunner { /// - /// Checks certificate trust status using machine-readable output. + /// Checks certificate trust status, returning structured certificate information. /// - Task<(int ExitCode, CertificateTrustResult? Result)> CheckHttpCertificateMachineReadableAsync( - DotNetCliRunnerInvocationOptions options, - CancellationToken cancellationToken); + CertificateTrustResult CheckHttpCertificate(); /// - /// Trusts the HTTPS development certificate. + /// Trusts the HTTPS development certificate, creating one if necessary. /// - Task TrustHttpCertificateAsync( - DotNetCliRunnerInvocationOptions options, - CancellationToken cancellationToken); + EnsureCertificateResult TrustHttpCertificate(); + + /// + /// Removes all HTTPS development certificates. + /// + CertificateCleanResult CleanHttpCertificate(); } diff --git a/src/Aspire.Cli/Certificates/NativeCertificateToolRunner.cs b/src/Aspire.Cli/Certificates/NativeCertificateToolRunner.cs index beb232f5346..ca9726743c3 100644 --- a/src/Aspire.Cli/Certificates/NativeCertificateToolRunner.cs +++ b/src/Aspire.Cli/Certificates/NativeCertificateToolRunner.cs @@ -1,8 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Security.Cryptography; using System.Security.Cryptography.X509Certificates; -using Aspire.Cli.DotNet; using Microsoft.AspNetCore.Certificates.Generation; namespace Aspire.Cli.Certificates; @@ -10,11 +10,11 @@ namespace Aspire.Cli.Certificates; /// /// Certificate tool runner that uses the native CertificateManager directly (no subprocess needed). /// -internal sealed class NativeCertificateToolRunner(CertificateManager certificateManager) : ICertificateToolRunner +internal sealed class NativeCertificateToolRunner(CertificateManager certificateManager, Func? isLinux = null) : ICertificateToolRunner { - public Task<(int ExitCode, CertificateTrustResult? Result)> CheckHttpCertificateMachineReadableAsync( - DotNetCliRunnerInvocationOptions options, - CancellationToken cancellationToken) + private readonly Func _isLinux = isLinux ?? OperatingSystem.IsLinux; + + public CertificateTrustResult CheckHttpCertificate() { var availableCertificates = certificateManager.ListCertificates( StoreName.My, StoreLocation.CurrentUser, isValid: true); @@ -26,8 +26,8 @@ internal sealed class NativeCertificateToolRunner(CertificateManager certificate { var status = certificateManager.CheckCertificateState(cert); var trustLevel = status.Success - ? certificateManager.GetTrustLevel(cert).ToString() - : DevCertTrustLevel.None; + ? certificateManager.GetTrustLevel(cert) + : CertificateManager.TrustLevel.None; return new DevCertInfo { @@ -50,14 +50,12 @@ internal sealed class NativeCertificateToolRunner(CertificateManager certificate var highestVersionedCert = validCerts.FirstOrDefault(); - var result = new CertificateTrustResult + return new CertificateTrustResult { HasCertificates = validCerts.Count > 0, TrustLevel = highestVersionedCert?.TrustLevel, Certificates = certInfos }; - - return Task.FromResult((0, (CertificateTrustResult?)result)); } finally { @@ -65,24 +63,114 @@ internal sealed class NativeCertificateToolRunner(CertificateManager certificate } } - public Task TrustHttpCertificateAsync( - DotNetCliRunnerInvocationOptions options, - CancellationToken cancellationToken) + public EnsureCertificateResult TrustHttpCertificate() { + if (_isLinux()) + { + var availableCertificates = certificateManager.ListCertificates( + StoreName.My, StoreLocation.CurrentUser, isValid: true); + + try + { + return TrustHttpCertificateOnLinux(availableCertificates, DateTimeOffset.Now); + } + finally + { + CertificateManager.DisposeCertificates(availableCertificates); + } + } + var now = DateTimeOffset.Now; - var result = certificateManager.EnsureAspNetCoreHttpsDevelopmentCertificate( + return certificateManager.EnsureAspNetCoreHttpsDevelopmentCertificate( now, now.Add(TimeSpan.FromDays(365)), trust: true); + } + + internal EnsureCertificateResult TrustHttpCertificateOnLinux(IEnumerable availableCertificates, DateTimeOffset now) + { + X509Certificate2? certificate = null; + var createdCertificate = false; + + try + { + certificate = availableCertificates + .Where(c => c.Subject == certificateManager.Subject && CertificateManager.GetCertificateVersion(c) >= CertificateManager.CurrentAspNetCoreCertificateVersion) + .OrderByDescending(CertificateManager.GetCertificateVersion) + .FirstOrDefault(); + + var successResult = EnsureCertificateResult.ExistingHttpsCertificateTrusted; + + if (certificate is null) + { + try + { + certificate = certificateManager.CreateAspNetCoreHttpsDevelopmentCertificate(now, now.Add(TimeSpan.FromDays(365))); + createdCertificate = true; + } + catch + { + return EnsureCertificateResult.ErrorCreatingTheCertificate; + } + + try + { + certificate = certificateManager.SaveCertificate(certificate); + } + catch + { + return EnsureCertificateResult.ErrorSavingTheCertificateIntoTheCurrentUserPersonalStore; + } + + successResult = EnsureCertificateResult.NewHttpsCertificateTrusted; + } - return Task.FromResult(result switch + try + { + return certificateManager.TrustCertificate(certificate) switch + { + CertificateManager.TrustLevel.Full => successResult, + CertificateManager.TrustLevel.Partial => EnsureCertificateResult.PartiallyFailedToTrustTheCertificate, + _ => EnsureCertificateResult.FailedToTrustTheCertificate + }; + } + catch (CertificateManager.UserCancelledTrustException) + { + return EnsureCertificateResult.UserCancelledTrustStep; + } + catch + { + return EnsureCertificateResult.FailedToTrustTheCertificate; + } + } + finally { - EnsureCertificateResult.Succeeded or - EnsureCertificateResult.ValidCertificatePresent or - EnsureCertificateResult.ExistingHttpsCertificateTrusted or - EnsureCertificateResult.NewHttpsCertificateTrusted => 0, - EnsureCertificateResult.UserCancelledTrustStep => 5, - _ => 4 // ErrorTrustingTheCertificate - }); + if (createdCertificate) + { + certificate?.Dispose(); + } + } + } + + /// Win32 ERROR_CANCELLED (0x4C7) encoded as an HRESULT (0x800704C7). + /// Thrown when the user dismisses the Windows certificate-store security dialog. + private const int UserCancelledHResult = unchecked((int)0x800704C7); + private const int UserCancelledErrorCode = 1223; + + public CertificateCleanResult CleanHttpCertificate() + { + try + { + certificateManager.CleanupHttpsCertificates(); + return new CertificateCleanResult { Success = true }; + } + catch (CryptographicException ex) when (ex.HResult == UserCancelledHResult || ex.HResult == UserCancelledErrorCode) + { + return new CertificateCleanResult { Success = false, WasCancelled = true, ErrorMessage = ex.Message }; + } + catch (Exception ex) + { + return new CertificateCleanResult { Success = false, ErrorMessage = ex.Message }; + } } private static string[]? GetSanExtension(X509Certificate2 cert) diff --git a/src/Aspire.Cli/Commands/CertificatesCleanCommand.cs b/src/Aspire.Cli/Commands/CertificatesCleanCommand.cs new file mode 100644 index 00000000000..4114fec5fa6 --- /dev/null +++ b/src/Aspire.Cli/Commands/CertificatesCleanCommand.cs @@ -0,0 +1,53 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.CommandLine; +using System.Globalization; +using Aspire.Cli.Certificates; +using Aspire.Cli.Configuration; +using Aspire.Cli.Interaction; +using Aspire.Cli.Resources; +using Aspire.Cli.Telemetry; +using Aspire.Cli.Utils; + +namespace Aspire.Cli.Commands; + +/// +/// Subcommand that removes all HTTPS development certificates. +/// +internal sealed class CertificatesCleanCommand : BaseCommand +{ + private readonly ICertificateToolRunner _certificateToolRunner; + + public CertificatesCleanCommand(ICertificateToolRunner certificateToolRunner, IInteractionService interactionService, IFeatures features, ICliUpdateNotifier updateNotifier, CliExecutionContext executionContext, AspireCliTelemetry telemetry) + : base("clean", CertificatesCommandStrings.CleanDescription, features, updateNotifier, executionContext, interactionService, telemetry) + { + _certificateToolRunner = certificateToolRunner; + } + + protected override bool UpdateNotificationsEnabled => false; + + protected override Task ExecuteAsync(ParseResult parseResult, CancellationToken cancellationToken) + { + InteractionService.DisplayMessage(KnownEmojis.Information, CertificatesCommandStrings.CleanProgress); + + var result = _certificateToolRunner.CleanHttpCertificate(); + + if (result.Success) + { + InteractionService.DisplaySuccess(CertificatesCommandStrings.CleanSuccess); + return Task.FromResult(ExitCodeConstants.Success); + } + + if (result.WasCancelled) + { + InteractionService.DisplayMessage(KnownEmojis.Warning, CertificatesCommandStrings.CleanCancelled); + return Task.FromResult(ExitCodeConstants.FailedToTrustCertificates); + } + + var details = string.Format(CultureInfo.CurrentCulture, CertificatesCommandStrings.CleanFailureDetailsFormat, result.ErrorMessage); + InteractionService.DisplayError(details); + InteractionService.DisplayError(CertificatesCommandStrings.CleanFailure); + return Task.FromResult(ExitCodeConstants.FailedToTrustCertificates); + } +} diff --git a/src/Aspire.Cli/Commands/CertificatesCommand.cs b/src/Aspire.Cli/Commands/CertificatesCommand.cs new file mode 100644 index 00000000000..92b4a502f88 --- /dev/null +++ b/src/Aspire.Cli/Commands/CertificatesCommand.cs @@ -0,0 +1,35 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.CommandLine; +using System.CommandLine.Help; +using Aspire.Cli.Configuration; +using Aspire.Cli.Interaction; +using Aspire.Cli.Resources; +using Aspire.Cli.Telemetry; +using Aspire.Cli.Utils; + +namespace Aspire.Cli.Commands; + +internal sealed class CertificatesCommand : BaseCommand +{ + internal override HelpGroup HelpGroup => HelpGroup.ToolsAndConfiguration; + + public CertificatesCommand(CertificatesCleanCommand cleanCommand, CertificatesTrustCommand trustCommand, IInteractionService interactionService, IFeatures features, ICliUpdateNotifier updateNotifier, CliExecutionContext executionContext, AspireCliTelemetry telemetry) + : base("certs", CertificatesCommandStrings.Description, features, updateNotifier, executionContext, interactionService, telemetry) + { + ArgumentNullException.ThrowIfNull(cleanCommand); + ArgumentNullException.ThrowIfNull(trustCommand); + + Subcommands.Add(cleanCommand); + Subcommands.Add(trustCommand); + } + + protected override bool UpdateNotificationsEnabled => false; + + protected override Task ExecuteAsync(ParseResult parseResult, CancellationToken cancellationToken) + { + new HelpAction().Invoke(parseResult); + return Task.FromResult(ExitCodeConstants.InvalidCommand); + } +} diff --git a/src/Aspire.Cli/Commands/CertificatesTrustCommand.cs b/src/Aspire.Cli/Commands/CertificatesTrustCommand.cs new file mode 100644 index 00000000000..ebf413b0693 --- /dev/null +++ b/src/Aspire.Cli/Commands/CertificatesTrustCommand.cs @@ -0,0 +1,54 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.CommandLine; +using System.Globalization; +using Aspire.Cli.Certificates; +using Aspire.Cli.Configuration; +using Aspire.Cli.Interaction; +using Aspire.Cli.Resources; +using Aspire.Cli.Telemetry; +using Aspire.Cli.Utils; +using Microsoft.AspNetCore.Certificates.Generation; + +namespace Aspire.Cli.Commands; + +/// +/// Subcommand that trusts the HTTPS development certificate, creating one if necessary. +/// +internal sealed class CertificatesTrustCommand : BaseCommand +{ + private readonly ICertificateToolRunner _certificateToolRunner; + + public CertificatesTrustCommand(ICertificateToolRunner certificateToolRunner, IInteractionService interactionService, IFeatures features, ICliUpdateNotifier updateNotifier, CliExecutionContext executionContext, AspireCliTelemetry telemetry) + : base("trust", CertificatesCommandStrings.TrustDescription, features, updateNotifier, executionContext, interactionService, telemetry) + { + _certificateToolRunner = certificateToolRunner; + } + + protected override bool UpdateNotificationsEnabled => false; + + protected override Task ExecuteAsync(ParseResult parseResult, CancellationToken cancellationToken) + { + InteractionService.DisplayMessage(KnownEmojis.Information, CertificatesCommandStrings.TrustProgress); + + var result = _certificateToolRunner.TrustHttpCertificate(); + + if (CertificateHelpers.IsSuccessfulTrustResult(result)) + { + InteractionService.DisplaySuccess(CertificatesCommandStrings.TrustSuccess); + return Task.FromResult(ExitCodeConstants.Success); + } + + if (result == EnsureCertificateResult.UserCancelledTrustStep) + { + InteractionService.DisplayMessage(KnownEmojis.Warning, CertificatesCommandStrings.TrustCancelled); + return Task.FromResult(ExitCodeConstants.FailedToTrustCertificates); + } + + var details = string.Format(CultureInfo.CurrentCulture, CertificatesCommandStrings.TrustFailureDetailsFormat, result); + InteractionService.DisplayError(details); + InteractionService.DisplayError(CertificatesCommandStrings.TrustFailure); + return Task.FromResult(ExitCodeConstants.FailedToTrustCertificates); + } +} diff --git a/src/Aspire.Cli/Commands/RootCommand.cs b/src/Aspire.Cli/Commands/RootCommand.cs index 58ce597751f..38b24cf00df 100644 --- a/src/Aspire.Cli/Commands/RootCommand.cs +++ b/src/Aspire.Cli/Commands/RootCommand.cs @@ -123,6 +123,7 @@ public RootCommand( DoCommand doCommand, ConfigCommand configCommand, CacheCommand cacheCommand, + CertificatesCommand certificatesCommand, DoctorCommand doctorCommand, ExecCommand execCommand, UpdateCommand updateCommand, @@ -210,6 +211,7 @@ public RootCommand( Subcommands.Add(publishCommand); Subcommands.Add(configCommand); Subcommands.Add(cacheCommand); + Subcommands.Add(certificatesCommand); Subcommands.Add(doctorCommand); Subcommands.Add(deployCommand); Subcommands.Add(doCommand); diff --git a/src/Aspire.Cli/Commands/RunCommand.cs b/src/Aspire.Cli/Commands/RunCommand.cs index c8a02f12456..6a766f82ec7 100644 --- a/src/Aspire.Cli/Commands/RunCommand.cs +++ b/src/Aspire.Cli/Commands/RunCommand.cs @@ -252,7 +252,7 @@ protected override async Task ExecuteAsync(ParseResult parseResult, Cancell // Now wait for the backchannel to be established var backchannel = await InteractionService.ShowStatusAsync( - isExtensionHost ? InteractionServiceStrings.BuildingAppHost : RunCommandStrings.ConnectingToAppHost, + RunCommandStrings.ConnectingToAppHost, async () => await backchannelCompletionSource.Task.WaitAsync(cancellationToken)); // Set up log capture - writes to unified CLI log file diff --git a/src/Aspire.Cli/DotNet/DotNetCliRunner.cs b/src/Aspire.Cli/DotNet/DotNetCliRunner.cs index 573fd9982ef..2f88d686563 100644 --- a/src/Aspire.Cli/DotNet/DotNetCliRunner.cs +++ b/src/Aspire.Cli/DotNet/DotNetCliRunner.cs @@ -487,94 +487,6 @@ public async Task RunAsync(FileInfo projectFile, bool watch, bool noBuild, cancellationToken: cancellationToken); } - public async Task<(int ExitCode, Certificates.CertificateTrustResult? Result)> CheckHttpCertificateMachineReadableAsync(DotNetCliRunnerInvocationOptions options, CancellationToken cancellationToken) - { - using var activity = telemetry.StartDiagnosticActivity(); - - string[] cliArgs = ["dev-certs", "https", "--check-trust-machine-readable"]; - var outputBuilder = new StringBuilder(); - - // Wrap the callback to capture JSON output - var originalCallback = options.StandardOutputCallback; - options.StandardOutputCallback = line => - { - outputBuilder.AppendLine(line); - originalCallback?.Invoke(line); - }; - - var exitCode = await ExecuteAsync( - args: cliArgs, - env: null, - projectFile: null, - workingDirectory: new DirectoryInfo(Environment.CurrentDirectory), - backchannelCompletionSource: null, - options: options, - cancellationToken: cancellationToken); - - // Parse the JSON output - try - { - var jsonOutput = outputBuilder.ToString().Trim(); - if (string.IsNullOrEmpty(jsonOutput)) - { - return (exitCode, new Certificates.CertificateTrustResult - { - HasCertificates = false, - TrustLevel = null, - Certificates = [] - }); - } - - var certificates = JsonSerializer.Deserialize(jsonOutput, JsonSourceGenerationContext.Default.ListDevCertInfo); - if (certificates is null || certificates.Count == 0) - { - return (exitCode, new Certificates.CertificateTrustResult - { - HasCertificates = false, - TrustLevel = null, - Certificates = [] - }); - } - - // Find the highest versioned valid certificate - var now = DateTimeOffset.Now; - var validCertificates = certificates - .Where(c => c.IsHttpsDevelopmentCertificate && c.ValidityNotBefore <= now && now <= c.ValidityNotAfter) - .OrderByDescending(c => c.Version) - .ToList(); - - var highestVersionedCert = validCertificates.FirstOrDefault(); - var trustLevel = highestVersionedCert?.TrustLevel; - - return (exitCode, new Certificates.CertificateTrustResult - { - HasCertificates = validCertificates.Count > 0, - TrustLevel = trustLevel, - Certificates = certificates - }); - } - catch (JsonException ex) - { - logger.LogDebug(ex, "Failed to parse dev-certs machine-readable output"); - return (exitCode, null); - } - } - - public async Task TrustHttpCertificateAsync(DotNetCliRunnerInvocationOptions options, CancellationToken cancellationToken) - { - using var activity = telemetry.StartDiagnosticActivity(); - - string[] cliArgs = ["dev-certs", "https", "--trust"]; - return await ExecuteAsync( - args: cliArgs, - env: null, - projectFile: null, - workingDirectory: new DirectoryInfo(Environment.CurrentDirectory), - backchannelCompletionSource: null, - options: options, - cancellationToken: cancellationToken); - } - public async Task<(int ExitCode, string? TemplateVersion)> InstallTemplateAsync(string packageName, string version, FileInfo? nugetConfigFile, string? nugetSource, bool force, DotNetCliRunnerInvocationOptions options, CancellationToken cancellationToken) { using var activity = telemetry.StartDiagnosticActivity(kind: ActivityKind.Client); diff --git a/src/Aspire.Cli/Interaction/BannerService.cs b/src/Aspire.Cli/Interaction/BannerService.cs index 6183ceae371..0478917643c 100644 --- a/src/Aspire.Cli/Interaction/BannerService.cs +++ b/src/Aspire.Cli/Interaction/BannerService.cs @@ -51,6 +51,14 @@ public BannerService(ConsoleEnvironment consoleEnvironment) public async Task DisplayBannerAsync(CancellationToken cancellationToken = default) { var cliVersion = VersionHelper.GetDefaultTemplateVersion(); + + // Strip build metadata (everything after '+') for display purposes. + var plusIndex = cliVersion.IndexOf('+', StringComparison.Ordinal); + if (plusIndex >= 0) + { + cliVersion = cliVersion[..plusIndex]; + } + var aspireWidth = s_aspireLines[0].TrimEnd().Length; var welcomeText = RootCommandStrings.BannerWelcomeText; var versionText = string.Format(CultureInfo.CurrentCulture, RootCommandStrings.BannerVersionFormat, cliVersion); diff --git a/src/Aspire.Cli/JsonSourceGenerationContext.cs b/src/Aspire.Cli/JsonSourceGenerationContext.cs index ced45b42cb0..7fc4f8abb4a 100644 --- a/src/Aspire.Cli/JsonSourceGenerationContext.cs +++ b/src/Aspire.Cli/JsonSourceGenerationContext.cs @@ -5,7 +5,6 @@ using System.Text.Json; using System.Text.Json.Serialization; using System.Text.Json.Nodes; -using Aspire.Cli.Certificates; using Aspire.Cli.Commands; using Aspire.Cli.Configuration; using Aspire.Cli.Mcp.Docs; @@ -24,7 +23,6 @@ namespace Aspire.Cli; [JsonSerializable(typeof(DoctorCheckSummary))] [JsonSerializable(typeof(ContainerVersionJson))] [JsonSerializable(typeof(AspireJsonConfiguration))] -[JsonSerializable(typeof(List))] [JsonSerializable(typeof(ConfigInfo))] [JsonSerializable(typeof(FeatureInfo))] [JsonSerializable(typeof(SettingsSchema))] diff --git a/src/Aspire.Cli/Program.cs b/src/Aspire.Cli/Program.cs index 144be108dd5..81b5c1d6bba 100644 --- a/src/Aspire.Cli/Program.cs +++ b/src/Aspire.Cli/Program.cs @@ -380,6 +380,9 @@ internal static async Task BuildApplicationAsync(string[] args, Dictionar builder.Services.AddTransient(); builder.Services.AddTransient(); builder.Services.AddTransient(); + builder.Services.AddTransient(); + builder.Services.AddTransient(); + builder.Services.AddTransient(); builder.Services.AddTransient(); builder.Services.AddTransient(); builder.Services.AddTransient(); diff --git a/src/Aspire.Cli/Projects/GuestAppHostProject.cs b/src/Aspire.Cli/Projects/GuestAppHostProject.cs index 032470d5cec..8b1ed3a14f8 100644 --- a/src/Aspire.Cli/Projects/GuestAppHostProject.cs +++ b/src/Aspire.Cli/Projects/GuestAppHostProject.cs @@ -25,7 +25,7 @@ namespace Aspire.Cli.Projects; /// Handler for guest (non-.NET) AppHost projects. /// Supports any language registered via . /// -internal sealed class GuestAppHostProject : IAppHostProject +internal sealed class GuestAppHostProject : IAppHostProject, IGuestAppHostSdkGenerator { private const string GeneratedFolderName = ".modules"; @@ -244,6 +244,11 @@ await GenerateCodeViaRpcAsync( } } + Task IGuestAppHostSdkGenerator.BuildAndGenerateSdkAsync(DirectoryInfo directory, CancellationToken cancellationToken) + { + return BuildAndGenerateSdkAsync(directory, cancellationToken); + } + // ═══════════════════════════════════════════════════════════════ // EXECUTION // ═══════════════════════════════════════════════════════════════ diff --git a/src/Aspire.Cli/Projects/IGuestAppHostSdkGenerator.cs b/src/Aspire.Cli/Projects/IGuestAppHostSdkGenerator.cs new file mode 100644 index 00000000000..ba89749d4c7 --- /dev/null +++ b/src/Aspire.Cli/Projects/IGuestAppHostSdkGenerator.cs @@ -0,0 +1,18 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace Aspire.Cli.Projects; + +/// +/// Generates SDK artifacts for a guest AppHost project. +/// +internal interface IGuestAppHostSdkGenerator +{ + /// + /// Builds any required server components and generates guest SDK artifacts. + /// + /// The AppHost project directory. + /// A cancellation token. + /// if SDK generation succeeded; otherwise, . + Task BuildAndGenerateSdkAsync(DirectoryInfo directory, CancellationToken cancellationToken); +} \ No newline at end of file diff --git a/src/Aspire.Cli/Projects/ProjectLocator.cs b/src/Aspire.Cli/Projects/ProjectLocator.cs index 07f7e3216e4..89d3d582402 100644 --- a/src/Aspire.Cli/Projects/ProjectLocator.cs +++ b/src/Aspire.Cli/Projects/ProjectLocator.cs @@ -19,6 +19,13 @@ internal interface IProjectLocator { Task UseOrFindAppHostProjectFileAsync(FileInfo? projectFile, MultipleAppHostProjectsFoundBehavior multipleAppHostProjectsFoundBehavior, bool createSettingsFile, CancellationToken cancellationToken = default); Task UseOrFindAppHostProjectFileAsync(FileInfo? projectFile, bool createSettingsFile, CancellationToken cancellationToken); + + /// + /// Resolves the AppHost project file from .aspire/settings.json only, without any + /// user interaction or recursive filesystem scanning. Returns null when no settings + /// file or appHostPath entry is found. + /// + Task GetAppHostFromSettingsAsync(CancellationToken cancellationToken = default); } internal sealed class ProjectLocator( @@ -152,7 +159,18 @@ await Parallel.ForEachAsync(candidatesWithHandlers, parallelOptions, async (cand }); } + /// + public async Task GetAppHostFromSettingsAsync(CancellationToken cancellationToken = default) + { + return await GetAppHostProjectFileFromSettingsAsync(silent: true, cancellationToken); + } + private async Task GetAppHostProjectFileFromSettingsAsync(CancellationToken cancellationToken) + { + return await GetAppHostProjectFileFromSettingsAsync(silent: false, cancellationToken); + } + + private async Task GetAppHostProjectFileFromSettingsAsync(bool silent, CancellationToken cancellationToken) { var searchDirectory = executionContext.WorkingDirectory; @@ -178,7 +196,10 @@ await Parallel.ForEachAsync(candidatesWithHandlers, parallelOptions, async (cand else { // AppHost file was specified but doesn't exist, return null to trigger fallback logic - interactionService.DisplayMessage(KnownEmojis.Warning, string.Format(CultureInfo.CurrentCulture, ErrorStrings.AppHostWasSpecifiedButDoesntExist, settingsFile.FullName, qualifiedAppHostPath)); + if (!silent) + { + interactionService.DisplayMessage(KnownEmojis.Warning, string.Format(CultureInfo.CurrentCulture, ErrorStrings.AppHostWasSpecifiedButDoesntExist, settingsFile.FullName, qualifiedAppHostPath)); + } return null; } } diff --git a/src/Aspire.Cli/Resources/CertificatesCommandStrings.Designer.cs b/src/Aspire.Cli/Resources/CertificatesCommandStrings.Designer.cs new file mode 100644 index 00000000000..dbc6a1ba27a --- /dev/null +++ b/src/Aspire.Cli/Resources/CertificatesCommandStrings.Designer.cs @@ -0,0 +1,176 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Aspire.Cli.Resources { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the MSBuild WriteCodeFragment class. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class CertificatesCommandStrings { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal CertificatesCommandStrings() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Aspire.Cli.Resources.CertificatesCommandStrings", typeof(CertificatesCommandStrings).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized string similar to Failed to clean HTTPS development certificates.. + /// + internal static string CleanFailure { + get { + return ResourceManager.GetString("CleanFailure", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Certificate clean operation failed: {0}. + /// + internal static string CleanFailureDetailsFormat { + get { + return ResourceManager.GetString("CleanFailureDetailsFormat", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Certificate clean operation was cancelled by the user.. + /// + internal static string CleanCancelled { + get { + return ResourceManager.GetString("CleanCancelled", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Remove all HTTPS development certificates.. + /// + internal static string CleanDescription { + get { + return ResourceManager.GetString("CleanDescription", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Cleaning development certificates (may require elevated permissions).... + /// + internal static string CleanProgress { + get { + return ResourceManager.GetString("CleanProgress", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to All HTTPS development certificates cleaned successfully.. + /// + internal static string CleanSuccess { + get { + return ResourceManager.GetString("CleanSuccess", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Manage HTTPS development certificates.. + /// + internal static string Description { + get { + return ResourceManager.GetString("Description", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Trust the HTTPS development certificate, creating one if necessary.. + /// + internal static string TrustDescription { + get { + return ResourceManager.GetString("TrustDescription", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Certificate trust operation was cancelled by the user.. + /// + internal static string TrustCancelled { + get { + return ResourceManager.GetString("TrustCancelled", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Failed to trust HTTPS development certificate.. + /// + internal static string TrustFailure { + get { + return ResourceManager.GetString("TrustFailure", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Certificate trust operation returned: {0}. + /// + internal static string TrustFailureDetailsFormat { + get { + return ResourceManager.GetString("TrustFailureDetailsFormat", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Trusting development certificate (may require elevated permissions).... + /// + internal static string TrustProgress { + get { + return ResourceManager.GetString("TrustProgress", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to HTTPS development certificate trusted successfully.. + /// + internal static string TrustSuccess { + get { + return ResourceManager.GetString("TrustSuccess", resourceCulture); + } + } + } +} diff --git a/src/Aspire.Cli/Resources/CertificatesCommandStrings.resx b/src/Aspire.Cli/Resources/CertificatesCommandStrings.resx new file mode 100644 index 00000000000..7242ee0d2d2 --- /dev/null +++ b/src/Aspire.Cli/Resources/CertificatesCommandStrings.resx @@ -0,0 +1,104 @@ + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Manage HTTPS development certificates. + + + Remove all HTTPS development certificates. + + + Certificate clean operation was cancelled by the user. + + + Trust the HTTPS development certificate, creating one if necessary. + + + Cleaning development certificates (may require elevated permissions)... + + + Trusting development certificate (may require elevated permissions)... + + + All HTTPS development certificates cleaned successfully. + + + HTTPS development certificate trusted successfully. + + + Failed to clean HTTPS development certificates. + + + Certificate clean operation failed: {0} + {0} is the error message from the failed operation + + + Certificate trust operation was cancelled by the user. + + + Failed to trust HTTPS development certificate. + + + Certificate trust operation returned: {0} + {0} is the EnsureCertificateResult value + + diff --git a/src/Aspire.Cli/Resources/DoctorCommandStrings.Designer.cs b/src/Aspire.Cli/Resources/DoctorCommandStrings.Designer.cs index e6e7591596b..c3601097b49 100644 --- a/src/Aspire.Cli/Resources/DoctorCommandStrings.Designer.cs +++ b/src/Aspire.Cli/Resources/DoctorCommandStrings.Designer.cs @@ -139,5 +139,167 @@ public static string CheckingPrerequisites { return ResourceManager.GetString("CheckingPrerequisites", resourceCulture); } } + + /// + /// Looks up a localized string similar to No HTTPS development certificate found. + /// + public static string DevCertsNoCertificateMessage { + get { + return ResourceManager.GetString("DevCertsNoCertificateMessage", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Aspire uses HTTPS for secure communication between the dashboard and your services during local development.. + /// + public static string DevCertsNoCertificateDetails { + get { + return ResourceManager.GetString("DevCertsNoCertificateDetails", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Run '{0}' to trust the HTTPS development certificate.. + /// + public static string DevCertsTrustFixFormat { + get { + return ResourceManager.GetString("DevCertsTrustFixFormat", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Run '{0}' to remove all certificates, then run '{1}' to create and trust a new one.. + /// + public static string DevCertsCleanAndTrustFixFormat { + get { + return ResourceManager.GetString("DevCertsCleanAndTrustFixFormat", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Multiple HTTPS development certificates found ({0} certificates), but none are trusted. + /// + public static string DevCertsMultipleNoneTrustedMessageFormat { + get { + return ResourceManager.GetString("DevCertsMultipleNoneTrustedMessageFormat", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Found certificates: {0}. Having multiple certificates can cause confusion.. + /// + public static string DevCertsMultipleNoneTrustedDetailsFormat { + get { + return ResourceManager.GetString("DevCertsMultipleNoneTrustedDetailsFormat", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Multiple HTTPS development certificates found ({0} certificates). + /// + public static string DevCertsMultipleSomeUntrustedMessageFormat { + get { + return ResourceManager.GetString("DevCertsMultipleSomeUntrustedMessageFormat", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Found certificates: {0}. Having multiple certificates can cause confusion when selecting which one to use.. + /// + public static string DevCertsMultipleSomeUntrustedDetailsFormat { + get { + return ResourceManager.GetString("DevCertsMultipleSomeUntrustedDetailsFormat", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to HTTPS development certificate is trusted. + /// + public static string DevCertsTrustedMessage { + get { + return ResourceManager.GetString("DevCertsTrustedMessage", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to HTTPS development certificate is not trusted. + /// + public static string DevCertsNotTrustedMessage { + get { + return ResourceManager.GetString("DevCertsNotTrustedMessage", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Certificate {0} exists in the personal store but was not found in the trusted root store.. + /// + public static string DevCertsNotTrustedDetailsFormat { + get { + return ResourceManager.GetString("DevCertsNotTrustedDetailsFormat", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to HTTPS development certificate is only partially trusted. + /// + public static string DevCertsPartiallyTrustedMessage { + get { + return ResourceManager.GetString("DevCertsPartiallyTrustedMessage", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The certificate is in the trusted store, but SSL_CERT_DIR is not configured to include '{0}'. Some applications may not trust the certificate. 'aspire run' will configure this automatically.. + /// + public static string DevCertsPartiallyTrustedDetailsFormat { + get { + return ResourceManager.GetString("DevCertsPartiallyTrustedDetailsFormat", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Set SSL_CERT_DIR in your shell profile: {0}. + /// + public static string DevCertsPartiallyTrustedFixFormat { + get { + return ResourceManager.GetString("DevCertsPartiallyTrustedFixFormat", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to HTTPS development certificate has an older version ({0}). + /// + public static string DevCertsOldVersionMessageFormat { + get { + return ResourceManager.GetString("DevCertsOldVersionMessageFormat", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Older certificate versions (< v{0}) may not support container trust scenarios.. + /// + public static string DevCertsOldVersionDetailsFormat { + get { + return ResourceManager.GetString("DevCertsOldVersionDetailsFormat", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [trusted]. + /// + public static string DevCertsTrustLabelFull { + get { + return ResourceManager.GetString("DevCertsTrustLabelFull", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [partial]. + /// + public static string DevCertsTrustLabelPartial { + get { + return ResourceManager.GetString("DevCertsTrustLabelPartial", resourceCulture); + } + } } } diff --git a/src/Aspire.Cli/Resources/DoctorCommandStrings.resx b/src/Aspire.Cli/Resources/DoctorCommandStrings.resx index 79923adbf16..93112cfcb8d 100644 --- a/src/Aspire.Cli/Resources/DoctorCommandStrings.resx +++ b/src/Aspire.Cli/Resources/DoctorCommandStrings.resx @@ -85,4 +85,60 @@ Checking Aspire environment... + + No HTTPS development certificate found + + + Aspire uses HTTPS for secure communication between the dashboard and your services during local development. + + + Run '{0}' to trust the HTTPS development certificate. + {0} is the aspire certs trust command (not localizable) + + + Run '{0}' to remove all certificates, then run '{1}' to create and trust a new one. + {0} is the aspire certs clean command, {1} is the aspire certs trust command (not localizable) + + + Multiple HTTPS development certificates found ({0} certificates), but none are trusted + + + Found certificates: {0}. Having multiple certificates can cause confusion. + + + Multiple HTTPS development certificates found ({0} certificates) + + + Found certificates: {0}. Having multiple certificates can cause confusion when selecting which one to use. + + + HTTPS development certificate is trusted + + + HTTPS development certificate is not trusted + + + Certificate {0} exists in the personal store but was not found in the trusted root store. + + + HTTPS development certificate is only partially trusted + + + The certificate is in the trusted store, but SSL_CERT_DIR is not configured to include '{0}'. Some applications may not trust the certificate. 'aspire run' will configure this automatically. + + + Set SSL_CERT_DIR in your shell profile: {0} + + + HTTPS development certificate has an older version ({0}) + + + Older certificate versions (< v{0}) may not support container trust scenarios. + + + [trusted] + + + [partial] + diff --git a/src/Aspire.Cli/Resources/xlf/CertificatesCommandStrings.cs.xlf b/src/Aspire.Cli/Resources/xlf/CertificatesCommandStrings.cs.xlf new file mode 100644 index 00000000000..42dced80d2d --- /dev/null +++ b/src/Aspire.Cli/Resources/xlf/CertificatesCommandStrings.cs.xlf @@ -0,0 +1,72 @@ + + + + + + Certificate clean operation was cancelled by the user. + Certificate clean operation was cancelled by the user. + + + + Remove all HTTPS development certificates. + Remove all HTTPS development certificates. + + + + Failed to clean HTTPS development certificates. + Failed to clean HTTPS development certificates. + + + + Certificate clean operation failed: {0} + Certificate clean operation failed: {0} + {0} is the error message from the failed operation + + + Cleaning development certificates (may require elevated permissions)... + Cleaning development certificates (may require elevated permissions)... + + + + All HTTPS development certificates cleaned successfully. + All HTTPS development certificates cleaned successfully. + + + + Manage HTTPS development certificates. + Manage HTTPS development certificates. + + + + Certificate trust operation was cancelled by the user. + Certificate trust operation was cancelled by the user. + + + + Trust the HTTPS development certificate, creating one if necessary. + Trust the HTTPS development certificate, creating one if necessary. + + + + Failed to trust HTTPS development certificate. + Failed to trust HTTPS development certificate. + + + + Certificate trust operation returned: {0} + Certificate trust operation returned: {0} + {0} is the EnsureCertificateResult value + + + Trusting development certificate (may require elevated permissions)... + Trusting development certificate (may require elevated permissions)... + + + + HTTPS development certificate trusted successfully. + HTTPS development certificate trusted successfully. + + + + + \ No newline at end of file diff --git a/src/Aspire.Cli/Resources/xlf/CertificatesCommandStrings.de.xlf b/src/Aspire.Cli/Resources/xlf/CertificatesCommandStrings.de.xlf new file mode 100644 index 00000000000..6fef8e31725 --- /dev/null +++ b/src/Aspire.Cli/Resources/xlf/CertificatesCommandStrings.de.xlf @@ -0,0 +1,72 @@ + + + + + + Certificate clean operation was cancelled by the user. + Certificate clean operation was cancelled by the user. + + + + Remove all HTTPS development certificates. + Remove all HTTPS development certificates. + + + + Failed to clean HTTPS development certificates. + Failed to clean HTTPS development certificates. + + + + Certificate clean operation failed: {0} + Certificate clean operation failed: {0} + {0} is the error message from the failed operation + + + Cleaning development certificates (may require elevated permissions)... + Cleaning development certificates (may require elevated permissions)... + + + + All HTTPS development certificates cleaned successfully. + All HTTPS development certificates cleaned successfully. + + + + Manage HTTPS development certificates. + Manage HTTPS development certificates. + + + + Certificate trust operation was cancelled by the user. + Certificate trust operation was cancelled by the user. + + + + Trust the HTTPS development certificate, creating one if necessary. + Trust the HTTPS development certificate, creating one if necessary. + + + + Failed to trust HTTPS development certificate. + Failed to trust HTTPS development certificate. + + + + Certificate trust operation returned: {0} + Certificate trust operation returned: {0} + {0} is the EnsureCertificateResult value + + + Trusting development certificate (may require elevated permissions)... + Trusting development certificate (may require elevated permissions)... + + + + HTTPS development certificate trusted successfully. + HTTPS development certificate trusted successfully. + + + + + \ No newline at end of file diff --git a/src/Aspire.Cli/Resources/xlf/CertificatesCommandStrings.es.xlf b/src/Aspire.Cli/Resources/xlf/CertificatesCommandStrings.es.xlf new file mode 100644 index 00000000000..d052b8a2c69 --- /dev/null +++ b/src/Aspire.Cli/Resources/xlf/CertificatesCommandStrings.es.xlf @@ -0,0 +1,72 @@ + + + + + + Certificate clean operation was cancelled by the user. + Certificate clean operation was cancelled by the user. + + + + Remove all HTTPS development certificates. + Remove all HTTPS development certificates. + + + + Failed to clean HTTPS development certificates. + Failed to clean HTTPS development certificates. + + + + Certificate clean operation failed: {0} + Certificate clean operation failed: {0} + {0} is the error message from the failed operation + + + Cleaning development certificates (may require elevated permissions)... + Cleaning development certificates (may require elevated permissions)... + + + + All HTTPS development certificates cleaned successfully. + All HTTPS development certificates cleaned successfully. + + + + Manage HTTPS development certificates. + Manage HTTPS development certificates. + + + + Certificate trust operation was cancelled by the user. + Certificate trust operation was cancelled by the user. + + + + Trust the HTTPS development certificate, creating one if necessary. + Trust the HTTPS development certificate, creating one if necessary. + + + + Failed to trust HTTPS development certificate. + Failed to trust HTTPS development certificate. + + + + Certificate trust operation returned: {0} + Certificate trust operation returned: {0} + {0} is the EnsureCertificateResult value + + + Trusting development certificate (may require elevated permissions)... + Trusting development certificate (may require elevated permissions)... + + + + HTTPS development certificate trusted successfully. + HTTPS development certificate trusted successfully. + + + + + \ No newline at end of file diff --git a/src/Aspire.Cli/Resources/xlf/CertificatesCommandStrings.fr.xlf b/src/Aspire.Cli/Resources/xlf/CertificatesCommandStrings.fr.xlf new file mode 100644 index 00000000000..5dd6680720e --- /dev/null +++ b/src/Aspire.Cli/Resources/xlf/CertificatesCommandStrings.fr.xlf @@ -0,0 +1,72 @@ + + + + + + Certificate clean operation was cancelled by the user. + Certificate clean operation was cancelled by the user. + + + + Remove all HTTPS development certificates. + Remove all HTTPS development certificates. + + + + Failed to clean HTTPS development certificates. + Failed to clean HTTPS development certificates. + + + + Certificate clean operation failed: {0} + Certificate clean operation failed: {0} + {0} is the error message from the failed operation + + + Cleaning development certificates (may require elevated permissions)... + Cleaning development certificates (may require elevated permissions)... + + + + All HTTPS development certificates cleaned successfully. + All HTTPS development certificates cleaned successfully. + + + + Manage HTTPS development certificates. + Manage HTTPS development certificates. + + + + Certificate trust operation was cancelled by the user. + Certificate trust operation was cancelled by the user. + + + + Trust the HTTPS development certificate, creating one if necessary. + Trust the HTTPS development certificate, creating one if necessary. + + + + Failed to trust HTTPS development certificate. + Failed to trust HTTPS development certificate. + + + + Certificate trust operation returned: {0} + Certificate trust operation returned: {0} + {0} is the EnsureCertificateResult value + + + Trusting development certificate (may require elevated permissions)... + Trusting development certificate (may require elevated permissions)... + + + + HTTPS development certificate trusted successfully. + HTTPS development certificate trusted successfully. + + + + + \ No newline at end of file diff --git a/src/Aspire.Cli/Resources/xlf/CertificatesCommandStrings.it.xlf b/src/Aspire.Cli/Resources/xlf/CertificatesCommandStrings.it.xlf new file mode 100644 index 00000000000..14657d019f1 --- /dev/null +++ b/src/Aspire.Cli/Resources/xlf/CertificatesCommandStrings.it.xlf @@ -0,0 +1,72 @@ + + + + + + Certificate clean operation was cancelled by the user. + Certificate clean operation was cancelled by the user. + + + + Remove all HTTPS development certificates. + Remove all HTTPS development certificates. + + + + Failed to clean HTTPS development certificates. + Failed to clean HTTPS development certificates. + + + + Certificate clean operation failed: {0} + Certificate clean operation failed: {0} + {0} is the error message from the failed operation + + + Cleaning development certificates (may require elevated permissions)... + Cleaning development certificates (may require elevated permissions)... + + + + All HTTPS development certificates cleaned successfully. + All HTTPS development certificates cleaned successfully. + + + + Manage HTTPS development certificates. + Manage HTTPS development certificates. + + + + Certificate trust operation was cancelled by the user. + Certificate trust operation was cancelled by the user. + + + + Trust the HTTPS development certificate, creating one if necessary. + Trust the HTTPS development certificate, creating one if necessary. + + + + Failed to trust HTTPS development certificate. + Failed to trust HTTPS development certificate. + + + + Certificate trust operation returned: {0} + Certificate trust operation returned: {0} + {0} is the EnsureCertificateResult value + + + Trusting development certificate (may require elevated permissions)... + Trusting development certificate (may require elevated permissions)... + + + + HTTPS development certificate trusted successfully. + HTTPS development certificate trusted successfully. + + + + + \ No newline at end of file diff --git a/src/Aspire.Cli/Resources/xlf/CertificatesCommandStrings.ja.xlf b/src/Aspire.Cli/Resources/xlf/CertificatesCommandStrings.ja.xlf new file mode 100644 index 00000000000..0fc1d3521e1 --- /dev/null +++ b/src/Aspire.Cli/Resources/xlf/CertificatesCommandStrings.ja.xlf @@ -0,0 +1,72 @@ + + + + + + Certificate clean operation was cancelled by the user. + Certificate clean operation was cancelled by the user. + + + + Remove all HTTPS development certificates. + Remove all HTTPS development certificates. + + + + Failed to clean HTTPS development certificates. + Failed to clean HTTPS development certificates. + + + + Certificate clean operation failed: {0} + Certificate clean operation failed: {0} + {0} is the error message from the failed operation + + + Cleaning development certificates (may require elevated permissions)... + Cleaning development certificates (may require elevated permissions)... + + + + All HTTPS development certificates cleaned successfully. + All HTTPS development certificates cleaned successfully. + + + + Manage HTTPS development certificates. + Manage HTTPS development certificates. + + + + Certificate trust operation was cancelled by the user. + Certificate trust operation was cancelled by the user. + + + + Trust the HTTPS development certificate, creating one if necessary. + Trust the HTTPS development certificate, creating one if necessary. + + + + Failed to trust HTTPS development certificate. + Failed to trust HTTPS development certificate. + + + + Certificate trust operation returned: {0} + Certificate trust operation returned: {0} + {0} is the EnsureCertificateResult value + + + Trusting development certificate (may require elevated permissions)... + Trusting development certificate (may require elevated permissions)... + + + + HTTPS development certificate trusted successfully. + HTTPS development certificate trusted successfully. + + + + + \ No newline at end of file diff --git a/src/Aspire.Cli/Resources/xlf/CertificatesCommandStrings.ko.xlf b/src/Aspire.Cli/Resources/xlf/CertificatesCommandStrings.ko.xlf new file mode 100644 index 00000000000..2291f85bd44 --- /dev/null +++ b/src/Aspire.Cli/Resources/xlf/CertificatesCommandStrings.ko.xlf @@ -0,0 +1,72 @@ + + + + + + Certificate clean operation was cancelled by the user. + Certificate clean operation was cancelled by the user. + + + + Remove all HTTPS development certificates. + Remove all HTTPS development certificates. + + + + Failed to clean HTTPS development certificates. + Failed to clean HTTPS development certificates. + + + + Certificate clean operation failed: {0} + Certificate clean operation failed: {0} + {0} is the error message from the failed operation + + + Cleaning development certificates (may require elevated permissions)... + Cleaning development certificates (may require elevated permissions)... + + + + All HTTPS development certificates cleaned successfully. + All HTTPS development certificates cleaned successfully. + + + + Manage HTTPS development certificates. + Manage HTTPS development certificates. + + + + Certificate trust operation was cancelled by the user. + Certificate trust operation was cancelled by the user. + + + + Trust the HTTPS development certificate, creating one if necessary. + Trust the HTTPS development certificate, creating one if necessary. + + + + Failed to trust HTTPS development certificate. + Failed to trust HTTPS development certificate. + + + + Certificate trust operation returned: {0} + Certificate trust operation returned: {0} + {0} is the EnsureCertificateResult value + + + Trusting development certificate (may require elevated permissions)... + Trusting development certificate (may require elevated permissions)... + + + + HTTPS development certificate trusted successfully. + HTTPS development certificate trusted successfully. + + + + + \ No newline at end of file diff --git a/src/Aspire.Cli/Resources/xlf/CertificatesCommandStrings.pl.xlf b/src/Aspire.Cli/Resources/xlf/CertificatesCommandStrings.pl.xlf new file mode 100644 index 00000000000..448100b79a7 --- /dev/null +++ b/src/Aspire.Cli/Resources/xlf/CertificatesCommandStrings.pl.xlf @@ -0,0 +1,72 @@ + + + + + + Certificate clean operation was cancelled by the user. + Certificate clean operation was cancelled by the user. + + + + Remove all HTTPS development certificates. + Remove all HTTPS development certificates. + + + + Failed to clean HTTPS development certificates. + Failed to clean HTTPS development certificates. + + + + Certificate clean operation failed: {0} + Certificate clean operation failed: {0} + {0} is the error message from the failed operation + + + Cleaning development certificates (may require elevated permissions)... + Cleaning development certificates (may require elevated permissions)... + + + + All HTTPS development certificates cleaned successfully. + All HTTPS development certificates cleaned successfully. + + + + Manage HTTPS development certificates. + Manage HTTPS development certificates. + + + + Certificate trust operation was cancelled by the user. + Certificate trust operation was cancelled by the user. + + + + Trust the HTTPS development certificate, creating one if necessary. + Trust the HTTPS development certificate, creating one if necessary. + + + + Failed to trust HTTPS development certificate. + Failed to trust HTTPS development certificate. + + + + Certificate trust operation returned: {0} + Certificate trust operation returned: {0} + {0} is the EnsureCertificateResult value + + + Trusting development certificate (may require elevated permissions)... + Trusting development certificate (may require elevated permissions)... + + + + HTTPS development certificate trusted successfully. + HTTPS development certificate trusted successfully. + + + + + \ No newline at end of file diff --git a/src/Aspire.Cli/Resources/xlf/CertificatesCommandStrings.pt-BR.xlf b/src/Aspire.Cli/Resources/xlf/CertificatesCommandStrings.pt-BR.xlf new file mode 100644 index 00000000000..2ea9442cc7b --- /dev/null +++ b/src/Aspire.Cli/Resources/xlf/CertificatesCommandStrings.pt-BR.xlf @@ -0,0 +1,72 @@ + + + + + + Certificate clean operation was cancelled by the user. + Certificate clean operation was cancelled by the user. + + + + Remove all HTTPS development certificates. + Remove all HTTPS development certificates. + + + + Failed to clean HTTPS development certificates. + Failed to clean HTTPS development certificates. + + + + Certificate clean operation failed: {0} + Certificate clean operation failed: {0} + {0} is the error message from the failed operation + + + Cleaning development certificates (may require elevated permissions)... + Cleaning development certificates (may require elevated permissions)... + + + + All HTTPS development certificates cleaned successfully. + All HTTPS development certificates cleaned successfully. + + + + Manage HTTPS development certificates. + Manage HTTPS development certificates. + + + + Certificate trust operation was cancelled by the user. + Certificate trust operation was cancelled by the user. + + + + Trust the HTTPS development certificate, creating one if necessary. + Trust the HTTPS development certificate, creating one if necessary. + + + + Failed to trust HTTPS development certificate. + Failed to trust HTTPS development certificate. + + + + Certificate trust operation returned: {0} + Certificate trust operation returned: {0} + {0} is the EnsureCertificateResult value + + + Trusting development certificate (may require elevated permissions)... + Trusting development certificate (may require elevated permissions)... + + + + HTTPS development certificate trusted successfully. + HTTPS development certificate trusted successfully. + + + + + \ No newline at end of file diff --git a/src/Aspire.Cli/Resources/xlf/CertificatesCommandStrings.ru.xlf b/src/Aspire.Cli/Resources/xlf/CertificatesCommandStrings.ru.xlf new file mode 100644 index 00000000000..beb8803597d --- /dev/null +++ b/src/Aspire.Cli/Resources/xlf/CertificatesCommandStrings.ru.xlf @@ -0,0 +1,72 @@ + + + + + + Certificate clean operation was cancelled by the user. + Certificate clean operation was cancelled by the user. + + + + Remove all HTTPS development certificates. + Remove all HTTPS development certificates. + + + + Failed to clean HTTPS development certificates. + Failed to clean HTTPS development certificates. + + + + Certificate clean operation failed: {0} + Certificate clean operation failed: {0} + {0} is the error message from the failed operation + + + Cleaning development certificates (may require elevated permissions)... + Cleaning development certificates (may require elevated permissions)... + + + + All HTTPS development certificates cleaned successfully. + All HTTPS development certificates cleaned successfully. + + + + Manage HTTPS development certificates. + Manage HTTPS development certificates. + + + + Certificate trust operation was cancelled by the user. + Certificate trust operation was cancelled by the user. + + + + Trust the HTTPS development certificate, creating one if necessary. + Trust the HTTPS development certificate, creating one if necessary. + + + + Failed to trust HTTPS development certificate. + Failed to trust HTTPS development certificate. + + + + Certificate trust operation returned: {0} + Certificate trust operation returned: {0} + {0} is the EnsureCertificateResult value + + + Trusting development certificate (may require elevated permissions)... + Trusting development certificate (may require elevated permissions)... + + + + HTTPS development certificate trusted successfully. + HTTPS development certificate trusted successfully. + + + + + \ No newline at end of file diff --git a/src/Aspire.Cli/Resources/xlf/CertificatesCommandStrings.tr.xlf b/src/Aspire.Cli/Resources/xlf/CertificatesCommandStrings.tr.xlf new file mode 100644 index 00000000000..6aac80a49ca --- /dev/null +++ b/src/Aspire.Cli/Resources/xlf/CertificatesCommandStrings.tr.xlf @@ -0,0 +1,72 @@ + + + + + + Certificate clean operation was cancelled by the user. + Certificate clean operation was cancelled by the user. + + + + Remove all HTTPS development certificates. + Remove all HTTPS development certificates. + + + + Failed to clean HTTPS development certificates. + Failed to clean HTTPS development certificates. + + + + Certificate clean operation failed: {0} + Certificate clean operation failed: {0} + {0} is the error message from the failed operation + + + Cleaning development certificates (may require elevated permissions)... + Cleaning development certificates (may require elevated permissions)... + + + + All HTTPS development certificates cleaned successfully. + All HTTPS development certificates cleaned successfully. + + + + Manage HTTPS development certificates. + Manage HTTPS development certificates. + + + + Certificate trust operation was cancelled by the user. + Certificate trust operation was cancelled by the user. + + + + Trust the HTTPS development certificate, creating one if necessary. + Trust the HTTPS development certificate, creating one if necessary. + + + + Failed to trust HTTPS development certificate. + Failed to trust HTTPS development certificate. + + + + Certificate trust operation returned: {0} + Certificate trust operation returned: {0} + {0} is the EnsureCertificateResult value + + + Trusting development certificate (may require elevated permissions)... + Trusting development certificate (may require elevated permissions)... + + + + HTTPS development certificate trusted successfully. + HTTPS development certificate trusted successfully. + + + + + \ No newline at end of file diff --git a/src/Aspire.Cli/Resources/xlf/CertificatesCommandStrings.zh-Hans.xlf b/src/Aspire.Cli/Resources/xlf/CertificatesCommandStrings.zh-Hans.xlf new file mode 100644 index 00000000000..7049db5fbb0 --- /dev/null +++ b/src/Aspire.Cli/Resources/xlf/CertificatesCommandStrings.zh-Hans.xlf @@ -0,0 +1,72 @@ + + + + + + Certificate clean operation was cancelled by the user. + Certificate clean operation was cancelled by the user. + + + + Remove all HTTPS development certificates. + Remove all HTTPS development certificates. + + + + Failed to clean HTTPS development certificates. + Failed to clean HTTPS development certificates. + + + + Certificate clean operation failed: {0} + Certificate clean operation failed: {0} + {0} is the error message from the failed operation + + + Cleaning development certificates (may require elevated permissions)... + Cleaning development certificates (may require elevated permissions)... + + + + All HTTPS development certificates cleaned successfully. + All HTTPS development certificates cleaned successfully. + + + + Manage HTTPS development certificates. + Manage HTTPS development certificates. + + + + Certificate trust operation was cancelled by the user. + Certificate trust operation was cancelled by the user. + + + + Trust the HTTPS development certificate, creating one if necessary. + Trust the HTTPS development certificate, creating one if necessary. + + + + Failed to trust HTTPS development certificate. + Failed to trust HTTPS development certificate. + + + + Certificate trust operation returned: {0} + Certificate trust operation returned: {0} + {0} is the EnsureCertificateResult value + + + Trusting development certificate (may require elevated permissions)... + Trusting development certificate (may require elevated permissions)... + + + + HTTPS development certificate trusted successfully. + HTTPS development certificate trusted successfully. + + + + + \ No newline at end of file diff --git a/src/Aspire.Cli/Resources/xlf/CertificatesCommandStrings.zh-Hant.xlf b/src/Aspire.Cli/Resources/xlf/CertificatesCommandStrings.zh-Hant.xlf new file mode 100644 index 00000000000..cfcb61fe8be --- /dev/null +++ b/src/Aspire.Cli/Resources/xlf/CertificatesCommandStrings.zh-Hant.xlf @@ -0,0 +1,72 @@ + + + + + + Certificate clean operation was cancelled by the user. + Certificate clean operation was cancelled by the user. + + + + Remove all HTTPS development certificates. + Remove all HTTPS development certificates. + + + + Failed to clean HTTPS development certificates. + Failed to clean HTTPS development certificates. + + + + Certificate clean operation failed: {0} + Certificate clean operation failed: {0} + {0} is the error message from the failed operation + + + Cleaning development certificates (may require elevated permissions)... + Cleaning development certificates (may require elevated permissions)... + + + + All HTTPS development certificates cleaned successfully. + All HTTPS development certificates cleaned successfully. + + + + Manage HTTPS development certificates. + Manage HTTPS development certificates. + + + + Certificate trust operation was cancelled by the user. + Certificate trust operation was cancelled by the user. + + + + Trust the HTTPS development certificate, creating one if necessary. + Trust the HTTPS development certificate, creating one if necessary. + + + + Failed to trust HTTPS development certificate. + Failed to trust HTTPS development certificate. + + + + Certificate trust operation returned: {0} + Certificate trust operation returned: {0} + {0} is the EnsureCertificateResult value + + + Trusting development certificate (may require elevated permissions)... + Trusting development certificate (may require elevated permissions)... + + + + HTTPS development certificate trusted successfully. + HTTPS development certificate trusted successfully. + + + + + \ No newline at end of file diff --git a/src/Aspire.Cli/Resources/xlf/DoctorCommandStrings.cs.xlf b/src/Aspire.Cli/Resources/xlf/DoctorCommandStrings.cs.xlf index 447f8ba2222..f92c4dff68e 100644 --- a/src/Aspire.Cli/Resources/xlf/DoctorCommandStrings.cs.xlf +++ b/src/Aspire.Cli/Resources/xlf/DoctorCommandStrings.cs.xlf @@ -1,4 +1,4 @@ - + @@ -22,6 +22,96 @@ Podrobné informace o požadavcích: https://aka.ms/aspire-prerequisites + + Run '{0}' to remove all certificates, then run '{1}' to create and trust a new one. + Run '{0}' to remove all certificates, then run '{1}' to create and trust a new one. + {0} is the aspire certs clean command, {1} is the aspire certs trust command (not localizable) + + + Found certificates: {0}. Having multiple certificates can cause confusion. + Found certificates: {0}. Having multiple certificates can cause confusion. + + + + Multiple HTTPS development certificates found ({0} certificates), but none are trusted + Multiple HTTPS development certificates found ({0} certificates), but none are trusted + + + + Found certificates: {0}. Having multiple certificates can cause confusion when selecting which one to use. + Found certificates: {0}. Having multiple certificates can cause confusion when selecting which one to use. + + + + Multiple HTTPS development certificates found ({0} certificates) + Multiple HTTPS development certificates found ({0} certificates) + + + + Aspire uses HTTPS for secure communication between the dashboard and your services during local development. + Aspire uses HTTPS for secure communication between the dashboard and your services during local development. + + + + No HTTPS development certificate found + No HTTPS development certificate found + + + + Certificate {0} exists in the personal store but was not found in the trusted root store. + Certificate {0} exists in the personal store but was not found in the trusted root store. + + + + HTTPS development certificate is not trusted + HTTPS development certificate is not trusted + + + + Older certificate versions (< v{0}) may not support container trust scenarios. + Older certificate versions (< v{0}) may not support container trust scenarios. + + + + HTTPS development certificate has an older version ({0}) + HTTPS development certificate has an older version ({0}) + + + + The certificate is in the trusted store, but SSL_CERT_DIR is not configured to include '{0}'. Some applications may not trust the certificate. 'aspire run' will configure this automatically. + The certificate is in the trusted store, but SSL_CERT_DIR is not configured to include '{0}'. Some applications may not trust the certificate. 'aspire run' will configure this automatically. + + + + Set SSL_CERT_DIR in your shell profile: {0} + Set SSL_CERT_DIR in your shell profile: {0} + + + + HTTPS development certificate is only partially trusted + HTTPS development certificate is only partially trusted + + + + Run '{0}' to trust the HTTPS development certificate. + Run '{0}' to trust the HTTPS development certificate. + {0} is the aspire certs trust command (not localizable) + + + [trusted] + [trusted] + + + + [partial] + [partial] + + + + HTTPS development certificate is trusted + HTTPS development certificate is trusted + + Environment Prostředí diff --git a/src/Aspire.Cli/Resources/xlf/DoctorCommandStrings.de.xlf b/src/Aspire.Cli/Resources/xlf/DoctorCommandStrings.de.xlf index ca45ef97c88..fcbd31729a4 100644 --- a/src/Aspire.Cli/Resources/xlf/DoctorCommandStrings.de.xlf +++ b/src/Aspire.Cli/Resources/xlf/DoctorCommandStrings.de.xlf @@ -1,4 +1,4 @@ - + @@ -22,6 +22,96 @@ Für detaillierte Voraussetzungen: https://aka.ms/aspire-prerequisites + + Run '{0}' to remove all certificates, then run '{1}' to create and trust a new one. + Run '{0}' to remove all certificates, then run '{1}' to create and trust a new one. + {0} is the aspire certs clean command, {1} is the aspire certs trust command (not localizable) + + + Found certificates: {0}. Having multiple certificates can cause confusion. + Found certificates: {0}. Having multiple certificates can cause confusion. + + + + Multiple HTTPS development certificates found ({0} certificates), but none are trusted + Multiple HTTPS development certificates found ({0} certificates), but none are trusted + + + + Found certificates: {0}. Having multiple certificates can cause confusion when selecting which one to use. + Found certificates: {0}. Having multiple certificates can cause confusion when selecting which one to use. + + + + Multiple HTTPS development certificates found ({0} certificates) + Multiple HTTPS development certificates found ({0} certificates) + + + + Aspire uses HTTPS for secure communication between the dashboard and your services during local development. + Aspire uses HTTPS for secure communication between the dashboard and your services during local development. + + + + No HTTPS development certificate found + No HTTPS development certificate found + + + + Certificate {0} exists in the personal store but was not found in the trusted root store. + Certificate {0} exists in the personal store but was not found in the trusted root store. + + + + HTTPS development certificate is not trusted + HTTPS development certificate is not trusted + + + + Older certificate versions (< v{0}) may not support container trust scenarios. + Older certificate versions (< v{0}) may not support container trust scenarios. + + + + HTTPS development certificate has an older version ({0}) + HTTPS development certificate has an older version ({0}) + + + + The certificate is in the trusted store, but SSL_CERT_DIR is not configured to include '{0}'. Some applications may not trust the certificate. 'aspire run' will configure this automatically. + The certificate is in the trusted store, but SSL_CERT_DIR is not configured to include '{0}'. Some applications may not trust the certificate. 'aspire run' will configure this automatically. + + + + Set SSL_CERT_DIR in your shell profile: {0} + Set SSL_CERT_DIR in your shell profile: {0} + + + + HTTPS development certificate is only partially trusted + HTTPS development certificate is only partially trusted + + + + Run '{0}' to trust the HTTPS development certificate. + Run '{0}' to trust the HTTPS development certificate. + {0} is the aspire certs trust command (not localizable) + + + [trusted] + [trusted] + + + + [partial] + [partial] + + + + HTTPS development certificate is trusted + HTTPS development certificate is trusted + + Environment Umgebung diff --git a/src/Aspire.Cli/Resources/xlf/DoctorCommandStrings.es.xlf b/src/Aspire.Cli/Resources/xlf/DoctorCommandStrings.es.xlf index de7dc93b84f..ff98fd04362 100644 --- a/src/Aspire.Cli/Resources/xlf/DoctorCommandStrings.es.xlf +++ b/src/Aspire.Cli/Resources/xlf/DoctorCommandStrings.es.xlf @@ -1,4 +1,4 @@ - + @@ -22,6 +22,96 @@ Para conocer los requisitos previos detallados: https://aka.ms/aspire-prerequisites + + Run '{0}' to remove all certificates, then run '{1}' to create and trust a new one. + Run '{0}' to remove all certificates, then run '{1}' to create and trust a new one. + {0} is the aspire certs clean command, {1} is the aspire certs trust command (not localizable) + + + Found certificates: {0}. Having multiple certificates can cause confusion. + Found certificates: {0}. Having multiple certificates can cause confusion. + + + + Multiple HTTPS development certificates found ({0} certificates), but none are trusted + Multiple HTTPS development certificates found ({0} certificates), but none are trusted + + + + Found certificates: {0}. Having multiple certificates can cause confusion when selecting which one to use. + Found certificates: {0}. Having multiple certificates can cause confusion when selecting which one to use. + + + + Multiple HTTPS development certificates found ({0} certificates) + Multiple HTTPS development certificates found ({0} certificates) + + + + Aspire uses HTTPS for secure communication between the dashboard and your services during local development. + Aspire uses HTTPS for secure communication between the dashboard and your services during local development. + + + + No HTTPS development certificate found + No HTTPS development certificate found + + + + Certificate {0} exists in the personal store but was not found in the trusted root store. + Certificate {0} exists in the personal store but was not found in the trusted root store. + + + + HTTPS development certificate is not trusted + HTTPS development certificate is not trusted + + + + Older certificate versions (< v{0}) may not support container trust scenarios. + Older certificate versions (< v{0}) may not support container trust scenarios. + + + + HTTPS development certificate has an older version ({0}) + HTTPS development certificate has an older version ({0}) + + + + The certificate is in the trusted store, but SSL_CERT_DIR is not configured to include '{0}'. Some applications may not trust the certificate. 'aspire run' will configure this automatically. + The certificate is in the trusted store, but SSL_CERT_DIR is not configured to include '{0}'. Some applications may not trust the certificate. 'aspire run' will configure this automatically. + + + + Set SSL_CERT_DIR in your shell profile: {0} + Set SSL_CERT_DIR in your shell profile: {0} + + + + HTTPS development certificate is only partially trusted + HTTPS development certificate is only partially trusted + + + + Run '{0}' to trust the HTTPS development certificate. + Run '{0}' to trust the HTTPS development certificate. + {0} is the aspire certs trust command (not localizable) + + + [trusted] + [trusted] + + + + [partial] + [partial] + + + + HTTPS development certificate is trusted + HTTPS development certificate is trusted + + Environment Entorno diff --git a/src/Aspire.Cli/Resources/xlf/DoctorCommandStrings.fr.xlf b/src/Aspire.Cli/Resources/xlf/DoctorCommandStrings.fr.xlf index da5b9ca9f79..785ff19d042 100644 --- a/src/Aspire.Cli/Resources/xlf/DoctorCommandStrings.fr.xlf +++ b/src/Aspire.Cli/Resources/xlf/DoctorCommandStrings.fr.xlf @@ -1,4 +1,4 @@ - + @@ -22,6 +22,96 @@ Pour les prérequis détaillés : https://aka.ms/aspire-prerequisites + + Run '{0}' to remove all certificates, then run '{1}' to create and trust a new one. + Run '{0}' to remove all certificates, then run '{1}' to create and trust a new one. + {0} is the aspire certs clean command, {1} is the aspire certs trust command (not localizable) + + + Found certificates: {0}. Having multiple certificates can cause confusion. + Found certificates: {0}. Having multiple certificates can cause confusion. + + + + Multiple HTTPS development certificates found ({0} certificates), but none are trusted + Multiple HTTPS development certificates found ({0} certificates), but none are trusted + + + + Found certificates: {0}. Having multiple certificates can cause confusion when selecting which one to use. + Found certificates: {0}. Having multiple certificates can cause confusion when selecting which one to use. + + + + Multiple HTTPS development certificates found ({0} certificates) + Multiple HTTPS development certificates found ({0} certificates) + + + + Aspire uses HTTPS for secure communication between the dashboard and your services during local development. + Aspire uses HTTPS for secure communication between the dashboard and your services during local development. + + + + No HTTPS development certificate found + No HTTPS development certificate found + + + + Certificate {0} exists in the personal store but was not found in the trusted root store. + Certificate {0} exists in the personal store but was not found in the trusted root store. + + + + HTTPS development certificate is not trusted + HTTPS development certificate is not trusted + + + + Older certificate versions (< v{0}) may not support container trust scenarios. + Older certificate versions (< v{0}) may not support container trust scenarios. + + + + HTTPS development certificate has an older version ({0}) + HTTPS development certificate has an older version ({0}) + + + + The certificate is in the trusted store, but SSL_CERT_DIR is not configured to include '{0}'. Some applications may not trust the certificate. 'aspire run' will configure this automatically. + The certificate is in the trusted store, but SSL_CERT_DIR is not configured to include '{0}'. Some applications may not trust the certificate. 'aspire run' will configure this automatically. + + + + Set SSL_CERT_DIR in your shell profile: {0} + Set SSL_CERT_DIR in your shell profile: {0} + + + + HTTPS development certificate is only partially trusted + HTTPS development certificate is only partially trusted + + + + Run '{0}' to trust the HTTPS development certificate. + Run '{0}' to trust the HTTPS development certificate. + {0} is the aspire certs trust command (not localizable) + + + [trusted] + [trusted] + + + + [partial] + [partial] + + + + HTTPS development certificate is trusted + HTTPS development certificate is trusted + + Environment Environnement diff --git a/src/Aspire.Cli/Resources/xlf/DoctorCommandStrings.it.xlf b/src/Aspire.Cli/Resources/xlf/DoctorCommandStrings.it.xlf index feb2f667d5c..ae684162ecf 100644 --- a/src/Aspire.Cli/Resources/xlf/DoctorCommandStrings.it.xlf +++ b/src/Aspire.Cli/Resources/xlf/DoctorCommandStrings.it.xlf @@ -1,4 +1,4 @@ - + @@ -22,6 +22,96 @@ Per prerequisiti dettagliati: https://aka.ms/aspire-prerequisites + + Run '{0}' to remove all certificates, then run '{1}' to create and trust a new one. + Run '{0}' to remove all certificates, then run '{1}' to create and trust a new one. + {0} is the aspire certs clean command, {1} is the aspire certs trust command (not localizable) + + + Found certificates: {0}. Having multiple certificates can cause confusion. + Found certificates: {0}. Having multiple certificates can cause confusion. + + + + Multiple HTTPS development certificates found ({0} certificates), but none are trusted + Multiple HTTPS development certificates found ({0} certificates), but none are trusted + + + + Found certificates: {0}. Having multiple certificates can cause confusion when selecting which one to use. + Found certificates: {0}. Having multiple certificates can cause confusion when selecting which one to use. + + + + Multiple HTTPS development certificates found ({0} certificates) + Multiple HTTPS development certificates found ({0} certificates) + + + + Aspire uses HTTPS for secure communication between the dashboard and your services during local development. + Aspire uses HTTPS for secure communication between the dashboard and your services during local development. + + + + No HTTPS development certificate found + No HTTPS development certificate found + + + + Certificate {0} exists in the personal store but was not found in the trusted root store. + Certificate {0} exists in the personal store but was not found in the trusted root store. + + + + HTTPS development certificate is not trusted + HTTPS development certificate is not trusted + + + + Older certificate versions (< v{0}) may not support container trust scenarios. + Older certificate versions (< v{0}) may not support container trust scenarios. + + + + HTTPS development certificate has an older version ({0}) + HTTPS development certificate has an older version ({0}) + + + + The certificate is in the trusted store, but SSL_CERT_DIR is not configured to include '{0}'. Some applications may not trust the certificate. 'aspire run' will configure this automatically. + The certificate is in the trusted store, but SSL_CERT_DIR is not configured to include '{0}'. Some applications may not trust the certificate. 'aspire run' will configure this automatically. + + + + Set SSL_CERT_DIR in your shell profile: {0} + Set SSL_CERT_DIR in your shell profile: {0} + + + + HTTPS development certificate is only partially trusted + HTTPS development certificate is only partially trusted + + + + Run '{0}' to trust the HTTPS development certificate. + Run '{0}' to trust the HTTPS development certificate. + {0} is the aspire certs trust command (not localizable) + + + [trusted] + [trusted] + + + + [partial] + [partial] + + + + HTTPS development certificate is trusted + HTTPS development certificate is trusted + + Environment Ambiente diff --git a/src/Aspire.Cli/Resources/xlf/DoctorCommandStrings.ja.xlf b/src/Aspire.Cli/Resources/xlf/DoctorCommandStrings.ja.xlf index ec214738011..f38e8ca3d02 100644 --- a/src/Aspire.Cli/Resources/xlf/DoctorCommandStrings.ja.xlf +++ b/src/Aspire.Cli/Resources/xlf/DoctorCommandStrings.ja.xlf @@ -1,4 +1,4 @@ - + @@ -22,6 +22,96 @@ 前提条件の詳細: https://aka.ms/aspire-prerequisites + + Run '{0}' to remove all certificates, then run '{1}' to create and trust a new one. + Run '{0}' to remove all certificates, then run '{1}' to create and trust a new one. + {0} is the aspire certs clean command, {1} is the aspire certs trust command (not localizable) + + + Found certificates: {0}. Having multiple certificates can cause confusion. + Found certificates: {0}. Having multiple certificates can cause confusion. + + + + Multiple HTTPS development certificates found ({0} certificates), but none are trusted + Multiple HTTPS development certificates found ({0} certificates), but none are trusted + + + + Found certificates: {0}. Having multiple certificates can cause confusion when selecting which one to use. + Found certificates: {0}. Having multiple certificates can cause confusion when selecting which one to use. + + + + Multiple HTTPS development certificates found ({0} certificates) + Multiple HTTPS development certificates found ({0} certificates) + + + + Aspire uses HTTPS for secure communication between the dashboard and your services during local development. + Aspire uses HTTPS for secure communication between the dashboard and your services during local development. + + + + No HTTPS development certificate found + No HTTPS development certificate found + + + + Certificate {0} exists in the personal store but was not found in the trusted root store. + Certificate {0} exists in the personal store but was not found in the trusted root store. + + + + HTTPS development certificate is not trusted + HTTPS development certificate is not trusted + + + + Older certificate versions (< v{0}) may not support container trust scenarios. + Older certificate versions (< v{0}) may not support container trust scenarios. + + + + HTTPS development certificate has an older version ({0}) + HTTPS development certificate has an older version ({0}) + + + + The certificate is in the trusted store, but SSL_CERT_DIR is not configured to include '{0}'. Some applications may not trust the certificate. 'aspire run' will configure this automatically. + The certificate is in the trusted store, but SSL_CERT_DIR is not configured to include '{0}'. Some applications may not trust the certificate. 'aspire run' will configure this automatically. + + + + Set SSL_CERT_DIR in your shell profile: {0} + Set SSL_CERT_DIR in your shell profile: {0} + + + + HTTPS development certificate is only partially trusted + HTTPS development certificate is only partially trusted + + + + Run '{0}' to trust the HTTPS development certificate. + Run '{0}' to trust the HTTPS development certificate. + {0} is the aspire certs trust command (not localizable) + + + [trusted] + [trusted] + + + + [partial] + [partial] + + + + HTTPS development certificate is trusted + HTTPS development certificate is trusted + + Environment 環境 diff --git a/src/Aspire.Cli/Resources/xlf/DoctorCommandStrings.ko.xlf b/src/Aspire.Cli/Resources/xlf/DoctorCommandStrings.ko.xlf index 47747d37aab..bf91746f78c 100644 --- a/src/Aspire.Cli/Resources/xlf/DoctorCommandStrings.ko.xlf +++ b/src/Aspire.Cli/Resources/xlf/DoctorCommandStrings.ko.xlf @@ -1,4 +1,4 @@ - + @@ -22,6 +22,96 @@ 필수 구성 요소 확인: https://aka.ms/aspire-prerequisites + + Run '{0}' to remove all certificates, then run '{1}' to create and trust a new one. + Run '{0}' to remove all certificates, then run '{1}' to create and trust a new one. + {0} is the aspire certs clean command, {1} is the aspire certs trust command (not localizable) + + + Found certificates: {0}. Having multiple certificates can cause confusion. + Found certificates: {0}. Having multiple certificates can cause confusion. + + + + Multiple HTTPS development certificates found ({0} certificates), but none are trusted + Multiple HTTPS development certificates found ({0} certificates), but none are trusted + + + + Found certificates: {0}. Having multiple certificates can cause confusion when selecting which one to use. + Found certificates: {0}. Having multiple certificates can cause confusion when selecting which one to use. + + + + Multiple HTTPS development certificates found ({0} certificates) + Multiple HTTPS development certificates found ({0} certificates) + + + + Aspire uses HTTPS for secure communication between the dashboard and your services during local development. + Aspire uses HTTPS for secure communication between the dashboard and your services during local development. + + + + No HTTPS development certificate found + No HTTPS development certificate found + + + + Certificate {0} exists in the personal store but was not found in the trusted root store. + Certificate {0} exists in the personal store but was not found in the trusted root store. + + + + HTTPS development certificate is not trusted + HTTPS development certificate is not trusted + + + + Older certificate versions (< v{0}) may not support container trust scenarios. + Older certificate versions (< v{0}) may not support container trust scenarios. + + + + HTTPS development certificate has an older version ({0}) + HTTPS development certificate has an older version ({0}) + + + + The certificate is in the trusted store, but SSL_CERT_DIR is not configured to include '{0}'. Some applications may not trust the certificate. 'aspire run' will configure this automatically. + The certificate is in the trusted store, but SSL_CERT_DIR is not configured to include '{0}'. Some applications may not trust the certificate. 'aspire run' will configure this automatically. + + + + Set SSL_CERT_DIR in your shell profile: {0} + Set SSL_CERT_DIR in your shell profile: {0} + + + + HTTPS development certificate is only partially trusted + HTTPS development certificate is only partially trusted + + + + Run '{0}' to trust the HTTPS development certificate. + Run '{0}' to trust the HTTPS development certificate. + {0} is the aspire certs trust command (not localizable) + + + [trusted] + [trusted] + + + + [partial] + [partial] + + + + HTTPS development certificate is trusted + HTTPS development certificate is trusted + + Environment 환경 diff --git a/src/Aspire.Cli/Resources/xlf/DoctorCommandStrings.pl.xlf b/src/Aspire.Cli/Resources/xlf/DoctorCommandStrings.pl.xlf index d662338344a..74d7da61c55 100644 --- a/src/Aspire.Cli/Resources/xlf/DoctorCommandStrings.pl.xlf +++ b/src/Aspire.Cli/Resources/xlf/DoctorCommandStrings.pl.xlf @@ -1,4 +1,4 @@ - + @@ -22,6 +22,96 @@ Szczegółowe wymagania wstępne znajdziesz na: https://aka.ms/aspire-prerequisites + + Run '{0}' to remove all certificates, then run '{1}' to create and trust a new one. + Run '{0}' to remove all certificates, then run '{1}' to create and trust a new one. + {0} is the aspire certs clean command, {1} is the aspire certs trust command (not localizable) + + + Found certificates: {0}. Having multiple certificates can cause confusion. + Found certificates: {0}. Having multiple certificates can cause confusion. + + + + Multiple HTTPS development certificates found ({0} certificates), but none are trusted + Multiple HTTPS development certificates found ({0} certificates), but none are trusted + + + + Found certificates: {0}. Having multiple certificates can cause confusion when selecting which one to use. + Found certificates: {0}. Having multiple certificates can cause confusion when selecting which one to use. + + + + Multiple HTTPS development certificates found ({0} certificates) + Multiple HTTPS development certificates found ({0} certificates) + + + + Aspire uses HTTPS for secure communication between the dashboard and your services during local development. + Aspire uses HTTPS for secure communication between the dashboard and your services during local development. + + + + No HTTPS development certificate found + No HTTPS development certificate found + + + + Certificate {0} exists in the personal store but was not found in the trusted root store. + Certificate {0} exists in the personal store but was not found in the trusted root store. + + + + HTTPS development certificate is not trusted + HTTPS development certificate is not trusted + + + + Older certificate versions (< v{0}) may not support container trust scenarios. + Older certificate versions (< v{0}) may not support container trust scenarios. + + + + HTTPS development certificate has an older version ({0}) + HTTPS development certificate has an older version ({0}) + + + + The certificate is in the trusted store, but SSL_CERT_DIR is not configured to include '{0}'. Some applications may not trust the certificate. 'aspire run' will configure this automatically. + The certificate is in the trusted store, but SSL_CERT_DIR is not configured to include '{0}'. Some applications may not trust the certificate. 'aspire run' will configure this automatically. + + + + Set SSL_CERT_DIR in your shell profile: {0} + Set SSL_CERT_DIR in your shell profile: {0} + + + + HTTPS development certificate is only partially trusted + HTTPS development certificate is only partially trusted + + + + Run '{0}' to trust the HTTPS development certificate. + Run '{0}' to trust the HTTPS development certificate. + {0} is the aspire certs trust command (not localizable) + + + [trusted] + [trusted] + + + + [partial] + [partial] + + + + HTTPS development certificate is trusted + HTTPS development certificate is trusted + + Environment Środowisko diff --git a/src/Aspire.Cli/Resources/xlf/DoctorCommandStrings.pt-BR.xlf b/src/Aspire.Cli/Resources/xlf/DoctorCommandStrings.pt-BR.xlf index 3e003b7a9b1..4339806f69c 100644 --- a/src/Aspire.Cli/Resources/xlf/DoctorCommandStrings.pt-BR.xlf +++ b/src/Aspire.Cli/Resources/xlf/DoctorCommandStrings.pt-BR.xlf @@ -1,4 +1,4 @@ - + @@ -22,6 +22,96 @@ Para obter os pré-requisitos detalhados: https://aka.ms/aspire-prerequisites + + Run '{0}' to remove all certificates, then run '{1}' to create and trust a new one. + Run '{0}' to remove all certificates, then run '{1}' to create and trust a new one. + {0} is the aspire certs clean command, {1} is the aspire certs trust command (not localizable) + + + Found certificates: {0}. Having multiple certificates can cause confusion. + Found certificates: {0}. Having multiple certificates can cause confusion. + + + + Multiple HTTPS development certificates found ({0} certificates), but none are trusted + Multiple HTTPS development certificates found ({0} certificates), but none are trusted + + + + Found certificates: {0}. Having multiple certificates can cause confusion when selecting which one to use. + Found certificates: {0}. Having multiple certificates can cause confusion when selecting which one to use. + + + + Multiple HTTPS development certificates found ({0} certificates) + Multiple HTTPS development certificates found ({0} certificates) + + + + Aspire uses HTTPS for secure communication between the dashboard and your services during local development. + Aspire uses HTTPS for secure communication between the dashboard and your services during local development. + + + + No HTTPS development certificate found + No HTTPS development certificate found + + + + Certificate {0} exists in the personal store but was not found in the trusted root store. + Certificate {0} exists in the personal store but was not found in the trusted root store. + + + + HTTPS development certificate is not trusted + HTTPS development certificate is not trusted + + + + Older certificate versions (< v{0}) may not support container trust scenarios. + Older certificate versions (< v{0}) may not support container trust scenarios. + + + + HTTPS development certificate has an older version ({0}) + HTTPS development certificate has an older version ({0}) + + + + The certificate is in the trusted store, but SSL_CERT_DIR is not configured to include '{0}'. Some applications may not trust the certificate. 'aspire run' will configure this automatically. + The certificate is in the trusted store, but SSL_CERT_DIR is not configured to include '{0}'. Some applications may not trust the certificate. 'aspire run' will configure this automatically. + + + + Set SSL_CERT_DIR in your shell profile: {0} + Set SSL_CERT_DIR in your shell profile: {0} + + + + HTTPS development certificate is only partially trusted + HTTPS development certificate is only partially trusted + + + + Run '{0}' to trust the HTTPS development certificate. + Run '{0}' to trust the HTTPS development certificate. + {0} is the aspire certs trust command (not localizable) + + + [trusted] + [trusted] + + + + [partial] + [partial] + + + + HTTPS development certificate is trusted + HTTPS development certificate is trusted + + Environment Ambiente diff --git a/src/Aspire.Cli/Resources/xlf/DoctorCommandStrings.ru.xlf b/src/Aspire.Cli/Resources/xlf/DoctorCommandStrings.ru.xlf index 1fb07570ee2..6f8a3eceb09 100644 --- a/src/Aspire.Cli/Resources/xlf/DoctorCommandStrings.ru.xlf +++ b/src/Aspire.Cli/Resources/xlf/DoctorCommandStrings.ru.xlf @@ -1,4 +1,4 @@ - + @@ -22,6 +22,96 @@ Подробнее о предварительных требованиях: https://aka.ms/aspire-prerequisites + + Run '{0}' to remove all certificates, then run '{1}' to create and trust a new one. + Run '{0}' to remove all certificates, then run '{1}' to create and trust a new one. + {0} is the aspire certs clean command, {1} is the aspire certs trust command (not localizable) + + + Found certificates: {0}. Having multiple certificates can cause confusion. + Found certificates: {0}. Having multiple certificates can cause confusion. + + + + Multiple HTTPS development certificates found ({0} certificates), but none are trusted + Multiple HTTPS development certificates found ({0} certificates), but none are trusted + + + + Found certificates: {0}. Having multiple certificates can cause confusion when selecting which one to use. + Found certificates: {0}. Having multiple certificates can cause confusion when selecting which one to use. + + + + Multiple HTTPS development certificates found ({0} certificates) + Multiple HTTPS development certificates found ({0} certificates) + + + + Aspire uses HTTPS for secure communication between the dashboard and your services during local development. + Aspire uses HTTPS for secure communication between the dashboard and your services during local development. + + + + No HTTPS development certificate found + No HTTPS development certificate found + + + + Certificate {0} exists in the personal store but was not found in the trusted root store. + Certificate {0} exists in the personal store but was not found in the trusted root store. + + + + HTTPS development certificate is not trusted + HTTPS development certificate is not trusted + + + + Older certificate versions (< v{0}) may not support container trust scenarios. + Older certificate versions (< v{0}) may not support container trust scenarios. + + + + HTTPS development certificate has an older version ({0}) + HTTPS development certificate has an older version ({0}) + + + + The certificate is in the trusted store, but SSL_CERT_DIR is not configured to include '{0}'. Some applications may not trust the certificate. 'aspire run' will configure this automatically. + The certificate is in the trusted store, but SSL_CERT_DIR is not configured to include '{0}'. Some applications may not trust the certificate. 'aspire run' will configure this automatically. + + + + Set SSL_CERT_DIR in your shell profile: {0} + Set SSL_CERT_DIR in your shell profile: {0} + + + + HTTPS development certificate is only partially trusted + HTTPS development certificate is only partially trusted + + + + Run '{0}' to trust the HTTPS development certificate. + Run '{0}' to trust the HTTPS development certificate. + {0} is the aspire certs trust command (not localizable) + + + [trusted] + [trusted] + + + + [partial] + [partial] + + + + HTTPS development certificate is trusted + HTTPS development certificate is trusted + + Environment Среда diff --git a/src/Aspire.Cli/Resources/xlf/DoctorCommandStrings.tr.xlf b/src/Aspire.Cli/Resources/xlf/DoctorCommandStrings.tr.xlf index b9f5b943168..e5beac499c7 100644 --- a/src/Aspire.Cli/Resources/xlf/DoctorCommandStrings.tr.xlf +++ b/src/Aspire.Cli/Resources/xlf/DoctorCommandStrings.tr.xlf @@ -1,4 +1,4 @@ - + @@ -22,6 +22,96 @@ Ayrıntılı önkoşullar için: https://aka.ms/aspire-prerequisites + + Run '{0}' to remove all certificates, then run '{1}' to create and trust a new one. + Run '{0}' to remove all certificates, then run '{1}' to create and trust a new one. + {0} is the aspire certs clean command, {1} is the aspire certs trust command (not localizable) + + + Found certificates: {0}. Having multiple certificates can cause confusion. + Found certificates: {0}. Having multiple certificates can cause confusion. + + + + Multiple HTTPS development certificates found ({0} certificates), but none are trusted + Multiple HTTPS development certificates found ({0} certificates), but none are trusted + + + + Found certificates: {0}. Having multiple certificates can cause confusion when selecting which one to use. + Found certificates: {0}. Having multiple certificates can cause confusion when selecting which one to use. + + + + Multiple HTTPS development certificates found ({0} certificates) + Multiple HTTPS development certificates found ({0} certificates) + + + + Aspire uses HTTPS for secure communication between the dashboard and your services during local development. + Aspire uses HTTPS for secure communication between the dashboard and your services during local development. + + + + No HTTPS development certificate found + No HTTPS development certificate found + + + + Certificate {0} exists in the personal store but was not found in the trusted root store. + Certificate {0} exists in the personal store but was not found in the trusted root store. + + + + HTTPS development certificate is not trusted + HTTPS development certificate is not trusted + + + + Older certificate versions (< v{0}) may not support container trust scenarios. + Older certificate versions (< v{0}) may not support container trust scenarios. + + + + HTTPS development certificate has an older version ({0}) + HTTPS development certificate has an older version ({0}) + + + + The certificate is in the trusted store, but SSL_CERT_DIR is not configured to include '{0}'. Some applications may not trust the certificate. 'aspire run' will configure this automatically. + The certificate is in the trusted store, but SSL_CERT_DIR is not configured to include '{0}'. Some applications may not trust the certificate. 'aspire run' will configure this automatically. + + + + Set SSL_CERT_DIR in your shell profile: {0} + Set SSL_CERT_DIR in your shell profile: {0} + + + + HTTPS development certificate is only partially trusted + HTTPS development certificate is only partially trusted + + + + Run '{0}' to trust the HTTPS development certificate. + Run '{0}' to trust the HTTPS development certificate. + {0} is the aspire certs trust command (not localizable) + + + [trusted] + [trusted] + + + + [partial] + [partial] + + + + HTTPS development certificate is trusted + HTTPS development certificate is trusted + + Environment Ortam diff --git a/src/Aspire.Cli/Resources/xlf/DoctorCommandStrings.zh-Hans.xlf b/src/Aspire.Cli/Resources/xlf/DoctorCommandStrings.zh-Hans.xlf index 827edc04b1f..1917bc071d8 100644 --- a/src/Aspire.Cli/Resources/xlf/DoctorCommandStrings.zh-Hans.xlf +++ b/src/Aspire.Cli/Resources/xlf/DoctorCommandStrings.zh-Hans.xlf @@ -1,4 +1,4 @@ - + @@ -22,6 +22,96 @@ 详细先决条件请参见: https://aka.ms/aspire-prerequisites + + Run '{0}' to remove all certificates, then run '{1}' to create and trust a new one. + Run '{0}' to remove all certificates, then run '{1}' to create and trust a new one. + {0} is the aspire certs clean command, {1} is the aspire certs trust command (not localizable) + + + Found certificates: {0}. Having multiple certificates can cause confusion. + Found certificates: {0}. Having multiple certificates can cause confusion. + + + + Multiple HTTPS development certificates found ({0} certificates), but none are trusted + Multiple HTTPS development certificates found ({0} certificates), but none are trusted + + + + Found certificates: {0}. Having multiple certificates can cause confusion when selecting which one to use. + Found certificates: {0}. Having multiple certificates can cause confusion when selecting which one to use. + + + + Multiple HTTPS development certificates found ({0} certificates) + Multiple HTTPS development certificates found ({0} certificates) + + + + Aspire uses HTTPS for secure communication between the dashboard and your services during local development. + Aspire uses HTTPS for secure communication between the dashboard and your services during local development. + + + + No HTTPS development certificate found + No HTTPS development certificate found + + + + Certificate {0} exists in the personal store but was not found in the trusted root store. + Certificate {0} exists in the personal store but was not found in the trusted root store. + + + + HTTPS development certificate is not trusted + HTTPS development certificate is not trusted + + + + Older certificate versions (< v{0}) may not support container trust scenarios. + Older certificate versions (< v{0}) may not support container trust scenarios. + + + + HTTPS development certificate has an older version ({0}) + HTTPS development certificate has an older version ({0}) + + + + The certificate is in the trusted store, but SSL_CERT_DIR is not configured to include '{0}'. Some applications may not trust the certificate. 'aspire run' will configure this automatically. + The certificate is in the trusted store, but SSL_CERT_DIR is not configured to include '{0}'. Some applications may not trust the certificate. 'aspire run' will configure this automatically. + + + + Set SSL_CERT_DIR in your shell profile: {0} + Set SSL_CERT_DIR in your shell profile: {0} + + + + HTTPS development certificate is only partially trusted + HTTPS development certificate is only partially trusted + + + + Run '{0}' to trust the HTTPS development certificate. + Run '{0}' to trust the HTTPS development certificate. + {0} is the aspire certs trust command (not localizable) + + + [trusted] + [trusted] + + + + [partial] + [partial] + + + + HTTPS development certificate is trusted + HTTPS development certificate is trusted + + Environment 环境 diff --git a/src/Aspire.Cli/Resources/xlf/DoctorCommandStrings.zh-Hant.xlf b/src/Aspire.Cli/Resources/xlf/DoctorCommandStrings.zh-Hant.xlf index ec5278559a6..78595ad3ce6 100644 --- a/src/Aspire.Cli/Resources/xlf/DoctorCommandStrings.zh-Hant.xlf +++ b/src/Aspire.Cli/Resources/xlf/DoctorCommandStrings.zh-Hant.xlf @@ -1,4 +1,4 @@ - + @@ -22,6 +22,96 @@ 如需詳細的先決條件: https://aka.ms/aspire-prerequisites + + Run '{0}' to remove all certificates, then run '{1}' to create and trust a new one. + Run '{0}' to remove all certificates, then run '{1}' to create and trust a new one. + {0} is the aspire certs clean command, {1} is the aspire certs trust command (not localizable) + + + Found certificates: {0}. Having multiple certificates can cause confusion. + Found certificates: {0}. Having multiple certificates can cause confusion. + + + + Multiple HTTPS development certificates found ({0} certificates), but none are trusted + Multiple HTTPS development certificates found ({0} certificates), but none are trusted + + + + Found certificates: {0}. Having multiple certificates can cause confusion when selecting which one to use. + Found certificates: {0}. Having multiple certificates can cause confusion when selecting which one to use. + + + + Multiple HTTPS development certificates found ({0} certificates) + Multiple HTTPS development certificates found ({0} certificates) + + + + Aspire uses HTTPS for secure communication between the dashboard and your services during local development. + Aspire uses HTTPS for secure communication between the dashboard and your services during local development. + + + + No HTTPS development certificate found + No HTTPS development certificate found + + + + Certificate {0} exists in the personal store but was not found in the trusted root store. + Certificate {0} exists in the personal store but was not found in the trusted root store. + + + + HTTPS development certificate is not trusted + HTTPS development certificate is not trusted + + + + Older certificate versions (< v{0}) may not support container trust scenarios. + Older certificate versions (< v{0}) may not support container trust scenarios. + + + + HTTPS development certificate has an older version ({0}) + HTTPS development certificate has an older version ({0}) + + + + The certificate is in the trusted store, but SSL_CERT_DIR is not configured to include '{0}'. Some applications may not trust the certificate. 'aspire run' will configure this automatically. + The certificate is in the trusted store, but SSL_CERT_DIR is not configured to include '{0}'. Some applications may not trust the certificate. 'aspire run' will configure this automatically. + + + + Set SSL_CERT_DIR in your shell profile: {0} + Set SSL_CERT_DIR in your shell profile: {0} + + + + HTTPS development certificate is only partially trusted + HTTPS development certificate is only partially trusted + + + + Run '{0}' to trust the HTTPS development certificate. + Run '{0}' to trust the HTTPS development certificate. + {0} is the aspire certs trust command (not localizable) + + + [trusted] + [trusted] + + + + [partial] + [partial] + + + + HTTPS development certificate is trusted + HTTPS development certificate is trusted + + Environment 環境 diff --git a/src/Aspire.Cli/Templating/CliTemplateFactory.TypeScriptStarterTemplate.cs b/src/Aspire.Cli/Templating/CliTemplateFactory.TypeScriptStarterTemplate.cs index a2d354a1d57..f910e0c21e3 100644 --- a/src/Aspire.Cli/Templating/CliTemplateFactory.TypeScriptStarterTemplate.cs +++ b/src/Aspire.Cli/Templating/CliTemplateFactory.TypeScriptStarterTemplate.cs @@ -3,8 +3,8 @@ using Aspire.Cli.Configuration; using Aspire.Cli.Interaction; +using Aspire.Cli.Projects; using Aspire.Cli.Resources; -using Aspire.Cli.Utils; using Microsoft.Extensions.Logging; using Spectre.Console; @@ -61,23 +61,7 @@ private async Task ApplyTypeScriptStarterTemplateAsync(CallbackT _logger.LogDebug("Copying embedded TypeScript starter template files to '{OutputPath}'.", outputPath); await CopyTemplateTreeToDiskAsync("ts-starter", outputPath, ApplyAllTokens, cancellationToken); - if (!CommandPathResolver.TryResolveCommand("npm", out var npmPath, out var errorMessage)) - { - _interactionService.DisplayError(errorMessage!); - return new TemplateResult(ExitCodeConstants.InvalidCommand); - } - - // Run npm install in the output directory (non-fatal — package may not be published yet) - _logger.LogDebug("Running npm install for TypeScript starter in '{OutputPath}'.", outputPath); - var npmInstallResult = await RunProcessAsync(npmPath!, "install", outputPath, cancellationToken); - if (npmInstallResult.ExitCode != 0) - { - _interactionService.DisplaySubtleMessage("npm install had warnings or errors. You may need to run 'npm install' manually after dependencies are available."); - DisplayProcessOutput(npmInstallResult, treatStandardErrorAsError: false); - } - - // Write channel to settings.json if available so that aspire add - // knows which channel to use for package resolution + // Write channel to settings.json before restore so package resolution uses the selected channel. if (!string.IsNullOrEmpty(inputs.Channel)) { var config = AspireJsonConfiguration.Load(outputPath); @@ -88,6 +72,21 @@ private async Task ApplyTypeScriptStarterTemplateAsync(CallbackT } } + var appHostProject = _projectFactory.TryGetProject(new FileInfo(Path.Combine(outputPath, "apphost.ts"))); + if (appHostProject is not IGuestAppHostSdkGenerator guestProject) + { + _interactionService.DisplayError("Automatic 'aspire restore' is unavailable for the new TypeScript starter project because no TypeScript AppHost SDK generator was found."); + return new TemplateResult(ExitCodeConstants.FailedToBuildArtifacts, outputPath); + } + + _logger.LogDebug("Generating SDK code for TypeScript starter in '{OutputPath}'.", outputPath); + var restoreSucceeded = await guestProject.BuildAndGenerateSdkAsync(new DirectoryInfo(outputPath), cancellationToken); + if (!restoreSucceeded) + { + _interactionService.DisplayError("Automatic 'aspire restore' failed for the new TypeScript starter project. Run 'aspire restore' in the project directory for more details."); + return new TemplateResult(ExitCodeConstants.FailedToBuildArtifacts, outputPath); + } + return new TemplateResult(ExitCodeConstants.Success, outputPath); }, emoji: KnownEmojis.Rocket); diff --git a/src/Aspire.Cli/Templating/CliTemplateFactory.cs b/src/Aspire.Cli/Templating/CliTemplateFactory.cs index 64634de5ae3..fce808f4a04 100644 --- a/src/Aspire.Cli/Templating/CliTemplateFactory.cs +++ b/src/Aspire.Cli/Templating/CliTemplateFactory.cs @@ -2,7 +2,6 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.CommandLine; -using System.Diagnostics; using System.Globalization; using System.Text; using Aspire.Cli.Commands; @@ -39,6 +38,7 @@ internal sealed partial class CliTemplateFactory : ITemplateFactory }; private readonly ILanguageDiscovery _languageDiscovery; + private readonly IAppHostProjectFactory _projectFactory; private readonly IScaffoldingService _scaffoldingService; private readonly INewCommandPrompter _prompter; private readonly CliExecutionContext _executionContext; @@ -49,6 +49,7 @@ internal sealed partial class CliTemplateFactory : ITemplateFactory public CliTemplateFactory( ILanguageDiscovery languageDiscovery, + IAppHostProjectFactory projectFactory, IScaffoldingService scaffoldingService, INewCommandPrompter prompter, CliExecutionContext executionContext, @@ -58,6 +59,7 @@ public CliTemplateFactory( ILogger logger) { _languageDiscovery = languageDiscovery; + _projectFactory = projectFactory; _scaffoldingService = scaffoldingService; _prompter = prompter; _executionContext = executionContext; @@ -209,76 +211,6 @@ private async Task CopyTemplateTreeToDiskAsync(string templateRoot, string outpu } } - private void DisplayProcessOutput(ProcessExecutionResult result, bool treatStandardErrorAsError) - { - if (!string.IsNullOrWhiteSpace(result.StandardOutput)) - { - _interactionService.DisplaySubtleMessage(result.StandardOutput.TrimEnd()); - } - - if (!string.IsNullOrWhiteSpace(result.StandardError)) - { - var message = result.StandardError.TrimEnd(); - if (treatStandardErrorAsError) - { - _interactionService.DisplayError(message); - } - else - { - _interactionService.DisplaySubtleMessage(message); - } - } - } - - private static async Task RunProcessAsync(string fileName, string arguments, string workingDirectory, CancellationToken cancellationToken) - { - var startInfo = new ProcessStartInfo(fileName, arguments) - { - RedirectStandardInput = true, - RedirectStandardOutput = true, - RedirectStandardError = true, - UseShellExecute = false, - CreateNoWindow = true, - WorkingDirectory = workingDirectory - }; - - using var process = new Process { StartInfo = startInfo }; - process.Start(); - process.StandardInput.Close(); // Prevent hanging on prompts - - // Drain output streams to prevent deadlocks - var outputTask = process.StandardOutput.ReadToEndAsync(cancellationToken); - var errorTask = process.StandardError.ReadToEndAsync(cancellationToken); - - try - { - await process.WaitForExitAsync(cancellationToken).ConfigureAwait(false); - await Task.WhenAll(outputTask, errorTask).ConfigureAwait(false); - } - catch (OperationCanceledException) when (cancellationToken.IsCancellationRequested) - { - try - { - if (!process.HasExited) - { - process.Kill(entireProcessTree: true); - } - } - catch (InvalidOperationException) - { - } - - throw; - } - - return new ProcessExecutionResult( - process.ExitCode, - await outputTask.ConfigureAwait(false), - await errorTask.ConfigureAwait(false)); - } - - private sealed record ProcessExecutionResult(int ExitCode, string StandardOutput, string StandardError); - private void DisplayPostCreationInstructions(string outputPath) { var currentDir = _executionContext.WorkingDirectory.FullName; diff --git a/src/Aspire.Cli/Utils/EnvironmentChecker/DevCertsCheck.cs b/src/Aspire.Cli/Utils/EnvironmentChecker/DevCertsCheck.cs index 971f27a8eca..5868bc17d1a 100644 --- a/src/Aspire.Cli/Utils/EnvironmentChecker/DevCertsCheck.cs +++ b/src/Aspire.Cli/Utils/EnvironmentChecker/DevCertsCheck.cs @@ -2,26 +2,17 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Diagnostics; +using System.Globalization; using System.Runtime.InteropServices; using System.Security.Cryptography.X509Certificates; +using Aspire.Cli.Certificates; +using Aspire.Cli.Resources; using Aspire.Hosting.Utils; +using Microsoft.AspNetCore.Certificates.Generation; using Microsoft.Extensions.Logging; namespace Aspire.Cli.Utils.EnvironmentChecker; -/// -/// Represents the trust level of a certificate. -/// -internal enum CertificateTrustLevel -{ - /// Certificate is not in any trusted store. - None, - /// Certificate is in a trusted store but SSL_CERT_DIR is not configured (Linux only). - Partial, - /// Certificate is fully trusted. - Full -} - /// /// Checks if the dotnet dev-certs HTTPS certificate is trusted and detects multiple certificates. /// @@ -32,33 +23,14 @@ internal sealed class DevCertsCheck(ILogger logger) : IEnvironmen public int Order => 35; // After SDK check (30), before container checks (40+) + private static readonly string s_trustFixCommand = string.Format(CultureInfo.InvariantCulture, DoctorCommandStrings.DevCertsTrustFixFormat, "aspire certs trust"); + private static readonly string s_cleanAndTrustFixCommand = string.Format(CultureInfo.InvariantCulture, DoctorCommandStrings.DevCertsCleanAndTrustFixFormat, "aspire certs clean", "aspire certs trust"); + public Task> CheckAsync(CancellationToken cancellationToken = default) { try { - var devCertificates = GetDeveloperCertificates(); - - if (devCertificates.Count == 0) - { - return Task.FromResult>([new EnvironmentCheckResult - { - Category = "sdk", - Name = "dev-certs", - Status = EnvironmentCheckStatus.Warning, - Message = "No HTTPS development certificate found", - Details = "Aspire uses HTTPS for secure communication between the dashboard and your services during local development.", - Fix = "Run: dotnet dev-certs https --trust", - Link = "https://aka.ms/aspire-prerequisites#dev-certs" - }]); - } - - // Check trust level for each certificate - var certInfos = devCertificates.Select(c => - { - var trustLevel = GetCertificateTrustLevel(c); - return new CertificateInfo(trustLevel, c.Thumbprint, c.GetCertificateVersion()); - }).ToList(); - + var certInfos = GetCertificateInfos(); var results = EvaluateCertificateResults(certInfos); return Task.FromResult>(results); @@ -68,7 +40,7 @@ public Task> CheckAsync(CancellationToken logger.LogDebug(ex, "Error checking dev-certs"); return Task.FromResult>([new EnvironmentCheckResult { - Category = "sdk", + Category = "environment", Name = "dev-certs", Status = EnvironmentCheckStatus.Warning, Message = "Unable to check HTTPS development certificate", @@ -85,13 +57,27 @@ public Task> CheckAsync(CancellationToken internal static List EvaluateCertificateResults( List certInfos) { - var trustedCount = certInfos.Count(c => c.TrustLevel != CertificateTrustLevel.None); - var fullyTrustedCount = certInfos.Count(c => c.TrustLevel == CertificateTrustLevel.Full); - var partiallyTrustedCount = certInfos.Count(c => c.TrustLevel == CertificateTrustLevel.Partial); + if (certInfos.Count == 0) + { + return [new EnvironmentCheckResult + { + Category = "environment", + Name = "dev-certs", + Status = EnvironmentCheckStatus.Warning, + Message = DoctorCommandStrings.DevCertsNoCertificateMessage, + Details = DoctorCommandStrings.DevCertsNoCertificateDetails, + Fix = s_trustFixCommand, + Link = "https://aka.ms/aspire-prerequisites#dev-certs" + }]; + } + + var trustedCount = certInfos.Count(c => c.TrustLevel != CertificateManager.TrustLevel.None); + var fullyTrustedCount = certInfos.Count(c => c.TrustLevel == CertificateManager.TrustLevel.Full); + var partiallyTrustedCount = certInfos.Count(c => c.TrustLevel == CertificateManager.TrustLevel.Partial); // Check for old certificate versions among trusted certificates var oldTrustedVersions = certInfos - .Where(c => c.TrustLevel != CertificateTrustLevel.None && c.Version < X509Certificate2Extensions.MinimumCertificateVersionSupportingContainerTrust) + .Where(c => c.TrustLevel != CertificateManager.TrustLevel.None && c.Version < X509Certificate2Extensions.MinimumCertificateVersionSupportingContainerTrust) .Select(c => c.Version) .ToList(); @@ -104,8 +90,8 @@ internal static List EvaluateCertificateResults( { var trustLabel = c.TrustLevel switch { - CertificateTrustLevel.Full => " [trusted]", - CertificateTrustLevel.Partial => " [partial]", + CertificateManager.TrustLevel.Full => $" {DoctorCommandStrings.DevCertsTrustLabelFull}", + CertificateManager.TrustLevel.Partial => $" {DoctorCommandStrings.DevCertsTrustLabelPartial}", _ => "" }; return $"v{c.Version} ({c.Thumbprint[..8]}...){trustLabel}"; @@ -115,12 +101,12 @@ internal static List EvaluateCertificateResults( { results.Add(new EnvironmentCheckResult { - Category = "sdk", + Category = "environment", Name = "dev-certs", Status = EnvironmentCheckStatus.Warning, - Message = $"Multiple HTTPS development certificates found ({certInfos.Count} certificates), but none are trusted", - Details = $"Found certificates: {certDetails}. Having multiple certificates can cause confusion.", - Fix = "Run 'dotnet dev-certs https --clean' to remove all certificates, then run 'dotnet dev-certs https --trust' to create a new one.", + Message = string.Format(CultureInfo.CurrentCulture, DoctorCommandStrings.DevCertsMultipleNoneTrustedMessageFormat, certInfos.Count), + Details = string.Format(CultureInfo.CurrentCulture, DoctorCommandStrings.DevCertsMultipleNoneTrustedDetailsFormat, certDetails), + Fix = s_cleanAndTrustFixCommand, Link = "https://aka.ms/aspire-prerequisites#dev-certs" }); } @@ -128,12 +114,12 @@ internal static List EvaluateCertificateResults( { results.Add(new EnvironmentCheckResult { - Category = "sdk", + Category = "environment", Name = "dev-certs", Status = EnvironmentCheckStatus.Warning, - Message = $"Multiple HTTPS development certificates found ({certInfos.Count} certificates)", - Details = $"Found certificates: {certDetails}. Having multiple certificates can cause confusion when selecting which one to use.", - Fix = "Run 'dotnet dev-certs https --clean' to remove all certificates, then run 'dotnet dev-certs https --trust' to create a new one.", + Message = string.Format(CultureInfo.CurrentCulture, DoctorCommandStrings.DevCertsMultipleSomeUntrustedMessageFormat, certInfos.Count), + Details = string.Format(CultureInfo.CurrentCulture, DoctorCommandStrings.DevCertsMultipleSomeUntrustedDetailsFormat, certDetails), + Fix = s_cleanAndTrustFixCommand, Link = "https://aka.ms/aspire-prerequisites#dev-certs" }); } @@ -142,10 +128,10 @@ internal static List EvaluateCertificateResults( { results.Add(new EnvironmentCheckResult { - Category = "sdk", + Category = "environment", Name = "dev-certs", Status = EnvironmentCheckStatus.Pass, - Message = "HTTPS development certificate is trusted" + Message = DoctorCommandStrings.DevCertsTrustedMessage }); } } @@ -155,12 +141,12 @@ internal static List EvaluateCertificateResults( var cert = certInfos[0]; results.Add(new EnvironmentCheckResult { - Category = "sdk", + Category = "environment", Name = "dev-certs", Status = EnvironmentCheckStatus.Warning, - Message = "HTTPS development certificate is not trusted", - Details = $"Certificate {cert.Thumbprint} exists in the personal store but was not found in the trusted root store.", - Fix = "Run: dotnet dev-certs https --trust", + Message = DoctorCommandStrings.DevCertsNotTrustedMessage, + Details = string.Format(CultureInfo.CurrentCulture, DoctorCommandStrings.DevCertsNotTrustedDetailsFormat, cert.Thumbprint), + Fix = s_trustFixCommand, Link = "https://aka.ms/aspire-prerequisites#dev-certs" }); } @@ -170,12 +156,12 @@ internal static List EvaluateCertificateResults( var devCertsTrustPath = GetDevCertsTrustPath(); results.Add(new EnvironmentCheckResult { - Category = "sdk", + Category = "environment", Name = "dev-certs", Status = EnvironmentCheckStatus.Warning, - Message = "HTTPS development certificate is only partially trusted", - Details = $"The certificate is in the trusted store, but SSL_CERT_DIR is not configured to include '{devCertsTrustPath}'. Some applications may not trust the certificate. 'aspire run' will configure this automatically.", - Fix = $"Set SSL_CERT_DIR in your shell profile: export SSL_CERT_DIR=\"/etc/ssl/certs:{devCertsTrustPath}\"", + Message = DoctorCommandStrings.DevCertsPartiallyTrustedMessage, + Details = string.Format(CultureInfo.CurrentCulture, DoctorCommandStrings.DevCertsPartiallyTrustedDetailsFormat, devCertsTrustPath), + Fix = string.Format(CultureInfo.CurrentCulture, DoctorCommandStrings.DevCertsPartiallyTrustedFixFormat, BuildSslCertDirFixCommand(devCertsTrustPath)), Link = "https://aka.ms/aspire-prerequisites#dev-certs" }); } @@ -184,10 +170,10 @@ internal static List EvaluateCertificateResults( // Trusted certificate - success case results.Add(new EnvironmentCheckResult { - Category = "sdk", + Category = "environment", Name = "dev-certs", Status = EnvironmentCheckStatus.Pass, - Message = "HTTPS development certificate is trusted" + Message = DoctorCommandStrings.DevCertsTrustedMessage }); } @@ -197,12 +183,12 @@ internal static List EvaluateCertificateResults( var versions = string.Join(", ", oldTrustedVersions.Select(v => $"v{v}")); results.Add(new EnvironmentCheckResult { - Category = "sdk", + Category = "environment", Name = "dev-certs-version", Status = EnvironmentCheckStatus.Warning, - Message = $"HTTPS development certificate has an older version ({versions})", - Details = $"Older certificate versions (< v{X509Certificate2Extensions.MinimumCertificateVersionSupportingContainerTrust}) may not support container trust scenarios. Consider regenerating your development certificate. For best compatibility, use .NET SDK 10.0.101 or later.", - Fix = "Run 'dotnet dev-certs https --clean' to remove all certificates, then run 'dotnet dev-certs https --trust' to create a new one.", + Message = string.Format(CultureInfo.CurrentCulture, DoctorCommandStrings.DevCertsOldVersionMessageFormat, versions), + Details = string.Format(CultureInfo.CurrentCulture, DoctorCommandStrings.DevCertsOldVersionDetailsFormat, X509Certificate2Extensions.MinimumCertificateVersionSupportingContainerTrust), + Fix = s_cleanAndTrustFixCommand, Link = "https://aka.ms/aspire-prerequisites#dev-certs" }); } @@ -210,6 +196,30 @@ internal static List EvaluateCertificateResults( return results; } + /// + /// Loads developer certificates and builds pre-computed certificate information. + /// Used by . + /// + private List GetCertificateInfos() + { + var devCertificates = GetDeveloperCertificates(); + try + { + return devCertificates.Select(c => + { + var trustLevel = GetCertificateTrustLevel(c); + return new CertificateInfo(trustLevel, c.Thumbprint, c.GetCertificateVersion()); + }).ToList(); + } + finally + { + foreach (var cert in devCertificates) + { + cert.Dispose(); + } + } + } + /// /// Gets all ASP.NET Core development certificates from the CurrentUser/My store. /// @@ -248,27 +258,27 @@ private List GetDeveloperCertificates() /// /// Gets the trust level of a certificate. /// - private CertificateTrustLevel GetCertificateTrustLevel(X509Certificate2 certificate) + private CertificateManager.TrustLevel GetCertificateTrustLevel(X509Certificate2 certificate) { if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) { // On macOS, use 'security verify-cert' to check trust (same as dotnet dev-certs) - return IsCertificateTrustedOnMacOS(certificate) ? CertificateTrustLevel.Full : CertificateTrustLevel.None; + return IsCertificateTrustedOnMacOS(certificate) ? CertificateManager.TrustLevel.Full : CertificateManager.TrustLevel.None; } // Check if the certificate exists in the Root stores if (!IsCertificateInRootStore(certificate)) { - return CertificateTrustLevel.None; + return CertificateManager.TrustLevel.None; } // On Linux, check if SSL_CERT_DIR is configured properly if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux) && !IsSslCertDirConfigured()) { - return CertificateTrustLevel.Partial; + return CertificateManager.TrustLevel.Partial; } - return CertificateTrustLevel.Full; + return CertificateManager.TrustLevel.Full; } /// @@ -299,6 +309,33 @@ private static bool IsSslCertDirConfigured() return paths.Any(p => string.Equals(p.TrimEnd(Path.DirectorySeparatorChar), devCertsTrustPath.TrimEnd(Path.DirectorySeparatorChar), StringComparison.OrdinalIgnoreCase)); } + /// + /// Builds the appropriate shell command for fixing SSL_CERT_DIR configuration. + /// + /// + /// + /// Always includes $SSL_CERT_DIR to preserve any existing value. If the variable + /// is unset, the empty expansion produces a harmless leading colon which OpenSSL treats + /// as the default certificate directory. + /// + /// + /// When possible, also includes the system OpenSSL certificate directory detected via + /// 'openssl version -d' (mirrors UnixCertificateManager.TryGetOpenSslDirectory). + /// + /// + private static string BuildSslCertDirFixCommand(string devCertsTrustPath) + { + // Always prepend $SSL_CERT_DIR to preserve any existing value. + // If unset, the empty expansion is harmless. + if (CertificateHelpers.TryGetOpenSslDirectory(out var openSslDir)) + { + var systemCertsPath = Path.Combine(openSslDir, "certs"); + return $"export SSL_CERT_DIR=\"$SSL_CERT_DIR:{systemCertsPath}:{devCertsTrustPath}\""; + } + + return $"export SSL_CERT_DIR=\"$SSL_CERT_DIR:{devCertsTrustPath}\""; + } + /// /// Checks if a certificate is trusted on macOS using the security command. /// @@ -400,4 +437,4 @@ private bool IsCertificateInRootStore(X509Certificate2 certificate) /// /// Pre-computed certificate information for evaluation without accessing the certificate store. /// -internal sealed record CertificateInfo(CertificateTrustLevel TrustLevel, string Thumbprint, int Version); +internal sealed record CertificateInfo(CertificateManager.TrustLevel TrustLevel, string Thumbprint, int Version); diff --git a/src/Aspire.Cli/Utils/EnvironmentChecker/DotNetSdkCheck.cs b/src/Aspire.Cli/Utils/EnvironmentChecker/DotNetSdkCheck.cs index 17c4d765d13..941e3a339f6 100644 --- a/src/Aspire.Cli/Utils/EnvironmentChecker/DotNetSdkCheck.cs +++ b/src/Aspire.Cli/Utils/EnvironmentChecker/DotNetSdkCheck.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using Aspire.Cli.DotNet; +using Aspire.Cli.Projects; using Microsoft.Extensions.Logging; namespace Aspire.Cli.Utils.EnvironmentChecker; @@ -9,7 +10,16 @@ namespace Aspire.Cli.Utils.EnvironmentChecker; /// /// Checks if the .NET SDK is installed and meets the minimum version requirement. /// -internal sealed class DotNetSdkCheck(IDotNetSdkInstaller sdkInstaller, ILogger logger) : IEnvironmentCheck +/// +/// This check is skipped when the detected AppHost is a non-.NET project (e.g., TypeScript, Python, Go), +/// since .NET SDK is not required for polyglot scenarios. +/// +internal sealed class DotNetSdkCheck( + IDotNetSdkInstaller sdkInstaller, + IProjectLocator projectLocator, + ILanguageDiscovery languageDiscovery, + CliExecutionContext executionContext, + ILogger logger) : IEnvironmentCheck { public int Order => 30; // File system check - slightly more expensive @@ -17,6 +27,12 @@ public async Task> CheckAsync(Cancellation { try { + if (!await IsDotNetAppHostAsync(cancellationToken)) + { + logger.LogDebug("Skipping .NET SDK check because no .NET AppHost was detected"); + return []; + } + var (success, highestVersion, minimumRequiredVersion) = await sdkInstaller.CheckAsync(cancellationToken); if (!success) @@ -64,4 +80,47 @@ public async Task> CheckAsync(Cancellation }]; } } + + /// + /// Determines whether a .NET AppHost is positively detected, meaning the .NET SDK check should run. + /// Only returns true when a settings file is found and the apphost is a .NET project. + /// When no settings file exists or the apphost is non-.NET, the check is skipped. + /// + private async Task IsDotNetAppHostAsync(CancellationToken cancellationToken) + { + try + { + // Use the silent settings-only lookup to find the apphost without + // emitting interaction output or performing recursive filesystem scans. + var appHostFile = await projectLocator.GetAppHostFromSettingsAsync(cancellationToken); + + if (appHostFile is not null && languageDiscovery.GetLanguageByFile(appHostFile) is { } language) + { + return language.LanguageId.Value.Equals(KnownLanguageId.CSharp, StringComparison.OrdinalIgnoreCase); + } + + // No apphost configured in settings. Look for possible .NET app hosts on file system (projects or apphost.cs) + // This doesn't guarantee the apphost is .NET, but it's a signal that it might be and worth checking for .NET SDK. + var csharp = languageDiscovery.GetLanguageById(KnownLanguageId.CSharp); + if (csharp is null) + { + return false; + } + + // Scan file system directly instead of using ProjectLocator for performance. + // Limit recursive scan to avoid expensive file system operations in large workspaces. + // We don't want a complete list of all possible project files, just a quick signal that a .NET apphost is probably present. + var match = FileSystemHelper.FindFirstFile(executionContext.WorkingDirectory.FullName, recurseLimit: 5, csharp.DetectionPatterns); + return match is not null; + } + catch (OperationCanceledException) when (cancellationToken.IsCancellationRequested) + { + throw; + } + catch (Exception ex) + { + logger.LogDebug(ex, "Error detecting AppHost language, skipping .NET SDK check"); + return false; + } + } } diff --git a/src/Aspire.Cli/Utils/FileSystemHelper.cs b/src/Aspire.Cli/Utils/FileSystemHelper.cs index 833c84f7369..d1c96303722 100644 --- a/src/Aspire.Cli/Utils/FileSystemHelper.cs +++ b/src/Aspire.Cli/Utils/FileSystemHelper.cs @@ -51,4 +51,55 @@ internal static void CopyDirectory(string sourceDir, string destinationDir, bool } } } + + /// + /// Recursively searches for the first file matching any of the given patterns. + /// Stops immediately when a match is found. + /// + /// Root folder to start search + /// Maximum directory depth to search. Use 0 to search only the root, or -1 for unlimited depth. + /// File name patterns, e.g., "*.csproj", "apphost.cs" + /// Full path to first matching file, or null if none found + public static string? FindFirstFile(string root, int recurseLimit = -1, params string[] patterns) + { + if (!Directory.Exists(root) || patterns.Length == 0) + { + return null; + } + + var dirs = new Stack<(string Path, int Depth)>(); + dirs.Push((root, 0)); + + while (dirs.Count > 0) + { + var (dir, depth) = dirs.Pop(); + + try + { + // Check for each pattern in this directory + foreach (var pattern in patterns) + { + foreach (var file in Directory.EnumerateFiles(dir, pattern)) + { + return file; // first match, exit immediately + } + } + + // Push subdirectories for further search if within depth limit + if (recurseLimit < 0 || depth < recurseLimit) + { + foreach (var sub in Directory.EnumerateDirectories(dir)) + { + dirs.Push((sub, depth + 1)); + } + } + } + catch + { + // Skip directories we can't access (permissions, etc.) + } + } + + return null; + } } diff --git a/src/Aspire.Dashboard/Components/Layout/MainLayout.razor.cs b/src/Aspire.Dashboard/Components/Layout/MainLayout.razor.cs index 4cf1298e102..51098e2dca9 100644 --- a/src/Aspire.Dashboard/Components/Layout/MainLayout.razor.cs +++ b/src/Aspire.Dashboard/Components/Layout/MainLayout.razor.cs @@ -200,7 +200,7 @@ private bool ShouldShowUnsecuredMcpMessage() private bool ShouldShowUnsecuredApiMessage() { // Only show warning if API is enabled and unsecured - return Options.CurrentValue.Api.Enabled == true && + return Options.CurrentValue.Api.Enabled.GetValueOrDefault() && Options.CurrentValue.Api.AuthMode == ApiAuthMode.Unsecured; } diff --git a/src/Aspire.Dashboard/Configuration/DashboardOptions.cs b/src/Aspire.Dashboard/Configuration/DashboardOptions.cs index 7a14a80af5e..a91ee1d6187 100644 --- a/src/Aspire.Dashboard/Configuration/DashboardOptions.cs +++ b/src/Aspire.Dashboard/Configuration/DashboardOptions.cs @@ -150,7 +150,7 @@ public sealed class ApiOptions /// /// Gets or sets whether the Telemetry HTTP API is enabled. /// When false, the /api/telemetry/* endpoints are not registered. - /// Defaults to true. + /// Defaults to false. /// public bool? Enabled { get; set; } diff --git a/src/Aspire.Dashboard/Configuration/PostConfigureDashboardOptions.cs b/src/Aspire.Dashboard/Configuration/PostConfigureDashboardOptions.cs index b166dfda5b4..6f982a8b29a 100644 --- a/src/Aspire.Dashboard/Configuration/PostConfigureDashboardOptions.cs +++ b/src/Aspire.Dashboard/Configuration/PostConfigureDashboardOptions.cs @@ -87,6 +87,8 @@ public void PostConfigure(string? name, DashboardOptions options) options.AI.Disabled = _configuration.GetBool(DashboardConfigNames.DashboardAIDisabledName.ConfigKey); + options.Api.Enabled ??= _configuration.GetBool(DashboardConfigNames.DashboardAspireApiEnabledName.ConfigKey); + // Normalize API keys: Api is canonical, falls back to Mcp if not set. // Api -> Mcp fallback only (not bidirectional). if (string.IsNullOrEmpty(options.Mcp.PrimaryApiKey) && !string.IsNullOrEmpty(options.Api.PrimaryApiKey)) diff --git a/src/Aspire.Dashboard/DashboardEndpointsBuilder.cs b/src/Aspire.Dashboard/DashboardEndpointsBuilder.cs index 194547390d5..6b38baa1b7a 100644 --- a/src/Aspire.Dashboard/DashboardEndpointsBuilder.cs +++ b/src/Aspire.Dashboard/DashboardEndpointsBuilder.cs @@ -108,8 +108,8 @@ public static void MapDashboardMcp(this IEndpointRouteBuilder endpoints, Dashboa public static void MapTelemetryApi(this IEndpointRouteBuilder endpoints, DashboardOptions dashboardOptions) { - // Check if API is disabled (defaults to enabled if not specified) - if (dashboardOptions.Api.Enabled == false) + // Check if API is enabled (defaults to disabled if not specified) + if (!dashboardOptions.Api.Enabled.GetValueOrDefault()) { return; } diff --git a/src/Aspire.Dashboard/DashboardWebApplication.cs b/src/Aspire.Dashboard/DashboardWebApplication.cs index 2be63142af4..65733abc012 100644 --- a/src/Aspire.Dashboard/DashboardWebApplication.cs +++ b/src/Aspire.Dashboard/DashboardWebApplication.cs @@ -413,7 +413,7 @@ public DashboardWebApplication( // Only show API security warning if API is enabled and unsecured // API runs on the frontend endpoint (no separate accessor needed) - if (_dashboardOptionsMonitor.CurrentValue.Api.Enabled == true && + if (_dashboardOptionsMonitor.CurrentValue.Api.Enabled.GetValueOrDefault() && _dashboardOptionsMonitor.CurrentValue.Api.AuthMode == ApiAuthMode.Unsecured) { _logger.LogWarning("Dashboard API is unsecured. Untrusted apps can access sensitive telemetry data."); diff --git a/src/Aspire.Dashboard/ServiceClient/DashboardClient.cs b/src/Aspire.Dashboard/ServiceClient/DashboardClient.cs index 7cdfabdd67d..7c045b0f48f 100644 --- a/src/Aspire.Dashboard/ServiceClient/DashboardClient.cs +++ b/src/Aspire.Dashboard/ServiceClient/DashboardClient.cs @@ -170,7 +170,8 @@ GrpcChannel CreateChannel() HttpHandler = httpHandler, ServiceConfig = new() { MethodConfigs = { methodConfig } }, LoggerFactory = _loggerFactory, - ThrowOperationCanceledOnCancellation = true + ThrowOperationCanceledOnCancellation = true, + MaxReceiveMessageSize = 16 * 1024 * 1024 // 16 MB }); X509CertificateCollection GetFileCertificate() diff --git a/src/Aspire.Hosting.Analyzers/AnalyzerReleases.Unshipped.md b/src/Aspire.Hosting.Analyzers/AnalyzerReleases.Unshipped.md index ab70a35f04b..62bfdc2112c 100644 --- a/src/Aspire.Hosting.Analyzers/AnalyzerReleases.Unshipped.md +++ b/src/Aspire.Hosting.Analyzers/AnalyzerReleases.Unshipped.md @@ -1,17 +1,2 @@ ; Unshipped analyzer release ; https://github.com/dotnet/roslyn/blob/main/src/RoslynAnalyzers/Microsoft.CodeAnalysis.Analyzers/ReleaseTrackingAnalyzers.Help.md - -### New Rules - -Rule ID | Category | Severity | Notes ---------|----------|----------|------- -ASPIREEXPORT001 | Design | Error | AspireExportAnalyzer, [Documentation](https://aka.ms/aspire/diagnostics/ASPIREEXPORT001) -ASPIREEXPORT002 | Design | Error | AspireExportAnalyzer, [Documentation](https://aka.ms/aspire/diagnostics/ASPIREEXPORT002) -ASPIREEXPORT003 | Design | Error | AspireExportAnalyzer, [Documentation](https://aka.ms/aspire/diagnostics/ASPIREEXPORT003) -ASPIREEXPORT004 | Design | Error | AspireExportAnalyzer, [Documentation](https://aka.ms/aspire/diagnostics/ASPIREEXPORT004) -ASPIREEXPORT005 | Design | Warning | AspireExportAnalyzer, [Documentation](https://aka.ms/aspire/diagnostics/ASPIREEXPORT005) -ASPIREEXPORT006 | Design | Warning | AspireExportAnalyzer, [Documentation](https://aka.ms/aspire/diagnostics/ASPIREEXPORT006) -ASPIREEXPORT007 | Design | Warning | AspireExportAnalyzer, [Documentation](https://aka.ms/aspire/diagnostics/ASPIREEXPORT007) -ASPIREEXPORT008 | Design | Warning | AspireExportAnalyzer, [Documentation](https://aka.ms/aspire/diagnostics/ASPIREEXPORT008) -ASPIREEXPORT009 | Design | Warning | AspireExportAnalyzer, [Documentation](https://aka.ms/aspire/diagnostics/ASPIREEXPORT009) -ASPIREEXPORT010 | Design | Warning | AspireExportAnalyzer, [Documentation](https://aka.ms/aspire/diagnostics/ASPIREEXPORT010) diff --git a/src/Aspire.Hosting.AppHost/Aspire.Hosting.AppHost.csproj b/src/Aspire.Hosting.AppHost/Aspire.Hosting.AppHost.csproj index 695484a4be9..f5f6efcf407 100644 --- a/src/Aspire.Hosting.AppHost/Aspire.Hosting.AppHost.csproj +++ b/src/Aspire.Hosting.AppHost/Aspire.Hosting.AppHost.csproj @@ -7,6 +7,7 @@ true aspire hosting Core library and MSBuild logic for Aspire AppHost projects. + true diff --git a/src/Aspire.Hosting.CodeGeneration.TypeScript/AtsTypeScriptCodeGenerator.cs b/src/Aspire.Hosting.CodeGeneration.TypeScript/AtsTypeScriptCodeGenerator.cs index c20b71ba205..c29f8ade7df 100644 --- a/src/Aspire.Hosting.CodeGeneration.TypeScript/AtsTypeScriptCodeGenerator.cs +++ b/src/Aspire.Hosting.CodeGeneration.TypeScript/AtsTypeScriptCodeGenerator.cs @@ -2490,6 +2490,13 @@ private static List CreateBuilderModels(IReadOnlyList 0 }) diff --git a/src/Aspire.Hosting.CodeGeneration.TypeScript/Resources/base.ts b/src/Aspire.Hosting.CodeGeneration.TypeScript/Resources/base.ts index 9a3427e7e72..6256537c773 100644 --- a/src/Aspire.Hosting.CodeGeneration.TypeScript/Resources/base.ts +++ b/src/Aspire.Hosting.CodeGeneration.TypeScript/Resources/base.ts @@ -1,5 +1,5 @@ // aspire.ts - Core Aspire types: base classes, ReferenceExpression -import { Handle, AspireClient, MarshalledHandle } from './transport.js'; +import { Handle, AspireClient, MarshalledHandle, registerCancellation, registerHandleWrapper, unregisterCancellation } from './transport.js'; // Re-export transport types for convenience export { Handle, AspireClient, CapabilityError, registerCallback, unregisterCallback, registerCancellation, unregisterCancellation } from './transport.js'; @@ -154,6 +154,30 @@ export class ReferenceExpression { }; } + /** + * Resolves the expression to its string value on the server. + * Only available on server-returned ReferenceExpression instances (handle mode). + * + * @param cancellationToken - Optional AbortSignal for cancellation support + * @returns The resolved string value, or null if the expression resolves to null + */ + async getValue(cancellationToken?: AbortSignal): Promise { + if (!this._handle || !this._client) { + throw new Error('getValue is only available on server-returned ReferenceExpression instances'); + } + const cancellationTokenId = registerCancellation(cancellationToken); + try { + const rpcArgs: Record = { context: this._handle }; + if (cancellationTokenId !== undefined) rpcArgs.cancellationToken = cancellationTokenId; + return await this._client.invokeCapability( + 'Aspire.Hosting.ApplicationModel/getValue', + rpcArgs + ); + } finally { + unregisterCancellation(cancellationTokenId); + } + } + /** * String representation for debugging. */ @@ -168,6 +192,10 @@ export class ReferenceExpression { } } +registerHandleWrapper('Aspire.Hosting/Aspire.Hosting.ApplicationModel.ReferenceExpression', (handle, client) => + new ReferenceExpression(handle, client) +); + /** * Extracts a value for use in reference expressions. * Supports handles (objects) and string literals. diff --git a/src/Aspire.Hosting.Integration.Analyzers/AnalyzerReleases.Shipped.md b/src/Aspire.Hosting.Integration.Analyzers/AnalyzerReleases.Shipped.md new file mode 100644 index 00000000000..d027c512cb9 --- /dev/null +++ b/src/Aspire.Hosting.Integration.Analyzers/AnalyzerReleases.Shipped.md @@ -0,0 +1,3 @@ +; Shipped analyzer releases +; https://github.com/dotnet/roslyn/blob/main/src/RoslynAnalyzers/Microsoft.CodeAnalysis.Analyzers/ReleaseTrackingAnalyzers.Help.md + diff --git a/src/Aspire.Hosting.Integration.Analyzers/AnalyzerReleases.Unshipped.md b/src/Aspire.Hosting.Integration.Analyzers/AnalyzerReleases.Unshipped.md new file mode 100644 index 00000000000..ab70a35f04b --- /dev/null +++ b/src/Aspire.Hosting.Integration.Analyzers/AnalyzerReleases.Unshipped.md @@ -0,0 +1,17 @@ +; Unshipped analyzer release +; https://github.com/dotnet/roslyn/blob/main/src/RoslynAnalyzers/Microsoft.CodeAnalysis.Analyzers/ReleaseTrackingAnalyzers.Help.md + +### New Rules + +Rule ID | Category | Severity | Notes +--------|----------|----------|------- +ASPIREEXPORT001 | Design | Error | AspireExportAnalyzer, [Documentation](https://aka.ms/aspire/diagnostics/ASPIREEXPORT001) +ASPIREEXPORT002 | Design | Error | AspireExportAnalyzer, [Documentation](https://aka.ms/aspire/diagnostics/ASPIREEXPORT002) +ASPIREEXPORT003 | Design | Error | AspireExportAnalyzer, [Documentation](https://aka.ms/aspire/diagnostics/ASPIREEXPORT003) +ASPIREEXPORT004 | Design | Error | AspireExportAnalyzer, [Documentation](https://aka.ms/aspire/diagnostics/ASPIREEXPORT004) +ASPIREEXPORT005 | Design | Warning | AspireExportAnalyzer, [Documentation](https://aka.ms/aspire/diagnostics/ASPIREEXPORT005) +ASPIREEXPORT006 | Design | Warning | AspireExportAnalyzer, [Documentation](https://aka.ms/aspire/diagnostics/ASPIREEXPORT006) +ASPIREEXPORT007 | Design | Warning | AspireExportAnalyzer, [Documentation](https://aka.ms/aspire/diagnostics/ASPIREEXPORT007) +ASPIREEXPORT008 | Design | Warning | AspireExportAnalyzer, [Documentation](https://aka.ms/aspire/diagnostics/ASPIREEXPORT008) +ASPIREEXPORT009 | Design | Warning | AspireExportAnalyzer, [Documentation](https://aka.ms/aspire/diagnostics/ASPIREEXPORT009) +ASPIREEXPORT010 | Design | Warning | AspireExportAnalyzer, [Documentation](https://aka.ms/aspire/diagnostics/ASPIREEXPORT010) diff --git a/src/Aspire.Hosting.Integration.Analyzers/Aspire.Hosting.Integration.Analyzers.csproj b/src/Aspire.Hosting.Integration.Analyzers/Aspire.Hosting.Integration.Analyzers.csproj new file mode 100644 index 00000000000..430dfb5802d --- /dev/null +++ b/src/Aspire.Hosting.Integration.Analyzers/Aspire.Hosting.Integration.Analyzers.csproj @@ -0,0 +1,44 @@ + + + + netstandard2.0 + true + true + false + false + false + 12.0 + + $(NoWarn),1573,1591,1712 + + false + + + + + + + + + + + + + + + + + + + + diff --git a/src/Aspire.Hosting.Analyzers/AspireExportAnalyzer.Diagnostics.cs b/src/Aspire.Hosting.Integration.Analyzers/AspireExportAnalyzer.Diagnostics.cs similarity index 100% rename from src/Aspire.Hosting.Analyzers/AspireExportAnalyzer.Diagnostics.cs rename to src/Aspire.Hosting.Integration.Analyzers/AspireExportAnalyzer.Diagnostics.cs diff --git a/src/Aspire.Hosting.Analyzers/AspireExportAnalyzer.cs b/src/Aspire.Hosting.Integration.Analyzers/AspireExportAnalyzer.cs similarity index 100% rename from src/Aspire.Hosting.Analyzers/AspireExportAnalyzer.cs rename to src/Aspire.Hosting.Integration.Analyzers/AspireExportAnalyzer.cs diff --git a/src/Aspire.Hosting.RemoteHost/Aspire.Hosting.RemoteHost.csproj b/src/Aspire.Hosting.RemoteHost/Aspire.Hosting.RemoteHost.csproj index 1184e98c9aa..96ed28b51f0 100644 --- a/src/Aspire.Hosting.RemoteHost/Aspire.Hosting.RemoteHost.csproj +++ b/src/Aspire.Hosting.RemoteHost/Aspire.Hosting.RemoteHost.csproj @@ -1,36 +1,11 @@ - Exe net10.0 enable enable - aspire-server - Remote host server for polyglot Aspire AppHosts. - aspire hosting polyglot - - - true - - false - - - false - false - - - $(NoWarn);IL3000 - - - Major - - - none - false - - - true - true + false + true diff --git a/src/Aspire.Hosting.RemoteHost/Ats/CapabilityDispatcher.cs b/src/Aspire.Hosting.RemoteHost/Ats/CapabilityDispatcher.cs index 441afafff4d..e06d0f612e1 100644 --- a/src/Aspire.Hosting.RemoteHost/Ats/CapabilityDispatcher.cs +++ b/src/Aspire.Hosting.RemoteHost/Ats/CapabilityDispatcher.cs @@ -309,29 +309,7 @@ private void RegisterContextTypeMethod(AtsCapabilityInfo capability, MethodInfo object? result; result = await InvokeMethodAsync(methodToInvoke, invokeTarget, methodArgs, capability.RunSyncOnBackgroundThread).ConfigureAwait(false); - // Handle async methods - await instead of blocking - if (result is Task task) - { - try - { - await task.ConfigureAwait(false); - } - catch (Exception ex) - { - throw new InvalidOperationException(ex.Message, ex); - } - - var taskType = task.GetType(); - if (taskType.IsGenericType) - { - var resultProperty = taskType.GetProperty("Result"); - result = resultProperty?.GetValue(task); - } - else - { - result = null; - } - } + result = await UnwrapAsyncResultAsync(result, methodToInvoke.ReturnType).ConfigureAwait(false); return _marshaller.MarshalToJson(result, capability.ReturnType); }; @@ -393,31 +371,7 @@ private void RegisterFromCapability(AtsCapabilityInfo capability, MethodInfo met object? result; result = await InvokeMethodAsync(methodToInvoke, target: null, methodArgs, capability.RunSyncOnBackgroundThread).ConfigureAwait(false); - // Handle async methods - await instead of blocking - if (result is Task task) - { - try - { - await task.ConfigureAwait(false); - } - catch (Exception ex) - { - // Rethrow the exception - it will be caught by the outer handler - // and converted to a CapabilityException - throw new InvalidOperationException(ex.Message, ex); - } - - var taskType = task.GetType(); - if (taskType.IsGenericType) - { - var resultProperty = taskType.GetProperty("Result"); - result = resultProperty?.GetValue(task); - } - else - { - result = null; - } - } + result = await UnwrapAsyncResultAsync(result, methodToInvoke.ReturnType).ConfigureAwait(false); return _marshaller.MarshalToJson(result, capability.ReturnType); }; @@ -505,7 +459,7 @@ public void Register( private static async Task InvokeMethodAsync(MethodInfo method, object? target, object?[] methodArgs, bool runSyncOnBackgroundThread) { - if (runSyncOnBackgroundThread && !typeof(Task).IsAssignableFrom(method.ReturnType)) + if (runSyncOnBackgroundThread && !IsAsyncReturnType(method.ReturnType)) { return await Task.Run(() => InvokeMethodCore(method, target, methodArgs)).ConfigureAwait(false); } @@ -513,6 +467,63 @@ public void Register( return InvokeMethodCore(method, target, methodArgs); } + private static bool IsAsyncReturnType(Type returnType) + { + if (typeof(Task).IsAssignableFrom(returnType) || returnType == typeof(ValueTask)) + { + return true; + } + + return returnType.IsGenericType && returnType.GetGenericTypeDefinition() == typeof(ValueTask<>); + } + + private static async Task UnwrapAsyncResultAsync(object? result, Type returnType) + { + try + { + if (result is Task task) + { + await task.ConfigureAwait(false); + return GetAsyncResultValue(task); + } + + if (returnType == typeof(ValueTask) && result is ValueTask valueTask) + { + await valueTask.ConfigureAwait(false); + return null; + } + + if (returnType.IsGenericType && returnType.GetGenericTypeDefinition() == typeof(ValueTask<>)) + { + var asTask = returnType.GetMethod(nameof(ValueTask.AsTask), BindingFlags.Instance | BindingFlags.Public) + ?? throw new InvalidOperationException($"Unable to await ValueTask result for return type '{returnType}'."); + var boxedTask = asTask.Invoke(result, null) as Task + ?? throw new InvalidOperationException($"Unable to convert ValueTask result for return type '{returnType}' to Task."); + + await boxedTask.ConfigureAwait(false); + return GetAsyncResultValue(boxedTask); + } + + return result; + } + catch (Exception ex) when (ex is not InvalidOperationException) + { + throw new InvalidOperationException(ex.Message, ex); + } + } + + private static object? GetAsyncResultValue(Task task) + { + var taskType = task.GetType(); + if (!taskType.IsGenericType) + { + return null; + } + + var resultProperty = taskType.GetProperty("Result"); + return resultProperty?.GetValue(task); + } + private static object? InvokeMethodCore(MethodInfo method, object? target, object?[] methodArgs) { try diff --git a/src/Aspire.Hosting.RemoteHost/Program.cs b/src/Aspire.Hosting.RemoteHost/Program.cs deleted file mode 100644 index 5018057dae5..00000000000 --- a/src/Aspire.Hosting.RemoteHost/Program.cs +++ /dev/null @@ -1,8 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -// This is the entry point for the pre-built AppHost server used in bundle mode. -// It runs the RemoteHostServer which listens on a Unix socket for JSON-RPC -// connections from polyglot app hosts (TypeScript, Python, etc.) - -await Aspire.Hosting.RemoteHost.RemoteHostServer.RunAsync(args).ConfigureAwait(false); diff --git a/src/Aspire.Hosting/ApplicationModel/CertificateTrustConfigurationCallbackAnnotation.cs b/src/Aspire.Hosting/ApplicationModel/CertificateTrustConfigurationCallbackAnnotation.cs index 39b4edfdff3..8451539c644 100644 --- a/src/Aspire.Hosting/ApplicationModel/CertificateTrustConfigurationCallbackAnnotation.cs +++ b/src/Aspire.Hosting/ApplicationModel/CertificateTrustConfigurationCallbackAnnotation.cs @@ -1,6 +1,9 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics.CodeAnalysis; +using System.Security.Cryptography.X509Certificates; + namespace Aspire.Hosting.ApplicationModel; /// @@ -89,4 +92,61 @@ public sealed class CertificateTrustConfigurationCallbackAnnotationContext /// Gets the that can be used to cancel the operation. /// public required CancellationToken CancellationToken { get; init; } + + /// + /// Adds a custom certificate bundle to the callback context. The provided generator will be invoked during trust configuration and should return the bundle contents as a byte array. + /// + /// A function that generates the custom certificate bundle and returns the bundle contents as a byte array. + /// A that can be used to reference the custom bundle. + /// + /// + /// + /// builder.AddContainer("my-java-app", "my-image:latest") + /// .WithCertificateTrustConfiguration(ctx => + /// { + /// ctx.EnvironmentVariables["JAVAX_NET_SSL_TRUSTSTORE"] = ctx.CreateCustomBundle((certs, ct) => + /// { + /// var pkcs12Builder = new Pkcs12Builder(); + /// var safeContents = new Pkcs12SafeContents(); + /// foreach (var cert in certs) + /// { + /// safeContents.AddCertificate(cert); + /// } + /// pkcs12Builder.AddSafeContentsUnencrypted(safeContents); + /// pkcs12Builder.SealWithMac(string.Empty, HashAlgorithmName.SHA256, 2048); + /// return Task.FromResult(pkcs12Builder.Encode()); + /// }); + /// return Task.CompletedTask; + /// }); + /// + /// + /// + [Experimental("ASPIRECERTIFICATES001", UrlFormat = "https://aka.ms/aspire/diagnostics/{0}")] + public ReferenceExpression CreateCustomBundle(Func> bundleGenerator) + { + ArgumentException.ThrowIfNullOrEmpty(RootCertificatesPath); + + var bundleId = Guid.NewGuid().ToString("N"); + CustomBundlesFactories[bundleId] = bundleGenerator; + + var bundleFilename = IsContainer ? $"{RootCertificatesPath}/bundles/{bundleId}" : Path.Join(RootCertificatesPath, "bundles", bundleId); + var reference = ReferenceExpression.Create($"{bundleFilename}"); + + return reference; + } + + /// + /// Gets the root path where certificates will be written for the resource. + /// + internal string? RootCertificatesPath { get; init; } + + /// + /// Is this being generated for a container (requires Linux style paths) + /// + internal bool IsContainer { get; init; } + + /// + /// Collection of custom certificate bundle generators added via the method, keyed by the bundle's unique ID/filename under the root certificates path. The value is a function that generates the bundle contents as a byte array given a collection of X509 certificates. + /// + internal Dictionary>> CustomBundlesFactories { get; } = new(); } diff --git a/src/Aspire.Hosting/ApplicationModel/CertificateTrustExecutionConfigurationGatherer.cs b/src/Aspire.Hosting/ApplicationModel/CertificateTrustExecutionConfigurationGatherer.cs index 5026cafc3bd..ae2c5283cbb 100644 --- a/src/Aspire.Hosting/ApplicationModel/CertificateTrustExecutionConfigurationGatherer.cs +++ b/src/Aspire.Hosting/ApplicationModel/CertificateTrustExecutionConfigurationGatherer.cs @@ -73,7 +73,7 @@ public async ValueTask GatherAsync(IExecutionConfigurationGathererContext contex additionalData.Certificates.AddRange(certificates); - if (!additionalData.Certificates.Any()) + if (additionalData.Certificates.Count == 0) { // No certificates to configure resourceLogger.LogInformation("No custom certificate authorities to configure for '{ResourceName}'. Default certificate authority trust behavior will be used.", resource.Name); @@ -97,9 +97,12 @@ public async ValueTask GatherAsync(IExecutionConfigurationGathererContext contex Scope = additionalData.Scope, CertificateBundlePath = configurationContext.CertificateBundlePath, CertificateDirectoriesPath = configurationContext.CertificateDirectoriesPath, + // Must use the tracked reference to ensure proper tracking of usage + RootCertificatesPath = configurationContext.RootCertificatesPath, Arguments = context.Arguments, EnvironmentVariables = context.EnvironmentVariables, CancellationToken = cancellationToken, + IsContainer = configurationContext.IsContainer, }; if (resource.TryGetAnnotationsOfType(out var callbacks)) @@ -110,6 +113,11 @@ public async ValueTask GatherAsync(IExecutionConfigurationGathererContext contex } } + foreach (var bundleFactory in callbackContext.CustomBundlesFactories) + { + additionalData.CustomBundlesFactories[bundleFactory.Key] = bundleFactory.Value; + } + if (additionalData.Scope == CertificateTrustScope.System) { resourceLogger.LogInformation("Resource '{ResourceName}' has a certificate trust scope of '{Scope}'. Automatically including system root certificates in the trusted configuration.", resource.Name, Enum.GetName(additionalData.Scope)); @@ -133,6 +141,11 @@ public class CertificateTrustExecutionConfigurationData : IExecutionConfiguratio /// The collection of certificates to trust. /// public X509Certificate2Collection Certificates { get; } = new(); + + /// + /// Collection of custom certificate bundle generators added via the method, keyed by the bundle's relative path under the root certificates path. The value is a function that generates the bundle contents as a byte array given a collection of X509 certificates and a cancellation token. + /// + public Dictionary>> CustomBundlesFactories { get; } = new(); } /// @@ -142,7 +155,7 @@ public class CertificateTrustExecutionConfigurationData : IExecutionConfiguratio public class CertificateTrustExecutionConfigurationContext { /// - /// The path to the certificate bundle file in the resource context (e.g., container filesystem). + /// The path to the PEM certificate bundle file in the resource context (e.g., container filesystem). /// public required ReferenceExpression CertificateBundlePath { get; init; } @@ -150,4 +163,14 @@ public class CertificateTrustExecutionConfigurationContext /// The path(s) to the certificate directories in the resource context (e.g., container filesystem). /// public required ReferenceExpression CertificateDirectoriesPath { get; init; } + + /// + /// The root path certificates will be written to in the resource context (e.g., container filesystem). + /// + public required string RootCertificatesPath { get; init; } + + /// + /// Is this request being generated for a container resource (i.e. does it require Linux style paths?). + /// + public bool IsContainer { get; init; } } diff --git a/src/Aspire.Hosting/ApplicationModel/ReferenceExpression.cs b/src/Aspire.Hosting/ApplicationModel/ReferenceExpression.cs index d879167ce38..0dfb1b7a024 100644 --- a/src/Aspire.Hosting/ApplicationModel/ReferenceExpression.cs +++ b/src/Aspire.Hosting/ApplicationModel/ReferenceExpression.cs @@ -221,6 +221,7 @@ IEnumerable IValueWithReferences.References /// Gets the value of the expression. The final string value after evaluating the format string and its parameters. /// /// A . + [AspireExport("getValue", Description = "Gets the resolved string value of the reference expression asynchronously")] public ValueTask GetValueAsync(CancellationToken cancellationToken) { return this.GetValueAsync(new(), cancellationToken); diff --git a/src/Aspire.Hosting/Aspire.Hosting.csproj b/src/Aspire.Hosting/Aspire.Hosting.csproj index c23e6be416d..e261e863c94 100644 --- a/src/Aspire.Hosting/Aspire.Hosting.csproj +++ b/src/Aspire.Hosting/Aspire.Hosting.csproj @@ -10,6 +10,10 @@ Core abstractions for the Aspire application model. + + + + @@ -140,4 +144,25 @@ + + + + + + + + $(BeforePack);IncludeIntegrationAnalyzerInPackage + + + + + + + + + + + + + diff --git a/src/Aspire.Hosting/Ats/AtsCapabilityScanner.cs b/src/Aspire.Hosting/Ats/AtsCapabilityScanner.cs index 8feaa5133b1..92dbe095f27 100644 --- a/src/Aspire.Hosting/Ats/AtsCapabilityScanner.cs +++ b/src/Aspire.Hosting/Ats/AtsCapabilityScanner.cs @@ -786,6 +786,10 @@ private static Dictionary> BuildTypeCompatibilityMap( IsInterface = false }; + // Register under its own type ID so base types with derived types + // are included when expanding capabilities that target them directly + AddToCompatibilityMap(typeToCompatibleTypes, typeInfo.AtsTypeId, concreteTypeRef); + // Register under each implemented interface foreach (var iface in typeInfo.ImplementedInterfaces) { diff --git a/src/Aspire.Hosting/Dashboard/DashboardEventHandlers.cs b/src/Aspire.Hosting/Dashboard/DashboardEventHandlers.cs index 43dcac25562..7321f97c7a0 100644 --- a/src/Aspire.Hosting/Dashboard/DashboardEventHandlers.cs +++ b/src/Aspire.Hosting/Dashboard/DashboardEventHandlers.cs @@ -635,6 +635,9 @@ internal async Task ConfigureEnvironmentVariables(EnvironmentCallbackContext con context.EnvironmentVariables[DashboardConfigNames.DashboardApiAuthModeName.EnvVarName] = "Unsecured"; } + // Enable dashboard API + context.EnvironmentVariables[DashboardConfigNames.DashboardAspireApiEnabledName.EnvVarName] = "true"; + // Configure dashboard to show CLI MCP instructions when running with an AppHost (not in standalone mode) context.EnvironmentVariables[DashboardConfigNames.DashboardMcpUseCliMcpName.EnvVarName] = "true"; diff --git a/src/Aspire.Hosting/Dcp/DcpExecutor.cs b/src/Aspire.Hosting/Dcp/DcpExecutor.cs index f170f369323..f5145a387ae 100644 --- a/src/Aspire.Hosting/Dcp/DcpExecutor.cs +++ b/src/Aspire.Hosting/Dcp/DcpExecutor.cs @@ -1419,7 +1419,7 @@ private void PreparePlainExecutables() // Just mark as IDE execution here - the actual launch configuration callback // will be invoked in CreateExecutableAsync after endpoints are allocated. exe.Spec.ExecutionType = ExecutionType.IDE; - exe.Spec.FallbackExecutionTypes = [ExecutionType.Process]; + exe.Spec.FallbackExecutionTypes = [ ExecutionType.Process ]; } else { @@ -1468,12 +1468,14 @@ private void PrepareProjectExecutables() if (project.SupportsDebugging(_configuration, out var supportsDebuggingAnnotation)) { exe.Spec.ExecutionType = ExecutionType.IDE; - exe.Spec.FallbackExecutionTypes = [ExecutionType.Process]; + exe.Spec.FallbackExecutionTypes = [ ExecutionType.Process ]; if (supportsDebuggingAnnotation.LaunchConfigurationType is "project") { var projectLaunchConfiguration = new ProjectLaunchConfiguration(); projectLaunchConfiguration.ProjectPath = projectMetadata.ProjectPath; + projectLaunchConfiguration.Mode = _configuration[KnownConfigNames.DebugSessionRunMode] + ?? (Debugger.IsAttached ? ExecutableLaunchMode.Debug : ExecutableLaunchMode.NoDebug); projectLaunchConfiguration.DisableLaunchProfile = project.TryGetLastAnnotation(out _); // Use the effective launch profile which has fallback logic @@ -1742,6 +1744,7 @@ private async Task CreateExecutableAsync(RenderedModelResource er, ILogger resou // Build the base paths for certificate output in the DCP session directory. var certificatesRootDir = Path.Join(_locations.DcpSessionDir, exe.Name()); var bundleOutputPath = Path.Join(certificatesRootDir, "cert.pem"); + var customBundleOutputPath = Path.Join(certificatesRootDir, "bundles"); var certificatesOutputPath = Path.Join(certificatesRootDir, "certs"); var baseServerAuthOutputPath = Path.Join(certificatesRootDir, "private"); @@ -1765,6 +1768,7 @@ private async Task CreateExecutableAsync(RenderedModelResource er, ILogger resou CertificateBundlePath = ReferenceExpression.Create($"{bundleOutputPath}"), // Build the SSL_CERT_DIR value by combining the new certs directory with any existing directories. CertificateDirectoriesPath = ReferenceExpression.Create($"{string.Join(Path.PathSeparator, dirs)}"), + RootCertificatesPath = certificatesRootDir, }; }) .WithHttpsCertificateConfig(cert => new() @@ -1794,6 +1798,19 @@ private async Task CreateExecutableAsync(RenderedModelResource er, ILogger resou }).DistinctBy(cert => cert.Thumbprint).ToList(), ContinueOnError = true, }; + + if (certificateTrustConfiguration.CustomBundlesFactories.Count > 0) + { + Directory.CreateDirectory(customBundleOutputPath); + } + + foreach (var bundleFactory in certificateTrustConfiguration.CustomBundlesFactories) + { + var bundleId = bundleFactory.Key; + var bundleBytes = await bundleFactory.Value(certificateTrustConfiguration.Certificates, cancellationToken).ConfigureAwait(false); + + File.WriteAllBytes(Path.Join(customBundleOutputPath, bundleId), bundleBytes); + } } exe.Spec.PemCertificates = pemCertificates; @@ -2155,6 +2172,8 @@ private async Task CreateContainerAsync(RenderedModelResource cr, ILogger resour CertificateBundlePath = ReferenceExpression.Create($"{certificatesDestination}/cert.pem"), // Build Linux PATH style colon-separated list of directories CertificateDirectoriesPath = ReferenceExpression.Create($"{string.Join(':', dirs)}"), + RootCertificatesPath = certificatesDestination, + IsContainer = true, }; }) .WithHttpsCertificateConfig(cert => new() @@ -2167,6 +2186,8 @@ private async Task CreateContainerAsync(RenderedModelResource cr, ILogger resour .BuildAsync(_executionContext, resourceLogger, cancellationToken) .ConfigureAwait(false); + List customBundleFiles = new(); + // Add the certificates to the executable spec so they'll be placed in the DCP config ContainerPemCertificates? pemCertificates = null; if (configuration.TryGetAdditionalData(out var certificateTrustConfiguration) @@ -2194,6 +2215,19 @@ private async Task CreateContainerAsync(RenderedModelResource cr, ILogger resour // Group by common directory to avoid creating multiple file system entries for the same root directory. pemCertificates.OverwriteBundlePaths = bundlePaths; } + + foreach (var bundleFactory in certificateTrustConfiguration.CustomBundlesFactories) + { + var bundleId = bundleFactory.Key; + var bundleBytes = await bundleFactory.Value(certificateTrustConfiguration.Certificates, cancellationToken).ConfigureAwait(false); + + customBundleFiles.Add(new ContainerFileSystemEntry + { + Name = bundleId, + Type = ContainerFileSystemEntryType.File, + RawContents = Convert.ToBase64String(bundleBytes), + }); + } } spec.PemCertificates = pemCertificates; @@ -2222,6 +2256,22 @@ private async Task CreateContainerAsync(RenderedModelResource cr, ILogger resour buildCreateFilesContext, cancellationToken).ConfigureAwait(false); + if (customBundleFiles.Count > 0) + { + createFiles.Add(new ContainerCreateFileSystem + { + Destination = certificatesDestination, + Entries = [ + new ContainerFileSystemEntry + { + Name = "bundles", + Type = ContainerFileSystemEntryType.Directory, + Entries = customBundleFiles, + }, + ], + }); + } + if (tlsCertificateConfiguration is not null) { var thumbprint = tlsCertificateConfiguration.Certificate.Thumbprint; diff --git a/src/Aspire.Hosting/buildTransitive/Aspire.Hosting.targets b/src/Aspire.Hosting/buildTransitive/Aspire.Hosting.targets new file mode 100644 index 00000000000..39a2d820fb0 --- /dev/null +++ b/src/Aspire.Hosting/buildTransitive/Aspire.Hosting.targets @@ -0,0 +1,12 @@ + + + + false + <_AspireIntegrationAnalyzerAssembly Condition="'$(_AspireIntegrationAnalyzerAssembly)' == ''">$(MSBuildThisFileDirectory)Aspire.Hosting.Integration.Analyzers.dll + + + + + + + diff --git a/src/Directory.Build.targets b/src/Directory.Build.targets index 828c0f7d33d..63c1108cf71 100644 --- a/src/Directory.Build.targets +++ b/src/Directory.Build.targets @@ -3,6 +3,7 @@ true $(MSBuildProjectDirectory)/api/$(AssemblyName).cs + true @@ -15,17 +16,15 @@ - - + + OutputItemType="Analyzer" /> + diff --git a/src/Shared/DashboardConfigNames.cs b/src/Shared/DashboardConfigNames.cs index 80abe566137..d8ef0d782cc 100644 --- a/src/Shared/DashboardConfigNames.cs +++ b/src/Shared/DashboardConfigNames.cs @@ -14,6 +14,7 @@ internal static class DashboardConfigNames public static readonly ConfigName DashboardConfigFilePathName = new(KnownConfigNames.DashboardConfigFilePath); public static readonly ConfigName DashboardFileConfigDirectoryName = new(KnownConfigNames.DashboardFileConfigDirectory); public static readonly ConfigName DashboardAIDisabledName = new(KnownConfigNames.DashboardAIDisabled); + public static readonly ConfigName DashboardAspireApiEnabledName = new(KnownConfigNames.DashboardApiEnabled); public static readonly ConfigName ResourceServiceUrlName = new(KnownConfigNames.ResourceServiceEndpointUrl); public static readonly ConfigName ForwardedHeaders = new(KnownConfigNames.DashboardForwardedHeadersEnabled); diff --git a/src/Shared/KnownConfigNames.cs b/src/Shared/KnownConfigNames.cs index d1b8af9fe23..57d3f2dbe54 100644 --- a/src/Shared/KnownConfigNames.cs +++ b/src/Shared/KnownConfigNames.cs @@ -18,6 +18,7 @@ internal static class KnownConfigNames public const string DashboardConfigFilePath = "ASPIRE_DASHBOARD_CONFIG_FILE_PATH"; public const string DashboardFileConfigDirectory = "ASPIRE_DASHBOARD_FILE_CONFIG_DIRECTORY"; public const string DashboardAIDisabled = "ASPIRE_DASHBOARD_AI_DISABLED"; + public const string DashboardApiEnabled = "ASPIRE_DASHBOARD_API_ENABLED"; public const string DashboardForwardedHeadersEnabled = "ASPIRE_DASHBOARD_FORWARDEDHEADERS_ENABLED"; public const string ShowDashboardResources = "ASPIRE_SHOW_DASHBOARD_RESOURCES"; diff --git a/tests/Aspire.Cli.EndToEnd.Tests/CertificatesCommandTests.cs b/tests/Aspire.Cli.EndToEnd.Tests/CertificatesCommandTests.cs new file mode 100644 index 00000000000..9c4e0da1972 --- /dev/null +++ b/tests/Aspire.Cli.EndToEnd.Tests/CertificatesCommandTests.cs @@ -0,0 +1,180 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Aspire.Cli.EndToEnd.Tests.Helpers; +using Aspire.Cli.Tests.Utils; +using Hex1b.Automation; +using Xunit; + +namespace Aspire.Cli.EndToEnd.Tests; + +/// +/// End-to-end tests for Aspire CLI certificates command, testing +/// certificate clean and trust operations in a Docker container. +/// +public sealed class CertificatesCommandTests(ITestOutputHelper output) +{ + [Fact] + public async Task CertificatesTrust_WithUntrustedCert_TrustsCertificate() + { + var repoRoot = CliE2ETestHelpers.GetRepoRoot(); + var installMode = CliE2ETestHelpers.DetectDockerInstallMode(repoRoot); + var workspace = TemporaryWorkspace.Create(output); + + using var terminal = CliE2ETestHelpers.CreateDockerTestTerminal(repoRoot, installMode, output, workspace: workspace); + + var pendingRun = terminal.RunAsync(TestContext.Current.CancellationToken); + + // Pattern for successful trust output + var trustSuccessPattern = new CellPatternSearcher() + .Find("trusted successfully"); + + // Pattern for doctor showing trusted after fix + var trustedPattern = new CellPatternSearcher() + .Find("certificate is trusted"); + + var counter = new SequenceCounter(); + var sequenceBuilder = new Hex1bTerminalInputSequenceBuilder(); + + sequenceBuilder.PrepareDockerEnvironment(counter, workspace); + sequenceBuilder.InstallAspireCliInDocker(installMode, counter); + + // Generate dev certs WITHOUT trust (creates untrusted cert) + sequenceBuilder + .Type("dotnet dev-certs https 2>/dev/null || true") + .Enter() + .WaitForSuccessPrompt(counter); + + // Configure SSL_CERT_DIR so trust detection works properly on Linux + sequenceBuilder.ConfigureSslCertDir(counter); + + // Run aspire certs trust — should trust the existing cert + sequenceBuilder + .Type("aspire certs trust") + .Enter() + .WaitUntil(s => trustSuccessPattern.Search(s).Count > 0, TimeSpan.FromSeconds(60)) + .WaitForSuccessPrompt(counter); + + // Verify doctor now shows the certificate as trusted + sequenceBuilder + .Type("aspire doctor") + .Enter() + .WaitUntil(s => trustedPattern.Search(s).Count > 0, TimeSpan.FromSeconds(60)) + .WaitForSuccessPrompt(counter) + .Type("exit") + .Enter(); + + var sequence = sequenceBuilder.Build(); + + await sequence.ApplyAsync(terminal, TestContext.Current.CancellationToken); + + await pendingRun; + } + + [Fact] + public async Task CertificatesClean_RemovesCertificates() + { + var repoRoot = CliE2ETestHelpers.GetRepoRoot(); + var installMode = CliE2ETestHelpers.DetectDockerInstallMode(repoRoot); + var workspace = TemporaryWorkspace.Create(output); + + using var terminal = CliE2ETestHelpers.CreateDockerTestTerminal(repoRoot, installMode, output, workspace: workspace); + + var pendingRun = terminal.RunAsync(TestContext.Current.CancellationToken); + + // Pattern for successful clean + var cleanedPattern = new CellPatternSearcher() + .Find("cleaned successfully"); + + // Pattern to verify doctor shows no cert after clean + var noCertPattern = new CellPatternSearcher() + .Find("No HTTPS development certificate"); + + var counter = new SequenceCounter(); + var sequenceBuilder = new Hex1bTerminalInputSequenceBuilder(); + + sequenceBuilder.PrepareDockerEnvironment(counter, workspace); + sequenceBuilder.InstallAspireCliInDocker(installMode, counter); + + // Generate dev certs first + sequenceBuilder + .Type("dotnet dev-certs https --trust 2>/dev/null || dotnet dev-certs https") + .Enter() + .WaitForSuccessPrompt(counter); + + sequenceBuilder.ConfigureSslCertDir(counter); + + // Run aspire certs clean + sequenceBuilder + .Type("aspire certs clean") + .Enter() + .WaitUntil(s => cleanedPattern.Search(s).Count > 0, TimeSpan.FromSeconds(60)) + .WaitForSuccessPrompt(counter); + + // Verify doctor now shows no certificate + sequenceBuilder + .Type("aspire doctor") + .Enter() + .WaitUntil(s => noCertPattern.Search(s).Count > 0, TimeSpan.FromSeconds(60)) + .WaitForSuccessPrompt(counter) + .Type("exit") + .Enter(); + + var sequence = sequenceBuilder.Build(); + + await sequence.ApplyAsync(terminal, TestContext.Current.CancellationToken); + + await pendingRun; + } + + [Fact] + public async Task CertificatesTrust_WithNoCert_CreatesAndTrustsCertificate() + { + var repoRoot = CliE2ETestHelpers.GetRepoRoot(); + var installMode = CliE2ETestHelpers.DetectDockerInstallMode(repoRoot); + var workspace = TemporaryWorkspace.Create(output); + + using var terminal = CliE2ETestHelpers.CreateDockerTestTerminal(repoRoot, installMode, output, workspace: workspace); + + var pendingRun = terminal.RunAsync(TestContext.Current.CancellationToken); + + // Pattern for successful trust + var trustSuccessPattern = new CellPatternSearcher() + .Find("trusted successfully"); + + // Pattern for doctor showing trusted + var trustedPattern = new CellPatternSearcher() + .Find("certificate is trusted"); + + var counter = new SequenceCounter(); + var sequenceBuilder = new Hex1bTerminalInputSequenceBuilder(); + + sequenceBuilder.PrepareDockerEnvironment(counter, workspace); + sequenceBuilder.InstallAspireCliInDocker(installMode, counter); + + // Configure SSL_CERT_DIR so trust detection works properly + sequenceBuilder.ConfigureSslCertDir(counter); + + // Run aspire certs trust with NO pre-existing cert — should create and trust + sequenceBuilder + .Type("aspire certs trust") + .Enter() + .WaitUntil(s => trustSuccessPattern.Search(s).Count > 0, TimeSpan.FromSeconds(60)) + .WaitForSuccessPrompt(counter); + + // Verify doctor now shows the certificate as trusted + sequenceBuilder + .Type("aspire doctor") + .Enter() + .WaitUntil(s => trustedPattern.Search(s).Count > 0, TimeSpan.FromSeconds(60)) + .WaitForSuccessPrompt(counter) + .Type("exit") + .Enter(); + + var sequence = sequenceBuilder.Build(); + + await sequence.ApplyAsync(terminal, TestContext.Current.CancellationToken); + + await pendingRun; + } +} diff --git a/tests/Aspire.Cli.EndToEnd.Tests/TypeScriptStarterTemplateTests.cs b/tests/Aspire.Cli.EndToEnd.Tests/TypeScriptStarterTemplateTests.cs index 38fde104a2e..243aa237a83 100644 --- a/tests/Aspire.Cli.EndToEnd.Tests/TypeScriptStarterTemplateTests.cs +++ b/tests/Aspire.Cli.EndToEnd.Tests/TypeScriptStarterTemplateTests.cs @@ -39,6 +39,24 @@ public async Task CreateAndRunTypeScriptStarterProject() // Step 1: Create project using aspire new, selecting the Express/React template sequenceBuilder.AspireNew("TsStarterApp", counter, template: AspireTemplate.ExpressReact); + // Step 1.5: Verify starter creation also restored the generated TypeScript SDK. + sequenceBuilder.ExecuteCallback(() => + { + var projectRoot = Path.Combine(workspace.WorkspaceRoot.FullName, "TsStarterApp"); + var modulesDir = Path.Combine(projectRoot, ".modules"); + + if (!Directory.Exists(modulesDir)) + { + throw new InvalidOperationException($".modules directory was not created at {modulesDir}"); + } + + var aspireModulePath = Path.Combine(modulesDir, "aspire.ts"); + if (!File.Exists(aspireModulePath)) + { + throw new InvalidOperationException($"Expected generated file not found: {aspireModulePath}"); + } + }); + // Step 2: Navigate into the project and start it in background with JSON output sequenceBuilder .Type("cd TsStarterApp") diff --git a/tests/Aspire.Cli.Tests/Certificates/CertificateServiceTests.cs b/tests/Aspire.Cli.Tests/Certificates/CertificateServiceTests.cs index 892a901813d..d6677f2a846 100644 --- a/tests/Aspire.Cli.Tests/Certificates/CertificateServiceTests.cs +++ b/tests/Aspire.Cli.Tests/Certificates/CertificateServiceTests.cs @@ -3,10 +3,10 @@ using System.Runtime.InteropServices; using Aspire.Cli.Certificates; -using Aspire.Cli.DotNet; using Aspire.Cli.Tests.Utils; -using Microsoft.Extensions.DependencyInjection; +using Microsoft.AspNetCore.Certificates.Generation; using Microsoft.AspNetCore.InternalTesting; +using Microsoft.Extensions.DependencyInjection; namespace Aspire.Cli.Tests.Certificates; @@ -22,14 +22,14 @@ public async Task EnsureCertificatesTrustedAsync_WithFullyTrustedCert_ReturnsEmp { return new TestCertificateToolRunner { - CheckHttpCertificateMachineReadableAsyncCallback = (_, _) => + CheckHttpCertificateCallback = () => { - return (0, new CertificateTrustResult + return new CertificateTrustResult { HasCertificates = true, - TrustLevel = DevCertTrustLevel.Full, - Certificates = [new DevCertInfo { Version = 5, TrustLevel = DevCertTrustLevel.Full, IsHttpsDevelopmentCertificate = true, ValidityNotBefore = DateTimeOffset.Now.AddDays(-1), ValidityNotAfter = DateTimeOffset.Now.AddDays(365) }] - }); + TrustLevel = CertificateManager.TrustLevel.Full, + Certificates = [new DevCertInfo { Version = 5, TrustLevel = CertificateManager.TrustLevel.Full, IsHttpsDevelopmentCertificate = true, ValidityNotBefore = DateTimeOffset.Now.AddDays(-1), ValidityNotAfter = DateTimeOffset.Now.AddDays(365) }] + }; } }; }; @@ -57,30 +57,30 @@ public async Task EnsureCertificatesTrustedAsync_WithNotTrustedCert_RunsTrustOpe var callCount = 0; return new TestCertificateToolRunner { - CheckHttpCertificateMachineReadableAsyncCallback = (_, _) => + CheckHttpCertificateCallback = () => { callCount++; // First call returns not trusted, second call (after trust) returns fully trusted if (callCount == 1) { - return (0, new CertificateTrustResult + return new CertificateTrustResult { HasCertificates = true, - TrustLevel = DevCertTrustLevel.None, - Certificates = [new DevCertInfo { Version = 5, TrustLevel = DevCertTrustLevel.None, IsHttpsDevelopmentCertificate = true, ValidityNotBefore = DateTimeOffset.Now.AddDays(-1), ValidityNotAfter = DateTimeOffset.Now.AddDays(365) }] - }); + TrustLevel = CertificateManager.TrustLevel.None, + Certificates = [new DevCertInfo { Version = 5, TrustLevel = CertificateManager.TrustLevel.None, IsHttpsDevelopmentCertificate = true, ValidityNotBefore = DateTimeOffset.Now.AddDays(-1), ValidityNotAfter = DateTimeOffset.Now.AddDays(365) }] + }; } - return (0, new CertificateTrustResult + return new CertificateTrustResult { HasCertificates = true, - TrustLevel = DevCertTrustLevel.Full, - Certificates = [new DevCertInfo { Version = 5, TrustLevel = DevCertTrustLevel.Full, IsHttpsDevelopmentCertificate = true, ValidityNotBefore = DateTimeOffset.Now.AddDays(-1), ValidityNotAfter = DateTimeOffset.Now.AddDays(365) }] - }); + TrustLevel = CertificateManager.TrustLevel.Full, + Certificates = [new DevCertInfo { Version = 5, TrustLevel = CertificateManager.TrustLevel.Full, IsHttpsDevelopmentCertificate = true, ValidityNotBefore = DateTimeOffset.Now.AddDays(-1), ValidityNotAfter = DateTimeOffset.Now.AddDays(365) }] + }; }, - TrustHttpCertificateAsyncCallback = (_, _) => + TrustHttpCertificateCallback = () => { trustCalled = true; - return 0; + return EnsureCertificateResult.ExistingHttpsCertificateTrusted; } }; }; @@ -112,14 +112,14 @@ public async Task EnsureCertificatesTrustedAsync_WithPartiallyTrustedCert_SetsSs { return new TestCertificateToolRunner { - CheckHttpCertificateMachineReadableAsyncCallback = (_, _) => + CheckHttpCertificateCallback = () => { - return (0, new CertificateTrustResult + return new CertificateTrustResult { HasCertificates = true, - TrustLevel = DevCertTrustLevel.Partial, - Certificates = [new DevCertInfo { Version = 5, TrustLevel = DevCertTrustLevel.Partial, IsHttpsDevelopmentCertificate = true, ValidityNotBefore = DateTimeOffset.Now.AddDays(-1), ValidityNotAfter = DateTimeOffset.Now.AddDays(365) }] - }); + TrustLevel = CertificateManager.TrustLevel.Partial, + Certificates = [new DevCertInfo { Version = 5, TrustLevel = CertificateManager.TrustLevel.Partial, IsHttpsDevelopmentCertificate = true, ValidityNotBefore = DateTimeOffset.Now.AddDays(-1), ValidityNotAfter = DateTimeOffset.Now.AddDays(365) }] + }; } }; }; @@ -148,30 +148,30 @@ public async Task EnsureCertificatesTrustedAsync_WithNoCertificates_RunsTrustOpe var callCount = 0; return new TestCertificateToolRunner { - CheckHttpCertificateMachineReadableAsyncCallback = (_, _) => + CheckHttpCertificateCallback = () => { callCount++; // First call returns no certificates, second call (after trust) returns fully trusted if (callCount == 1) { - return (0, new CertificateTrustResult + return new CertificateTrustResult { HasCertificates = false, TrustLevel = null, Certificates = [] - }); + }; } - return (0, new CertificateTrustResult + return new CertificateTrustResult { HasCertificates = true, - TrustLevel = DevCertTrustLevel.Full, - Certificates = [new DevCertInfo { Version = 5, TrustLevel = DevCertTrustLevel.Full, IsHttpsDevelopmentCertificate = true, ValidityNotBefore = DateTimeOffset.Now.AddDays(-1), ValidityNotAfter = DateTimeOffset.Now.AddDays(365) }] - }); + TrustLevel = CertificateManager.TrustLevel.Full, + Certificates = [new DevCertInfo { Version = 5, TrustLevel = CertificateManager.TrustLevel.Full, IsHttpsDevelopmentCertificate = true, ValidityNotBefore = DateTimeOffset.Now.AddDays(-1), ValidityNotAfter = DateTimeOffset.Now.AddDays(365) }] + }; }, - TrustHttpCertificateAsyncCallback = (_, _) => + TrustHttpCertificateCallback = () => { trustCalled = true; - return 0; + return EnsureCertificateResult.NewHttpsCertificateTrusted; } }; }; @@ -196,20 +196,18 @@ public async Task EnsureCertificatesTrustedAsync_TrustOperationFails_DisplaysWar { return new TestCertificateToolRunner { - CheckHttpCertificateMachineReadableAsyncCallback = (_, _) => + CheckHttpCertificateCallback = () => { - return (0, new CertificateTrustResult + return new CertificateTrustResult { HasCertificates = true, - TrustLevel = DevCertTrustLevel.None, - Certificates = [new DevCertInfo { Version = 5, TrustLevel = DevCertTrustLevel.None, IsHttpsDevelopmentCertificate = true, ValidityNotBefore = DateTimeOffset.Now.AddDays(-1), ValidityNotAfter = DateTimeOffset.Now.AddDays(365) }] - }); + TrustLevel = CertificateManager.TrustLevel.None, + Certificates = [new DevCertInfo { Version = 5, TrustLevel = CertificateManager.TrustLevel.None, IsHttpsDevelopmentCertificate = true, ValidityNotBefore = DateTimeOffset.Now.AddDays(-1), ValidityNotAfter = DateTimeOffset.Now.AddDays(365) }] + }; }, - TrustHttpCertificateAsyncCallback = (options, _) => + TrustHttpCertificateCallback = () => { - Assert.NotNull(options.StandardErrorCallback); - options.StandardErrorCallback!.Invoke("There was an error trusting the HTTPS developer certificate. It will be trusted by some clients but not by others."); - return 4; + return EnsureCertificateResult.FailedToTrustTheCertificate; } }; }; @@ -225,31 +223,33 @@ public async Task EnsureCertificatesTrustedAsync_TrustOperationFails_DisplaysWar private sealed class TestCertificateToolRunner : ICertificateToolRunner { - public Func? CheckHttpCertificateMachineReadableAsyncCallback { get; set; } - public Func? TrustHttpCertificateAsyncCallback { get; set; } + public Func? CheckHttpCertificateCallback { get; set; } + public Func? TrustHttpCertificateCallback { get; set; } - public Task<(int ExitCode, CertificateTrustResult? Result)> CheckHttpCertificateMachineReadableAsync(DotNetCliRunnerInvocationOptions options, CancellationToken cancellationToken) + public CertificateTrustResult CheckHttpCertificate() { - if (CheckHttpCertificateMachineReadableAsyncCallback != null) + if (CheckHttpCertificateCallback is not null) { - return Task.FromResult(CheckHttpCertificateMachineReadableAsyncCallback(options, cancellationToken)); + return CheckHttpCertificateCallback(); } // Default: Return a fully trusted certificate result - var result = new CertificateTrustResult + return new CertificateTrustResult { HasCertificates = true, - TrustLevel = DevCertTrustLevel.Full, + TrustLevel = CertificateManager.TrustLevel.Full, Certificates = [] }; - return Task.FromResult<(int, CertificateTrustResult?)>((0, result)); } - public Task TrustHttpCertificateAsync(DotNetCliRunnerInvocationOptions options, CancellationToken cancellationToken) + public EnsureCertificateResult TrustHttpCertificate() { - return TrustHttpCertificateAsyncCallback != null - ? Task.FromResult(TrustHttpCertificateAsyncCallback(options, cancellationToken)) - : Task.FromResult(0); + return TrustHttpCertificateCallback is not null + ? TrustHttpCertificateCallback() + : EnsureCertificateResult.ExistingHttpsCertificateTrusted; } + + public CertificateCleanResult CleanHttpCertificate() + => new CertificateCleanResult { Success = true }; } } diff --git a/tests/Aspire.Cli.Tests/Certificates/NativeCertificateToolRunnerTests.cs b/tests/Aspire.Cli.Tests/Certificates/NativeCertificateToolRunnerTests.cs new file mode 100644 index 00000000000..415c677034a --- /dev/null +++ b/tests/Aspire.Cli.Tests/Certificates/NativeCertificateToolRunnerTests.cs @@ -0,0 +1,97 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Security.Cryptography.X509Certificates; +using Aspire.Cli.Certificates; +using Microsoft.AspNetCore.Certificates.Generation; +using Microsoft.Extensions.Logging.Abstractions; + +namespace Aspire.Cli.Tests.Certificates; + +public class NativeCertificateToolRunnerTests +{ + [Fact] + public void TrustHttpCertificateOnLinux_WithNoCurrentCertificate_CreatesAndTrustsCertificate() + { + var certificateManager = new TestCertificateManager(); + var runner = new NativeCertificateToolRunner(certificateManager, isLinux: () => true); + + var result = runner.TrustHttpCertificateOnLinux([], DateTimeOffset.UtcNow); + + Assert.Equal(EnsureCertificateResult.NewHttpsCertificateTrusted, result); + Assert.True(certificateManager.SaveCalled); + Assert.True(certificateManager.TrustCalled); + } + + [Fact] + public void TrustHttpCertificateOnLinux_WithExistingCurrentCertificate_TrustsWithoutSaving() + { + var certificateManager = new TestCertificateManager(); + using var certificate = certificateManager.CreateAspNetCoreHttpsDevelopmentCertificate( + DateTimeOffset.UtcNow.AddDays(-1), + DateTimeOffset.UtcNow.AddDays(365)); + var runner = new NativeCertificateToolRunner(certificateManager, isLinux: () => true); + + var result = runner.TrustHttpCertificateOnLinux([certificate], DateTimeOffset.UtcNow); + + Assert.Equal(EnsureCertificateResult.ExistingHttpsCertificateTrusted, result); + Assert.False(certificateManager.SaveCalled); + Assert.True(certificateManager.TrustCalled); + } + + [Fact] + public void TrustHttpCertificateOnLinux_WithOnlyOlderCertificate_CreatesCurrentCertificate() + { + var currentVersionManager = new TestCertificateManager(CertificateManager.CurrentAspNetCoreCertificateVersion); + var olderVersionManager = new TestCertificateManager(CertificateManager.CurrentAspNetCoreCertificateVersion - 1); + using var olderCertificate = olderVersionManager.CreateAspNetCoreHttpsDevelopmentCertificate( + DateTimeOffset.UtcNow.AddDays(-1), + DateTimeOffset.UtcNow.AddDays(365)); + var runner = new NativeCertificateToolRunner(currentVersionManager, isLinux: () => true); + + var result = runner.TrustHttpCertificateOnLinux([olderCertificate], DateTimeOffset.UtcNow); + + Assert.Equal(EnsureCertificateResult.NewHttpsCertificateTrusted, result); + Assert.True(currentVersionManager.SaveCalled); + Assert.True(currentVersionManager.TrustCalled); + } + + private sealed class TestCertificateManager(int version = CertificateManager.CurrentAspNetCoreCertificateVersion) + : CertificateManager(NullLogger.Instance, CertificateManager.LocalhostHttpsDistinguishedName, version, version) + { + public bool SaveCalled { get; private set; } + public bool TrustCalled { get; private set; } + + protected override X509Certificate2 SaveCertificateCore(X509Certificate2 certificate, StoreName storeName, StoreLocation storeLocation) + { + SaveCalled = true; + return certificate; + } + + protected override TrustLevel TrustCertificateCore(X509Certificate2 certificate) + { + TrustCalled = true; + return TrustLevel.Full; + } + + public override TrustLevel GetTrustLevel(X509Certificate2 certificate) => TrustLevel.None; + + internal override bool IsExportable(X509Certificate2 c) => true; + + protected override void RemoveCertificateFromTrustedRoots(X509Certificate2 certificate) + { + } + + protected override IList GetCertificatesToRemove(StoreName storeName, StoreLocation storeLocation) => []; + + protected override void CreateDirectoryWithPermissions(string directoryPath) + { + } + + internal override CheckCertificateStateResult CheckCertificateState(X509Certificate2 candidate) => new(true, null); + + internal override void CorrectCertificateState(X509Certificate2 candidate) + { + } + } +} diff --git a/tests/Aspire.Cli.Tests/Commands/CertificatesCommandTests.cs b/tests/Aspire.Cli.Tests/Commands/CertificatesCommandTests.cs new file mode 100644 index 00000000000..26b9024e916 --- /dev/null +++ b/tests/Aspire.Cli.Tests/Commands/CertificatesCommandTests.cs @@ -0,0 +1,56 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Aspire.Cli.Tests.Utils; +using Microsoft.AspNetCore.InternalTesting; +using Microsoft.Extensions.DependencyInjection; + +namespace Aspire.Cli.Tests.Commands; + +public class CertificatesCommandTests(ITestOutputHelper outputHelper) +{ + [Fact] + public async Task CertificatesCommand_Help_ShowsCertificatesSubcommand() + { + using var workspace = TemporaryWorkspace.Create(outputHelper); + var services = CliTestHelper.CreateServiceCollection(workspace, outputHelper); + var provider = services.BuildServiceProvider(); + + var command = provider.GetRequiredService(); + var result = command.Parse("certs --help"); + + var exitCode = await result.InvokeAsync().DefaultTimeout(); + + Assert.Equal(ExitCodeConstants.Success, exitCode); + } + + [Fact] + public async Task CertificatesCommand_CleanSubcommand_ShowsInHelp() + { + using var workspace = TemporaryWorkspace.Create(outputHelper); + var services = CliTestHelper.CreateServiceCollection(workspace, outputHelper); + var provider = services.BuildServiceProvider(); + + var command = provider.GetRequiredService(); + var result = command.Parse("certs clean --help"); + + var exitCode = await result.InvokeAsync().DefaultTimeout(); + + Assert.Equal(ExitCodeConstants.Success, exitCode); + } + + [Fact] + public async Task CertificatesCommand_TrustSubcommand_ShowsInHelp() + { + using var workspace = TemporaryWorkspace.Create(outputHelper); + var services = CliTestHelper.CreateServiceCollection(workspace, outputHelper); + var provider = services.BuildServiceProvider(); + + var command = provider.GetRequiredService(); + var result = command.Parse("certs trust --help"); + + var exitCode = await result.InvokeAsync().DefaultTimeout(); + + Assert.Equal(ExitCodeConstants.Success, exitCode); + } +} diff --git a/tests/Aspire.Cli.Tests/Commands/DotNetSdkCheckTests.cs b/tests/Aspire.Cli.Tests/Commands/DotNetSdkCheckTests.cs new file mode 100644 index 00000000000..aa8c086ffae --- /dev/null +++ b/tests/Aspire.Cli.Tests/Commands/DotNetSdkCheckTests.cs @@ -0,0 +1,168 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Aspire.Cli.Projects; +using Aspire.Cli.Tests.TestServices; +using Aspire.Cli.Tests.Utils; +using Aspire.Cli.Utils.EnvironmentChecker; +using Microsoft.AspNetCore.InternalTesting; +using Microsoft.Extensions.Logging.Abstractions; + +namespace Aspire.Cli.Tests.Commands; + +public class DotNetSdkCheckTests(ITestOutputHelper outputHelper) +{ + [Fact] + public async Task CheckAsync_SkipsCheck_WhenNoAppHostFound() + { + // No apphost in settings — skip .NET SDK check entirely + using var workspace = TemporaryWorkspace.Create(outputHelper); + var check = CreateDotNetSdkCheck(workspace, + sdkCheckResult: (false, null, "10.0.100"), + languageDiscovery: new TestLanguageDiscovery()); + + var results = await check.CheckAsync().DefaultTimeout(); + + Assert.Empty(results); + } + + [Fact] + public async Task CheckAsync_SkipsCheck_WhenNonDotNetAppHostFound() + { + using var workspace = TemporaryWorkspace.Create(outputHelper); + var check = CreateDotNetSdkCheck(workspace, + appHostFileName: "apphost.ts", + sdkCheckResult: (false, null, "10.0.100")); + + var results = await check.CheckAsync().DefaultTimeout(); + + Assert.Empty(results); + } + + [Fact] + public async Task CheckAsync_RunsCheck_WhenDotNetAppHostFound() + { + using var workspace = TemporaryWorkspace.Create(outputHelper); + var check = CreateDotNetSdkCheck(workspace, appHostFileName: "MyAppHost.csproj"); + + var results = await check.CheckAsync().DefaultTimeout(); + } + + [Fact] + public async Task CheckAsync_ReturnsFail_WhenDotNetAppHostFound_AndSdkNotInstalled() + { + using var workspace = TemporaryWorkspace.Create(outputHelper); + var check = CreateDotNetSdkCheck(workspace, + appHostFileName: "MyAppHost.csproj", + sdkCheckResult: (false, null, "10.0.100")); + + var results = await check.CheckAsync().DefaultTimeout(); + + Assert.Single(results); + Assert.Equal(EnvironmentCheckStatus.Fail, results[0].Status); + Assert.Contains(".NET SDK not found", results[0].Message); + } + + [Fact] + public async Task CheckAsync_SkipsCheck_WhenNoSettingsFileExists() + { + // No settings.json — can't determine language, skip .NET check + using var workspace = TemporaryWorkspace.Create(outputHelper); + var check = CreateDotNetSdkCheck(workspace); + + var results = await check.CheckAsync().DefaultTimeout(); + + Assert.Empty(results); + } + + [Fact] + public async Task CheckAsync_SkipsCheck_WhenLanguageNotRecognized() + { + using var workspace = TemporaryWorkspace.Create(outputHelper); + var check = CreateDotNetSdkCheck(workspace, appHostFileName: "unknown.xyz"); + + var results = await check.CheckAsync().DefaultTimeout(); + + // Unrecognized file — skip .NET check + Assert.Empty(results); + } + + [Theory] + [InlineData("MyAppHost.csproj", true)] + [InlineData("apphost.cs", true)] + [InlineData("readme.txt", false)] + [InlineData("src/MyAppHost.csproj", true)] + [InlineData("src/AppHost/apphost.cs", true)] + [InlineData("src/deep/nested/readme.txt", false)] + [InlineData("a/b/c/d/e/f/apphost.cs", false)] + public async Task CheckAsync_FallsBackToFileSystemScan_WhenNoSettingsFile(string relativePath, bool shouldRunCheck) + { + using var workspace = TemporaryWorkspace.Create(outputHelper); + var check = CreateDotNetSdkCheck(workspace); + + // Create the file on disk (with nested directories) so FindFirstFile can discover it + var filePath = Path.Combine(workspace.WorkspaceRoot.FullName, relativePath.Replace('/', Path.DirectorySeparatorChar)); + Directory.CreateDirectory(Path.GetDirectoryName(filePath)!); + await File.WriteAllTextAsync(filePath, ""); + + var results = await check.CheckAsync().DefaultTimeout(); + + if (shouldRunCheck) + { + Assert.Single(results); + Assert.Equal(EnvironmentCheckStatus.Pass, results[0].Status); + } + else + { + Assert.Empty(results); + } + } + + private static readonly LanguageInfo s_typeScriptLanguage = new( + LanguageId: new LanguageId(KnownLanguageId.TypeScript), + DisplayName: "TypeScript (Node.js)", + PackageName: "Aspire.Hosting.CodeGeneration.TypeScript", + DetectionPatterns: ["apphost.ts"], + CodeGenerator: "TypeScript", + AppHostFileName: "apphost.ts"); + + private static CliExecutionContext CreateExecutionContext(TemporaryWorkspace workspace) => + new( + workingDirectory: workspace.WorkspaceRoot, + hivesDirectory: workspace.WorkspaceRoot.CreateSubdirectory(".aspire-hives"), + cacheDirectory: workspace.WorkspaceRoot.CreateSubdirectory(".aspire-cache"), + sdksDirectory: workspace.WorkspaceRoot.CreateSubdirectory(".aspire-sdks"), + logsDirectory: workspace.WorkspaceRoot.CreateSubdirectory(".aspire-logs"), + logFilePath: "test.log"); + + private static DotNetSdkCheck CreateDotNetSdkCheck( + TemporaryWorkspace workspace, + string? appHostFileName = null, + (bool Success, string? HighestVersion, string MinimumRequired)? sdkCheckResult = null, + ILanguageDiscovery? languageDiscovery = null) + { + var appHostFile = appHostFileName is not null + ? new FileInfo(Path.Combine(workspace.WorkspaceRoot.FullName, appHostFileName)) + : null; + + var sdkInstaller = new TestDotNetSdkInstaller(); + if (sdkCheckResult is var (success, highest, minimum)) + { + sdkInstaller.CheckAsyncCallback = _ => (success, highest, minimum); + } + + var projectLocator = new TestProjectLocator + { + GetAppHostFromSettingsAsyncCallback = _ => Task.FromResult(appHostFile) + }; + + var executionContext = CreateExecutionContext(workspace); + + return new DotNetSdkCheck( + sdkInstaller, + projectLocator, + languageDiscovery ?? new TestLanguageDiscovery(s_typeScriptLanguage), + executionContext, + NullLogger.Instance); + } +} diff --git a/tests/Aspire.Cli.Tests/Commands/ExecCommandTests.cs b/tests/Aspire.Cli.Tests/Commands/ExecCommandTests.cs index a435baef7ee..0f38143cbf2 100644 --- a/tests/Aspire.Cli.Tests/Commands/ExecCommandTests.cs +++ b/tests/Aspire.Cli.Tests/Commands/ExecCommandTests.cs @@ -177,6 +177,8 @@ public Task UseOrFindAppHostProjectFileAsync(FileInf { throw new Aspire.Cli.Projects.ProjectLocatorException("No project file found.", Aspire.Cli.Projects.ProjectLocatorFailureReason.NoProjectFileFound); } + + public Task GetAppHostFromSettingsAsync(CancellationToken cancellationToken = default) => Task.FromResult(null); } private sealed class MultipleProjectFilesProjectLocator : Aspire.Cli.Projects.IProjectLocator @@ -190,6 +192,8 @@ public Task UseOrFindAppHostProjectFileAsync(FileInf { throw new Aspire.Cli.Projects.ProjectLocatorException("Multiple project files found.", Aspire.Cli.Projects.ProjectLocatorFailureReason.MultipleProjectFilesFound); } + + public Task GetAppHostFromSettingsAsync(CancellationToken cancellationToken = default) => Task.FromResult(null); } private sealed class ProjectFileDoesNotExistLocator : Aspire.Cli.Projects.IProjectLocator @@ -203,5 +207,7 @@ public Task UseOrFindAppHostProjectFileAsync(FileInf { throw new Aspire.Cli.Projects.ProjectLocatorException("Project file does not exist.", Aspire.Cli.Projects.ProjectLocatorFailureReason.ProjectFileDoesntExist); } + + public Task GetAppHostFromSettingsAsync(CancellationToken cancellationToken = default) => Task.FromResult(null); } } diff --git a/tests/Aspire.Cli.Tests/Commands/ExtensionInternalCommandTests.cs b/tests/Aspire.Cli.Tests/Commands/ExtensionInternalCommandTests.cs index d7939daf7c8..74e24ae949d 100644 --- a/tests/Aspire.Cli.Tests/Commands/ExtensionInternalCommandTests.cs +++ b/tests/Aspire.Cli.Tests/Commands/ExtensionInternalCommandTests.cs @@ -240,6 +240,8 @@ public Task UseOrFindServiceProjectFileAsync( { throw new NotImplementedException(); } + + public Task GetAppHostFromSettingsAsync(CancellationToken cancellationToken = default) => Task.FromResult(null); } private sealed class MultipleProjectsProjectLocator : IProjectLocator @@ -293,6 +295,8 @@ public Task UseOrFindServiceProjectFileAsync( { throw new NotImplementedException(); } + + public Task GetAppHostFromSettingsAsync(CancellationToken cancellationToken = default) => Task.FromResult(null); } private sealed class NoProjectFileProjectLocator : IProjectLocator @@ -338,6 +342,8 @@ public Task UseOrFindServiceProjectFileAsync( { throw new NotImplementedException(); } + + public Task GetAppHostFromSettingsAsync(CancellationToken cancellationToken = default) => Task.FromResult(null); } private sealed class ThrowingProjectLocator : IProjectLocator @@ -383,5 +389,7 @@ public Task UseOrFindServiceProjectFileAsync( { throw new NotImplementedException(); } + + public Task GetAppHostFromSettingsAsync(CancellationToken cancellationToken = default) => Task.FromResult(null); } } diff --git a/tests/Aspire.Cli.Tests/Commands/NewCommandTests.cs b/tests/Aspire.Cli.Tests/Commands/NewCommandTests.cs index afbf6f97885..1ae966d7936 100644 --- a/tests/Aspire.Cli.Tests/Commands/NewCommandTests.cs +++ b/tests/Aspire.Cli.Tests/Commands/NewCommandTests.cs @@ -4,6 +4,7 @@ using Aspire.Cli.Utils; using Aspire.Cli.Certificates; using Aspire.Cli.Commands; +using Aspire.Cli.Configuration; using Aspire.Cli.Interaction; using Aspire.Cli.NuGet; using Aspire.Cli.Packaging; @@ -1273,6 +1274,143 @@ await File.WriteAllTextAsync(Path.Combine(context.TargetDirectory.FullName, "app Assert.DoesNotContain("://localhost", runProfile); } + [Fact] + public async Task NewCommandWithTypeScriptStarterGeneratesSdkArtifacts() + { + using var workspace = TemporaryWorkspace.Create(outputHelper); + + var buildAndGenerateCalled = false; + string? channelSeenByProject = null; + + var services = CliTestHelper.CreateServiceCollection(workspace, outputHelper, options => + { + options.DotNetCliRunnerFactory = _ => new TestDotNetCliRunner + { + SearchPackagesAsyncCallback = (dir, query, prerelease, take, skip, nugetSource, useCache, runnerOptions, cancellationToken) => + { + var package = new NuGetPackage + { + Id = "Aspire.ProjectTemplates", + Source = "nuget", + Version = "9.2.0" + }; + + return (0, new NuGetPackage[] { package }); + } + }; + + options.PackagingServiceFactory = _ => new NewCommandTestPackagingService + { + GetChannelsAsyncCallback = cancellationToken => + { + var dailyCache = new NewCommandTestFakeNuGetPackageCache + { + GetTemplatePackagesAsyncCallback = (dir, prerelease, nugetConfig, ct) => + { + var package = new NuGetPackage + { + Id = "Aspire.ProjectTemplates", + Source = "nuget", + Version = "9.2.0" + }; + + return Task.FromResult>([package]); + } + }; + + var dailyChannel = PackageChannel.CreateExplicitChannel("daily", PackageChannelQuality.Both, [], dailyCache); + return Task.FromResult>([dailyChannel]); + } + }; + }); + + services.AddSingleton(new TestTypeScriptStarterProjectFactory((directory, cancellationToken) => + { + buildAndGenerateCalled = true; + var config = AspireJsonConfiguration.Load(directory.FullName); + channelSeenByProject = config?.Channel; + + var modulesDir = Directory.CreateDirectory(Path.Combine(directory.FullName, ".modules")); + File.WriteAllText(Path.Combine(modulesDir.FullName, "aspire.ts"), "// generated sdk"); + + return Task.FromResult(true); + })); + + var provider = services.BuildServiceProvider(); + var command = provider.GetRequiredService(); + var result = command.Parse("new aspire-ts-starter --name TestApp --output . --channel daily --localhost-tld false"); + + var exitCode = await result.InvokeAsync().DefaultTimeout(); + + Assert.Equal(0, exitCode); + Assert.True(buildAndGenerateCalled); + Assert.Equal("daily", channelSeenByProject); + Assert.True(File.Exists(Path.Combine(workspace.WorkspaceRoot.FullName, ".modules", "aspire.ts"))); + } + + [Fact] + public async Task NewCommandWithTypeScriptStarterReturnsFailedToBuildArtifactsWhenSdkGenerationFails() + { + using var workspace = TemporaryWorkspace.Create(outputHelper); + + var interactionService = new TestInteractionService(); + + var services = CliTestHelper.CreateServiceCollection(workspace, outputHelper, options => + { + options.DotNetCliRunnerFactory = _ => new TestDotNetCliRunner + { + SearchPackagesAsyncCallback = (dir, query, prerelease, take, skip, nugetSource, useCache, runnerOptions, cancellationToken) => + { + var package = new NuGetPackage + { + Id = "Aspire.ProjectTemplates", + Source = "nuget", + Version = "9.2.0" + }; + + return (0, new NuGetPackage[] { package }); + } + }; + + options.PackagingServiceFactory = _ => new NewCommandTestPackagingService + { + GetChannelsAsyncCallback = cancellationToken => + { + var dailyCache = new NewCommandTestFakeNuGetPackageCache + { + GetTemplatePackagesAsyncCallback = (dir, prerelease, nugetConfig, ct) => + { + var package = new NuGetPackage + { + Id = "Aspire.ProjectTemplates", + Source = "nuget", + Version = "9.2.0" + }; + + return Task.FromResult>([package]); + } + }; + + var dailyChannel = PackageChannel.CreateExplicitChannel("daily", PackageChannelQuality.Both, [], dailyCache); + return Task.FromResult>([dailyChannel]); + } + }; + }); + + services.AddSingleton(interactionService); + services.AddSingleton(new TestTypeScriptStarterProjectFactory((directory, cancellationToken) => Task.FromResult(false))); + + var provider = services.BuildServiceProvider(); + var command = provider.GetRequiredService(); + var result = command.Parse("new aspire-ts-starter --name TestApp --output . --channel daily --localhost-tld false"); + + var exitCode = await result.InvokeAsync().DefaultTimeout(); + + Assert.Equal(ExitCodeConstants.FailedToBuildArtifacts, exitCode); + Assert.Single(interactionService.DisplayedErrors); + Assert.Equal("Automatic 'aspire restore' failed for the new TypeScript starter project. Run 'aspire restore' in the project directory for more details.", interactionService.DisplayedErrors[0]); + } + [Fact] public async Task NewCommandNonInteractiveDoesNotPrompt() { @@ -1506,3 +1644,101 @@ public Task ScaffoldAsync(ScaffoldContext context, CancellationToken cancellatio return Task.CompletedTask; } } + +internal sealed class TestTypeScriptStarterProjectFactory(Func> buildAndGenerateSdkAsync) : IAppHostProjectFactory +{ + private readonly TestTypeScriptStarterProject _project = new(buildAndGenerateSdkAsync); + + public IAppHostProject GetProject(LanguageInfo language) + { + ArgumentNullException.ThrowIfNull(language); + + if (!string.Equals(language.LanguageId, KnownLanguageId.TypeScript, StringComparison.Ordinal)) + { + throw new NotSupportedException($"No handler available for language '{language.LanguageId}'."); + } + + return _project; + } + + public IAppHostProject? TryGetProject(FileInfo appHostFile) + { + return appHostFile.Name.Equals("apphost.ts", StringComparison.OrdinalIgnoreCase) ? _project : null; + } + + public IAppHostProject GetProject(FileInfo appHostFile) + { + return TryGetProject(appHostFile) ?? throw new NotSupportedException($"No handler available for AppHost file '{appHostFile.Name}'."); + } +} + +internal sealed class TestTypeScriptStarterProject(Func> buildAndGenerateSdkAsync) : IAppHostProject, IGuestAppHostSdkGenerator +{ + public bool IsUnsupported { get; set; } + + public string LanguageId => KnownLanguageId.TypeScript; + + public string DisplayName => "TypeScript (Node.js)"; + + public string? AppHostFileName => "apphost.ts"; + + public Task GetDetectionPatternsAsync(CancellationToken cancellationToken = default) + { + return Task.FromResult(["apphost.ts"]); + } + + public bool CanHandle(FileInfo appHostFile) + { + return appHostFile.Name.Equals("apphost.ts", StringComparison.OrdinalIgnoreCase); + } + + public bool IsUsingProjectReferences(FileInfo appHostFile) + { + return false; + } + + public Task RunAsync(AppHostProjectContext context, CancellationToken cancellationToken) + { + throw new NotImplementedException(); + } + + public Task PublishAsync(PublishContext context, CancellationToken cancellationToken) + { + throw new NotImplementedException(); + } + + public Task ValidateAppHostAsync(FileInfo appHostFile, CancellationToken cancellationToken) + { + return Task.FromResult(new AppHostValidationResult(IsValid: CanHandle(appHostFile))); + } + + public Task AddPackageAsync(AddPackageContext context, CancellationToken cancellationToken) + { + throw new NotImplementedException(); + } + + public Task UpdatePackagesAsync(UpdatePackagesContext context, CancellationToken cancellationToken) + { + throw new NotImplementedException(); + } + + public Task FindAndStopRunningInstanceAsync(FileInfo appHostFile, DirectoryInfo homeDirectory, CancellationToken cancellationToken) + { + return Task.FromResult(RunningInstanceResult.NoRunningInstance); + } + + public Task GetUserSecretsIdAsync(FileInfo appHostFile, bool autoInit, CancellationToken cancellationToken) + { + return Task.FromResult(null); + } + + public Task> GetPackageReferencesAsync(FileInfo appHostFile, CancellationToken cancellationToken) + { + throw new NotImplementedException(); + } + + public Task BuildAndGenerateSdkAsync(DirectoryInfo directory, CancellationToken cancellationToken) + { + return buildAndGenerateSdkAsync(directory, cancellationToken); + } +} diff --git a/tests/Aspire.Cli.Tests/Commands/RunCommandTests.cs b/tests/Aspire.Cli.Tests/Commands/RunCommandTests.cs index 03ff8aad9bf..c9be9da0286 100644 --- a/tests/Aspire.Cli.Tests/Commands/RunCommandTests.cs +++ b/tests/Aspire.Cli.Tests/Commands/RunCommandTests.cs @@ -172,6 +172,8 @@ public Task UseOrFindAppHostProjectFileAsync(FileInf { throw new Aspire.Cli.Projects.ProjectLocatorException("Project file does not exist.", Aspire.Cli.Projects.ProjectLocatorFailureReason.ProjectFileDoesntExist); } + + public Task GetAppHostFromSettingsAsync(CancellationToken cancellationToken = default) => Task.FromResult(null); } [Fact] @@ -225,6 +227,8 @@ public Task UseOrFindAppHostProjectFileAsync(FileInf { throw new Aspire.Cli.Projects.ProjectLocatorException("No project file found.", Aspire.Cli.Projects.ProjectLocatorFailureReason.NoProjectFileFound); } + + public Task GetAppHostFromSettingsAsync(CancellationToken cancellationToken = default) => Task.FromResult(null); } private sealed class MultipleProjectFilesProjectLocator : IProjectLocator @@ -238,6 +242,8 @@ public Task UseOrFindAppHostProjectFileAsync(FileInf { throw new Aspire.Cli.Projects.ProjectLocatorException("Multiple project files found.", Aspire.Cli.Projects.ProjectLocatorFailureReason.MultipleProjectFilesFound); } + + public Task GetAppHostFromSettingsAsync(CancellationToken cancellationToken = default) => Task.FromResult(null); } private sealed class FixedTimeProvider(DateTimeOffset utcNow) : TimeProvider @@ -1266,6 +1272,8 @@ public Task UseOrFindAppHostProjectFileAsync(FileInf // Return a .cs file to simulate single file AppHost return Task.FromResult(new FileInfo("/tmp/apphost.cs")); } + + public Task GetAppHostFromSettingsAsync(CancellationToken cancellationToken = default) => Task.FromResult(null); } [Fact] diff --git a/tests/Aspire.Cli.Tests/TestServices/NoProjectFileProjectLocator.cs b/tests/Aspire.Cli.Tests/TestServices/NoProjectFileProjectLocator.cs index 1fabc438d91..907b9982a7f 100644 --- a/tests/Aspire.Cli.Tests/TestServices/NoProjectFileProjectLocator.cs +++ b/tests/Aspire.Cli.Tests/TestServices/NoProjectFileProjectLocator.cs @@ -16,4 +16,6 @@ public Task UseOrFindAppHostProjectFileAsync(FileInf { throw new ProjectLocatorException("No project file found.", ProjectLocatorFailureReason.NoProjectFileFound); } + + public Task GetAppHostFromSettingsAsync(CancellationToken cancellationToken = default) => Task.FromResult(null); } diff --git a/tests/Aspire.Cli.Tests/TestServices/TestCertificateToolRunner.cs b/tests/Aspire.Cli.Tests/TestServices/TestCertificateToolRunner.cs index 549c0f8c246..14939e7f043 100644 --- a/tests/Aspire.Cli.Tests/TestServices/TestCertificateToolRunner.cs +++ b/tests/Aspire.Cli.Tests/TestServices/TestCertificateToolRunner.cs @@ -2,7 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using Aspire.Cli.Certificates; -using Aspire.Cli.DotNet; +using Microsoft.AspNetCore.Certificates.Generation; namespace Aspire.Cli.Tests.TestServices; @@ -12,30 +12,37 @@ namespace Aspire.Cli.Tests.TestServices; /// internal sealed class TestCertificateToolRunner : ICertificateToolRunner { - public Func? CheckHttpCertificateMachineReadableAsyncCallback { get; set; } - public Func? TrustHttpCertificateAsyncCallback { get; set; } + public Func? CheckHttpCertificateCallback { get; set; } + public Func? TrustHttpCertificateCallback { get; set; } + public Func? CleanHttpCertificateCallback { get; set; } - public Task<(int ExitCode, CertificateTrustResult? Result)> CheckHttpCertificateMachineReadableAsync(DotNetCliRunnerInvocationOptions options, CancellationToken cancellationToken) + public CertificateTrustResult CheckHttpCertificate() { - if (CheckHttpCertificateMachineReadableAsyncCallback != null) + if (CheckHttpCertificateCallback is not null) { - return Task.FromResult(CheckHttpCertificateMachineReadableAsyncCallback(options, cancellationToken)); + return CheckHttpCertificateCallback(); } // Default: Return a fully trusted certificate result - var result = new CertificateTrustResult + return new CertificateTrustResult { HasCertificates = true, - TrustLevel = DevCertTrustLevel.Full, + TrustLevel = CertificateManager.TrustLevel.Full, Certificates = [] }; - return Task.FromResult<(int, CertificateTrustResult?)>((0, result)); } - public Task TrustHttpCertificateAsync(DotNetCliRunnerInvocationOptions options, CancellationToken cancellationToken) + public EnsureCertificateResult TrustHttpCertificate() { - return TrustHttpCertificateAsyncCallback != null - ? Task.FromResult(TrustHttpCertificateAsyncCallback(options, cancellationToken)) - : Task.FromResult(0); + return TrustHttpCertificateCallback is not null + ? TrustHttpCertificateCallback() + : EnsureCertificateResult.ExistingHttpsCertificateTrusted; + } + + public CertificateCleanResult CleanHttpCertificate() + { + return CleanHttpCertificateCallback is not null + ? CleanHttpCertificateCallback() + : new CertificateCleanResult { Success = true }; } } diff --git a/tests/Aspire.Cli.Tests/TestServices/TestLanguageDiscovery.cs b/tests/Aspire.Cli.Tests/TestServices/TestLanguageDiscovery.cs index e406f8e73e3..ae78422cf70 100644 --- a/tests/Aspire.Cli.Tests/TestServices/TestLanguageDiscovery.cs +++ b/tests/Aspire.Cli.Tests/TestServices/TestLanguageDiscovery.cs @@ -7,10 +7,11 @@ namespace Aspire.Cli.Tests.TestServices; /// /// Test implementation of that includes C# support for testing. +/// Optionally accepts additional languages for polyglot scenarios. /// internal sealed class TestLanguageDiscovery : ILanguageDiscovery { - private static readonly LanguageInfo[] s_allLanguages = + private static readonly LanguageInfo[] s_defaultLanguages = [ new LanguageInfo( LanguageId: new LanguageId(KnownLanguageId.CSharp), @@ -21,19 +22,26 @@ internal sealed class TestLanguageDiscovery : ILanguageDiscovery AppHostFileName: null), ]; + private readonly LanguageInfo[] _allLanguages; + + public TestLanguageDiscovery(params LanguageInfo[] additionalLanguages) + { + _allLanguages = [.. s_defaultLanguages, .. additionalLanguages]; + } + public Task> GetAvailableLanguagesAsync(CancellationToken cancellationToken = default) - => Task.FromResult>(s_allLanguages); + => Task.FromResult>(_allLanguages); public Task GetPackageForLanguageAsync(LanguageId languageId, CancellationToken cancellationToken = default) { - var language = s_allLanguages.FirstOrDefault(l => + var language = _allLanguages.FirstOrDefault(l => string.Equals(l.LanguageId.Value, languageId.Value, StringComparison.OrdinalIgnoreCase)); return Task.FromResult(language?.PackageName); } public Task DetectLanguageAsync(DirectoryInfo directory, CancellationToken cancellationToken = default) { - foreach (var language in s_allLanguages) + foreach (var language in _allLanguages) { foreach (var pattern in language.DetectionPatterns) { @@ -60,13 +68,13 @@ public Task> GetAvailableLanguagesAsync(CancellationTo public LanguageInfo? GetLanguageById(LanguageId languageId) { - return s_allLanguages.FirstOrDefault(l => + return _allLanguages.FirstOrDefault(l => string.Equals(l.LanguageId.Value, languageId.Value, StringComparison.OrdinalIgnoreCase)); } public LanguageInfo? GetLanguageByFile(FileInfo file) { - return s_allLanguages.FirstOrDefault(l => + return _allLanguages.FirstOrDefault(l => l.DetectionPatterns.Any(p => MatchesPattern(file.Name, p))); } diff --git a/tests/Aspire.Cli.Tests/TestServices/TestProjectLocator.cs b/tests/Aspire.Cli.Tests/TestServices/TestProjectLocator.cs index 634ffc24a17..ebb53915f80 100644 --- a/tests/Aspire.Cli.Tests/TestServices/TestProjectLocator.cs +++ b/tests/Aspire.Cli.Tests/TestServices/TestProjectLocator.cs @@ -12,6 +12,8 @@ internal sealed class TestProjectLocator : IProjectLocator public Func>? UseOrFindAppHostProjectFileWithBehaviorAsyncCallback { get; set; } + public Func>? GetAppHostFromSettingsAsyncCallback { get; set; } + public async Task UseOrFindAppHostProjectFileAsync(FileInfo? projectFile, bool createSettingsFile, CancellationToken cancellationToken) { if (UseOrFindAppHostProjectFileAsyncCallback != null) @@ -45,5 +47,16 @@ public async Task UseOrFindAppHostProjectFileAsync(F return new AppHostProjectSearchResult(appHostFile, [appHostFile]); } + + public async Task GetAppHostFromSettingsAsync(CancellationToken cancellationToken = default) + { + if (GetAppHostFromSettingsAsyncCallback != null) + { + return await GetAppHostFromSettingsAsyncCallback(cancellationToken); + } + + // Default: no settings file found + return null; + } } diff --git a/tests/Aspire.Cli.Tests/Utils/CliTestHelper.cs b/tests/Aspire.Cli.Tests/Utils/CliTestHelper.cs index 5f733deb2f0..157fe041569 100644 --- a/tests/Aspire.Cli.Tests/Utils/CliTestHelper.cs +++ b/tests/Aspire.Cli.Tests/Utils/CliTestHelper.cs @@ -180,6 +180,9 @@ public static IServiceCollection CreateServiceCollection(TemporaryWorkspace work services.AddTransient(); services.AddTransient(); services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); services.AddTransient(); services.AddTransient(); services.AddTransient(); @@ -480,7 +483,8 @@ public ISolutionLocator CreateDefaultSolutionLocatorFactory(IServiceProvider ser var cliTemplateLogger = serviceProvider.GetRequiredService>(); var templateNuGetConfigService = new TemplateNuGetConfigService(interactionService, executionContext, packagingService, configurationService); var dotNetFactory = new DotNetTemplateFactory(interactionService, runner, certificateService, packagingService, prompter, templateVersionPrompter, executionContext, sdkInstaller, features, configurationService, telemetry, hostEnvironment, templateNuGetConfigService); - var cliFactory = new CliTemplateFactory(languageDiscovery, scaffoldingService, prompter, executionContext, interactionService, hostEnvironment, templateNuGetConfigService, cliTemplateLogger); + var projectFactory = serviceProvider.GetRequiredService(); + var cliFactory = new CliTemplateFactory(languageDiscovery, projectFactory, scaffoldingService, prompter, executionContext, interactionService, hostEnvironment, templateNuGetConfigService, cliTemplateLogger); return new TemplateProvider([dotNetFactory, cliFactory]); }; diff --git a/tests/Aspire.Cli.Tests/Utils/DevCertsCheckFixRecommendationTests.cs b/tests/Aspire.Cli.Tests/Utils/DevCertsCheckFixRecommendationTests.cs new file mode 100644 index 00000000000..795205f40f5 --- /dev/null +++ b/tests/Aspire.Cli.Tests/Utils/DevCertsCheckFixRecommendationTests.cs @@ -0,0 +1,159 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Aspire.Cli.Certificates; +using Aspire.Cli.Utils.EnvironmentChecker; +using Microsoft.AspNetCore.Certificates.Generation; + +namespace Aspire.Cli.Tests.Utils; + +public class DevCertsCheckFixRecommendationTests +{ + [Fact] + public void EvaluateCertificateResults_NoCertificates_RecommendsTrust() + { + var results = DevCertsCheck.EvaluateCertificateResults([]); + + var result = Assert.Single(results); + Assert.Equal(EnvironmentCheckStatus.Warning, result.Status); + Assert.NotNull(result.Fix); + Assert.Contains("aspire certs trust", result.Fix); + Assert.DoesNotContain("aspire certs clean", result.Fix); + } + + [Fact] + public void EvaluateCertificateResults_SingleUntrustedCert_RecommendsTrust() + { + var certInfos = new List + { + new(CertificateManager.TrustLevel.None, "AABB1234", 4) + }; + + var results = DevCertsCheck.EvaluateCertificateResults(certInfos); + + var result = Assert.Single(results); + Assert.Equal(EnvironmentCheckStatus.Warning, result.Status); + Assert.NotNull(result.Fix); + Assert.Contains("aspire certs trust", result.Fix); + Assert.DoesNotContain("aspire certs clean", result.Fix); + } + + [Fact] + public void EvaluateCertificateResults_SingleFullyTrustedCert_ReportsPass() + { + var certInfos = new List + { + new(CertificateManager.TrustLevel.Full, "AABB1234", 4) + }; + + var results = DevCertsCheck.EvaluateCertificateResults(certInfos); + + var result = Assert.Single(results); + Assert.Equal(EnvironmentCheckStatus.Pass, result.Status); + Assert.Null(result.Fix); + } + + [Fact] + public void EvaluateCertificateResults_MultipleCerts_SomeUntrusted_RecommendsCleanAndTrust() + { + var certInfos = new List + { + new(CertificateManager.TrustLevel.Full, "AABB1234", 4), + new(CertificateManager.TrustLevel.None, "CCDD5678", 4) + }; + + var results = DevCertsCheck.EvaluateCertificateResults(certInfos); + + var result = Assert.Single(results); + Assert.Equal(EnvironmentCheckStatus.Warning, result.Status); + Assert.NotNull(result.Fix); + Assert.Contains("aspire certs clean", result.Fix); + Assert.Contains("aspire certs trust", result.Fix); + } + + [Fact] + public void EvaluateCertificateResults_MultipleCerts_NoneUntrusted_RecommendsCleanAndTrust() + { + var certInfos = new List + { + new(CertificateManager.TrustLevel.None, "AABB1234", 4), + new(CertificateManager.TrustLevel.None, "CCDD5678", 4) + }; + + var results = DevCertsCheck.EvaluateCertificateResults(certInfos); + + var result = Assert.Single(results); + Assert.Equal(EnvironmentCheckStatus.Warning, result.Status); + Assert.NotNull(result.Fix); + Assert.Contains("aspire certs clean", result.Fix); + Assert.Contains("aspire certs trust", result.Fix); + } + + [Fact] + public void EvaluateCertificateResults_OldVersionCert_RecommendsCleanAndTrust() + { + var certInfos = new List + { + new(CertificateManager.TrustLevel.Full, "AABB1234", 1) + }; + + var results = DevCertsCheck.EvaluateCertificateResults(certInfos); + + // Should have two results: pass for trust status, warning for old version + Assert.Equal(2, results.Count); + var versionWarning = results.First(r => r.Name == "dev-certs-version"); + Assert.Equal(EnvironmentCheckStatus.Warning, versionWarning.Status); + Assert.NotNull(versionWarning.Fix); + Assert.Contains("aspire certs clean", versionWarning.Fix); + Assert.Contains("aspire certs trust", versionWarning.Fix); + } + + [Fact] + public void EvaluateCertificateResults_PartiallyTrustedCert_RecommendsSslCertDir() + { + var certInfos = new List + { + new(CertificateManager.TrustLevel.Partial, "AABB1234", 4) + }; + + var results = DevCertsCheck.EvaluateCertificateResults(certInfos); + + var result = Assert.Single(results); + Assert.Equal(EnvironmentCheckStatus.Warning, result.Status); + Assert.NotNull(result.Fix); + // Partial trust fix involves SSL_CERT_DIR, not aspire certs commands + Assert.DoesNotContain("aspire certs", result.Fix); + } + + [Fact] + public void EvaluateCertificateResults_MultipleAllTrusted_ReportsPass() + { + var certInfos = new List + { + new(CertificateManager.TrustLevel.Full, "AABB1234", 4), + new(CertificateManager.TrustLevel.Full, "CCDD5678", 4) + }; + + var results = DevCertsCheck.EvaluateCertificateResults(certInfos); + + var result = Assert.Single(results); + Assert.Equal(EnvironmentCheckStatus.Pass, result.Status); + } + + [Fact] + public void IsSuccessfulTrustResult_SuccessResults_ReturnsTrue() + { + Assert.True(CertificateHelpers.IsSuccessfulTrustResult(EnsureCertificateResult.Succeeded)); + Assert.True(CertificateHelpers.IsSuccessfulTrustResult(EnsureCertificateResult.ValidCertificatePresent)); + Assert.True(CertificateHelpers.IsSuccessfulTrustResult(EnsureCertificateResult.ExistingHttpsCertificateTrusted)); + Assert.True(CertificateHelpers.IsSuccessfulTrustResult(EnsureCertificateResult.NewHttpsCertificateTrusted)); + } + + [Fact] + public void IsSuccessfulTrustResult_FailureResults_ReturnsFalse() + { + Assert.False(CertificateHelpers.IsSuccessfulTrustResult(EnsureCertificateResult.FailedToTrustTheCertificate)); + Assert.False(CertificateHelpers.IsSuccessfulTrustResult(EnsureCertificateResult.ErrorCreatingTheCertificate)); + Assert.False(CertificateHelpers.IsSuccessfulTrustResult(EnsureCertificateResult.ErrorSavingTheCertificateIntoTheCurrentUserPersonalStore)); + } +} diff --git a/tests/Aspire.Cli.Tests/Utils/DevCertsCheckTests.cs b/tests/Aspire.Cli.Tests/Utils/DevCertsCheckTests.cs index 255a2cda4e5..3d4b5b79b7e 100644 --- a/tests/Aspire.Cli.Tests/Utils/DevCertsCheckTests.cs +++ b/tests/Aspire.Cli.Tests/Utils/DevCertsCheckTests.cs @@ -3,6 +3,7 @@ using Aspire.Cli.Utils.EnvironmentChecker; using Aspire.Hosting.Utils; +using Microsoft.AspNetCore.Certificates.Generation; namespace Aspire.Cli.Tests.Utils; @@ -10,13 +11,24 @@ public class DevCertsCheckTests { private const int MinVersion = X509Certificate2Extensions.MinimumCertificateVersionSupportingContainerTrust; + [Fact] + public void EvaluateCertificateResults_NoCertificates_ReturnsWarning() + { + var results = DevCertsCheck.EvaluateCertificateResults([]); + + var devCertsResult = Assert.Single(results); + Assert.Equal("dev-certs", devCertsResult.Name); + Assert.Equal(EnvironmentCheckStatus.Warning, devCertsResult.Status); + Assert.Contains("No HTTPS development certificate found", devCertsResult.Message); + } + [Fact] public void EvaluateCertificateResults_MultipleCerts_AllTrusted_ReturnsPass() { var certs = new List { - new(CertificateTrustLevel.Full, "AAAA1111BBBB2222", MinVersion), - new(CertificateTrustLevel.Full, "CCCC3333DDDD4444", MinVersion), + new(CertificateManager.TrustLevel.Full, "AAAA1111BBBB2222", MinVersion), + new(CertificateManager.TrustLevel.Full, "CCCC3333DDDD4444", MinVersion), }; var results = DevCertsCheck.EvaluateCertificateResults(certs); @@ -31,8 +43,8 @@ public void EvaluateCertificateResults_MultipleCerts_NoneTrusted_ReturnsWarning( { var certs = new List { - new(CertificateTrustLevel.None, "AAAA1111BBBB2222", MinVersion), - new(CertificateTrustLevel.None, "CCCC3333DDDD4444", MinVersion), + new(CertificateManager.TrustLevel.None, "AAAA1111BBBB2222", MinVersion), + new(CertificateManager.TrustLevel.None, "CCCC3333DDDD4444", MinVersion), }; var results = DevCertsCheck.EvaluateCertificateResults(certs); @@ -47,8 +59,8 @@ public void EvaluateCertificateResults_MultipleCerts_SomeUntrusted_ReturnsWarnin { var certs = new List { - new(CertificateTrustLevel.Full, "AAAA1111BBBB2222", MinVersion), - new(CertificateTrustLevel.None, "CCCC3333DDDD4444", MinVersion), + new(CertificateManager.TrustLevel.Full, "AAAA1111BBBB2222", MinVersion), + new(CertificateManager.TrustLevel.None, "CCCC3333DDDD4444", MinVersion), }; var results = DevCertsCheck.EvaluateCertificateResults(certs); @@ -63,7 +75,7 @@ public void EvaluateCertificateResults_SingleCert_Trusted_ReturnsPass() { var certs = new List { - new(CertificateTrustLevel.Full, "AAAA1111BBBB2222", MinVersion), + new(CertificateManager.TrustLevel.Full, "AAAA1111BBBB2222", MinVersion), }; var results = DevCertsCheck.EvaluateCertificateResults(certs); @@ -78,7 +90,7 @@ public void EvaluateCertificateResults_SingleCert_Untrusted_ReturnsWarning() { var certs = new List { - new(CertificateTrustLevel.None, "AAAA1111BBBB2222", MinVersion), + new(CertificateManager.TrustLevel.None, "AAAA1111BBBB2222", MinVersion), }; var results = DevCertsCheck.EvaluateCertificateResults(certs); @@ -93,7 +105,7 @@ public void EvaluateCertificateResults_SingleCert_PartiallyTrusted_ReturnsWarnin { var certs = new List { - new(CertificateTrustLevel.Partial, "AAAA1111BBBB2222", MinVersion), + new(CertificateManager.TrustLevel.Partial, "AAAA1111BBBB2222", MinVersion), }; var results = DevCertsCheck.EvaluateCertificateResults(certs); @@ -108,7 +120,7 @@ public void EvaluateCertificateResults_OldTrustedCert_ReturnsVersionWarning() { var certs = new List { - new(CertificateTrustLevel.Full, "AAAA1111BBBB2222", MinVersion - 1), + new(CertificateManager.TrustLevel.Full, "AAAA1111BBBB2222", MinVersion - 1), }; var results = DevCertsCheck.EvaluateCertificateResults(certs); @@ -124,8 +136,8 @@ public void EvaluateCertificateResults_MultipleCerts_AllTrusted_NoVersionWarning { var certs = new List { - new(CertificateTrustLevel.Full, "AAAA1111BBBB2222", MinVersion), - new(CertificateTrustLevel.Full, "CCCC3333DDDD4444", MinVersion + 1), + new(CertificateManager.TrustLevel.Full, "AAAA1111BBBB2222", MinVersion), + new(CertificateManager.TrustLevel.Full, "CCCC3333DDDD4444", MinVersion + 1), }; var results = DevCertsCheck.EvaluateCertificateResults(certs); @@ -142,8 +154,8 @@ public void EvaluateCertificateResults_MultipleCerts_AllPartiallyTrusted_Returns // Partially trusted counts as trusted (not None), so all certs are "trusted" var certs = new List { - new(CertificateTrustLevel.Partial, "AAAA1111BBBB2222", MinVersion), - new(CertificateTrustLevel.Partial, "CCCC3333DDDD4444", MinVersion), + new(CertificateManager.TrustLevel.Partial, "AAAA1111BBBB2222", MinVersion), + new(CertificateManager.TrustLevel.Partial, "CCCC3333DDDD4444", MinVersion), }; var results = DevCertsCheck.EvaluateCertificateResults(certs); @@ -158,9 +170,9 @@ public void EvaluateCertificateResults_ThreeCerts_TwoTrustedOneNot_ReturnsWarnin { var certs = new List { - new(CertificateTrustLevel.Full, "AAAA1111BBBB2222", MinVersion), - new(CertificateTrustLevel.Full, "CCCC3333DDDD4444", MinVersion), - new(CertificateTrustLevel.None, "EEEE5555FFFF6666", MinVersion), + new(CertificateManager.TrustLevel.Full, "AAAA1111BBBB2222", MinVersion), + new(CertificateManager.TrustLevel.Full, "CCCC3333DDDD4444", MinVersion), + new(CertificateManager.TrustLevel.None, "EEEE5555FFFF6666", MinVersion), }; var results = DevCertsCheck.EvaluateCertificateResults(certs); diff --git a/tests/Aspire.Dashboard.Tests/Integration/FrontendBrowserTokenAuthTests.cs b/tests/Aspire.Dashboard.Tests/Integration/FrontendBrowserTokenAuthTests.cs index 7e081925a4e..a245a157b94 100644 --- a/tests/Aspire.Dashboard.Tests/Integration/FrontendBrowserTokenAuthTests.cs +++ b/tests/Aspire.Dashboard.Tests/Integration/FrontendBrowserTokenAuthTests.cs @@ -212,6 +212,11 @@ public async Task LogOutput_NoToken_GeneratedTokenLogged() Assert.Equal(LogLevel.Warning, w.LogLevel); }, w => + { + Assert.Equal("Dashboard API is unsecured. Untrusted apps can access sensitive telemetry data.", LogTestHelpers.GetValue(w, "{OriginalFormat}")); + Assert.Equal(LogLevel.Warning, w.LogLevel); + }, + w => { Assert.Equal("Login to the dashboard at {DashboardLoginUrl}", LogTestHelpers.GetValue(w, "{OriginalFormat}")); diff --git a/tests/Aspire.Dashboard.Tests/Integration/IntegrationTestHelpers.cs b/tests/Aspire.Dashboard.Tests/Integration/IntegrationTestHelpers.cs index 4a69f505db3..4a002981404 100644 --- a/tests/Aspire.Dashboard.Tests/Integration/IntegrationTestHelpers.cs +++ b/tests/Aspire.Dashboard.Tests/Integration/IntegrationTestHelpers.cs @@ -64,6 +64,7 @@ public static DashboardWebApplication CreateDashboardWebApplication( [DashboardConfigNames.DashboardMcpUrlName.ConfigKey] = "http://127.0.0.1:0", [DashboardConfigNames.DashboardOtlpAuthModeName.ConfigKey] = nameof(OtlpAuthMode.Unsecured), [DashboardConfigNames.DashboardFrontendAuthModeName.ConfigKey] = nameof(FrontendAuthMode.Unsecured), + [DashboardConfigNames.DashboardApiEnabledName.ConfigKey] = "true", // Allow the requirement of HTTPS communication with the OpenIdConnect authority to be relaxed during tests. ["Authentication:Schemes:OpenIdConnect:RequireHttpsMetadata"] = "false" }; diff --git a/tests/Aspire.Dashboard.Tests/Integration/StartupTests.cs b/tests/Aspire.Dashboard.Tests/Integration/StartupTests.cs index c0473235abe..4b000997ff9 100644 --- a/tests/Aspire.Dashboard.Tests/Integration/StartupTests.cs +++ b/tests/Aspire.Dashboard.Tests/Integration/StartupTests.cs @@ -725,6 +725,11 @@ public async Task LogOutput_DynamicPort_PortResolvedInLogs() { Assert.Equal("MCP server is unsecured. Untrusted apps can access sensitive information.", LogTestHelpers.GetValue(w, "{OriginalFormat}")); Assert.Equal(LogLevel.Warning, w.LogLevel); + }, + w => + { + Assert.Equal("Dashboard API is unsecured. Untrusted apps can access sensitive telemetry data.", LogTestHelpers.GetValue(w, "{OriginalFormat}")); + Assert.Equal(LogLevel.Warning, w.LogLevel); }); } @@ -765,6 +770,11 @@ public async Task LogOutput_NoOtlpEndpoints_NoOtlpLogs() { Assert.Equal("MCP server is unsecured. Untrusted apps can access sensitive information.", LogTestHelpers.GetValue(w, "{OriginalFormat}")); Assert.Equal(LogLevel.Warning, w.LogLevel); + }, + w => + { + Assert.Equal("Dashboard API is unsecured. Untrusted apps can access sensitive telemetry data.", LogTestHelpers.GetValue(w, "{OriginalFormat}")); + Assert.Equal(LogLevel.Warning, w.LogLevel); }); } @@ -790,6 +800,53 @@ public async Task LogOutput_McpDisabled_NoMcpWarningLog() Assert.DoesNotContain(l, w => LogTestHelpers.GetValue(w, "{OriginalFormat}")?.ToString()?.Contains("MCP server is unsecured") == true); } + [Theory] + [InlineData(null, HttpStatusCode.NotFound)] + [InlineData(true, HttpStatusCode.OK)] + [InlineData(false, HttpStatusCode.NotFound)] + public async Task ApiEnabled_ReturnsExpectedStatusAndWarning(bool? enabled, HttpStatusCode expectedStatusCode) + { + const string ApiUnsecuredWarning = "Dashboard API is unsecured. Untrusted apps can access sensitive telemetry data."; + + // Arrange + var testSink = new TestSink(); + await using var app = IntegrationTestHelpers.CreateDashboardWebApplication(testOutputHelper, + additionalConfiguration: config => + { + if (enabled is not null) + { + config[DashboardConfigNames.DashboardApiEnabledName.ConfigKey] = enabled.Value.ToString(); + } + else + { + config.Remove(DashboardConfigNames.DashboardApiEnabledName.ConfigKey); + } + }, + testSink: testSink); + await app.StartAsync().DefaultTimeout(); + + using var httpClient = IntegrationTestHelpers.CreateHttpClient($"http://{app.FrontendSingleEndPointAccessor().EndPoint}"); + + // Act + var response = await httpClient.GetAsync("/api/telemetry/spans").DefaultTimeout(); + + // Assert + Assert.Equal(expectedStatusCode, response.StatusCode); + + var warnings = testSink.Writes + .Where(w => w.LoggerName == typeof(DashboardWebApplication).FullName && w.LogLevel >= LogLevel.Warning) + .ToList(); + + if (enabled == true) + { + Assert.Contains(warnings, w => LogTestHelpers.GetValue(w, "{OriginalFormat}")?.ToString() == ApiUnsecuredWarning); + } + else + { + Assert.DoesNotContain(warnings, w => LogTestHelpers.GetValue(w, "{OriginalFormat}")?.ToString() == ApiUnsecuredWarning); + } + } + [Fact] public async Task LogOutput_LocalhostAddress_LocalhostInLogOutput() { @@ -885,6 +942,11 @@ await ServerRetryHelper.BindPortsWithRetry(async ports => { Assert.Equal("MCP server is unsecured. Untrusted apps can access sensitive information.", LogTestHelpers.GetValue(w, "{OriginalFormat}")); Assert.Equal(LogLevel.Warning, w.LogLevel); + }, + w => + { + Assert.Equal("Dashboard API is unsecured. Untrusted apps can access sensitive telemetry data.", LogTestHelpers.GetValue(w, "{OriginalFormat}")); + Assert.Equal(LogLevel.Warning, w.LogLevel); }); } diff --git a/tests/Aspire.Dashboard.Tests/Integration/TelemetryApiTests.cs b/tests/Aspire.Dashboard.Tests/Integration/TelemetryApiTests.cs index 21a6c745617..15d6995796c 100644 --- a/tests/Aspire.Dashboard.Tests/Integration/TelemetryApiTests.cs +++ b/tests/Aspire.Dashboard.Tests/Integration/TelemetryApiTests.cs @@ -181,25 +181,6 @@ public async Task GetSpans_WithWrongApiKey_ReturnsUnauthorized() Assert.Equal(HttpStatusCode.Unauthorized, response.StatusCode); } - [Fact] - public async Task GetSpans_ApiDisabled_Returns404() - { - // Arrange - disable the Telemetry API explicitly - await using var app = IntegrationTestHelpers.CreateDashboardWebApplication(_testOutputHelper, config => - { - config[DashboardConfigNames.DashboardApiEnabledName.ConfigKey] = "false"; - }); - await app.StartAsync().DefaultTimeout(); - - using var httpClient = IntegrationTestHelpers.CreateHttpClient($"http://{app.FrontendSingleEndPointAccessor().EndPoint}"); - - // Act - var response = await httpClient.GetAsync("/api/telemetry/spans").DefaultTimeout(); - - // Assert - Assert.Equal(HttpStatusCode.NotFound, response.StatusCode); - } - [Fact] public async Task GetLogs_UnsecuredMode_Returns200() { diff --git a/tests/Aspire.Deployment.EndToEnd.Tests/AcaCompactNamingDeploymentTests.cs b/tests/Aspire.Deployment.EndToEnd.Tests/AcaCompactNamingDeploymentTests.cs index 8eb942dee73..c24b504d934 100644 --- a/tests/Aspire.Deployment.EndToEnd.Tests/AcaCompactNamingDeploymentTests.cs +++ b/tests/Aspire.Deployment.EndToEnd.Tests/AcaCompactNamingDeploymentTests.cs @@ -66,9 +66,6 @@ private async Task DeployWithCompactNamingFixesStorageCollisionCore(Cancellation using var terminal = DeploymentE2ETestHelpers.CreateTestTerminal(); var pendingRun = terminal.RunAsync(cancellationToken); - var waitingForInitComplete = new CellPatternSearcher() - .Find("Aspire initialization complete"); - var waitingForVersionSelectionPrompt = new CellPatternSearcher() .Find("(based on NuGet.config)"); @@ -91,13 +88,7 @@ private async Task DeployWithCompactNamingFixesStorageCollisionCore(Cancellation // Step 3: Create single-file AppHost output.WriteLine("Step 3: Creating single-file AppHost..."); - sequenceBuilder.Type("aspire init --language csharp") - .Enter() - .Wait(TimeSpan.FromSeconds(5)) - .Enter() - .WaitUntil(s => waitingForInitComplete.Search(s).Count > 0, TimeSpan.FromMinutes(2)) - .DeclineAgentInitPrompt() - .WaitForSuccessPrompt(counter, TimeSpan.FromMinutes(2)); + sequenceBuilder.AspireInit(counter); // Step 4: Add required packages output.WriteLine("Step 4: Adding Azure Container Apps package..."); diff --git a/tests/Aspire.Deployment.EndToEnd.Tests/AcaDeploymentErrorOutputTests.cs b/tests/Aspire.Deployment.EndToEnd.Tests/AcaDeploymentErrorOutputTests.cs index 48a3a908dd8..358a70e11ab 100644 --- a/tests/Aspire.Deployment.EndToEnd.Tests/AcaDeploymentErrorOutputTests.cs +++ b/tests/Aspire.Deployment.EndToEnd.Tests/AcaDeploymentErrorOutputTests.cs @@ -69,9 +69,6 @@ private async Task DeployWithInvalidLocation_ErrorOutputIsCleanCore(Cancellation using var terminal = DeploymentE2ETestHelpers.CreateTestTerminal(); var pendingRun = terminal.RunAsync(cancellationToken); - var waitingForInitComplete = new CellPatternSearcher() - .Find("Aspire initialization complete"); - var waitingForVersionSelectionPrompt = new CellPatternSearcher() .Find("(based on NuGet.config)"); @@ -94,13 +91,7 @@ private async Task DeployWithInvalidLocation_ErrorOutputIsCleanCore(Cancellation // Step 3: Create single-file AppHost output.WriteLine("Step 3: Creating single-file AppHost..."); - sequenceBuilder.Type("aspire init --language csharp") - .Enter() - .Wait(TimeSpan.FromSeconds(5)) - .Enter() - .WaitUntil(s => waitingForInitComplete.Search(s).Count > 0, TimeSpan.FromMinutes(2)) - .DeclineAgentInitPrompt() - .WaitForSuccessPrompt(counter, TimeSpan.FromMinutes(2)); + sequenceBuilder.AspireInit(counter); // Step 4: Add Azure Container Apps package output.WriteLine("Step 4: Adding Azure Container Apps package..."); diff --git a/tests/Aspire.Deployment.EndToEnd.Tests/AzureAppConfigDeploymentTests.cs b/tests/Aspire.Deployment.EndToEnd.Tests/AzureAppConfigDeploymentTests.cs index ba542dbb355..fd97e69de47 100644 --- a/tests/Aspire.Deployment.EndToEnd.Tests/AzureAppConfigDeploymentTests.cs +++ b/tests/Aspire.Deployment.EndToEnd.Tests/AzureAppConfigDeploymentTests.cs @@ -63,10 +63,6 @@ private async Task DeployAzureAppConfigResourceCore(CancellationToken cancellati using var terminal = DeploymentE2ETestHelpers.CreateTestTerminal(); var pendingRun = terminal.RunAsync(cancellationToken); - // Pattern searchers for aspire init - var waitingForInitComplete = new CellPatternSearcher() - .Find("Aspire initialization complete"); - // Pattern searchers for aspire add prompts // Integration selection prompt appears when multiple packages match the search term var waitingForIntegrationSelectionPrompt = new CellPatternSearcher() @@ -96,15 +92,7 @@ private async Task DeployAzureAppConfigResourceCore(CancellationToken cancellati // Step 3: Create single-file AppHost using aspire init output.WriteLine("Step 3: Creating single-file AppHost with aspire init..."); - sequenceBuilder.Type("aspire init --language csharp") - .Enter() - // NuGet.config prompt may or may not appear depending on environment. - // Wait a moment then press Enter to dismiss if present, then wait for completion. - .Wait(TimeSpan.FromSeconds(5)) - .Enter() // Dismiss NuGet.config prompt if present (no-op if already auto-accepted) - .WaitUntil(s => waitingForInitComplete.Search(s).Count > 0, TimeSpan.FromMinutes(2)) - .DeclineAgentInitPrompt() - .WaitForSuccessPrompt(counter, TimeSpan.FromMinutes(2)); + sequenceBuilder.AspireInit(counter); // Step 4a: Add Aspire.Hosting.Azure.ContainerApps package (for managed identity support) // This command triggers TWO prompts in sequence: diff --git a/tests/Aspire.Deployment.EndToEnd.Tests/AzureContainerRegistryDeploymentTests.cs b/tests/Aspire.Deployment.EndToEnd.Tests/AzureContainerRegistryDeploymentTests.cs index ec4805b85aa..0768af83d3e 100644 --- a/tests/Aspire.Deployment.EndToEnd.Tests/AzureContainerRegistryDeploymentTests.cs +++ b/tests/Aspire.Deployment.EndToEnd.Tests/AzureContainerRegistryDeploymentTests.cs @@ -63,10 +63,6 @@ private async Task DeployAzureContainerRegistryResourceCore(CancellationToken ca using var terminal = DeploymentE2ETestHelpers.CreateTestTerminal(); var pendingRun = terminal.RunAsync(cancellationToken); - // Pattern searchers for aspire init - var waitingForInitComplete = new CellPatternSearcher() - .Find("Aspire initialization complete"); - // Pattern searchers for aspire add prompts var waitingForAddVersionSelectionPrompt = new CellPatternSearcher() .Find("(based on NuGet.config)"); @@ -91,15 +87,7 @@ private async Task DeployAzureContainerRegistryResourceCore(CancellationToken ca // Step 3: Create single-file AppHost using aspire init output.WriteLine("Step 3: Creating single-file AppHost with aspire init..."); - sequenceBuilder.Type("aspire init --language csharp") - .Enter() - // NuGet.config prompt may or may not appear depending on environment. - // Wait a moment then press Enter to dismiss if present, then wait for completion. - .Wait(TimeSpan.FromSeconds(5)) - .Enter() // Dismiss NuGet.config prompt if present (no-op if already auto-accepted) - .WaitUntil(s => waitingForInitComplete.Search(s).Count > 0, TimeSpan.FromMinutes(2)) - .DeclineAgentInitPrompt() - .WaitForSuccessPrompt(counter, TimeSpan.FromMinutes(2)); + sequenceBuilder.AspireInit(counter); // Step 4: Add Aspire.Hosting.Azure.ContainerRegistry package output.WriteLine("Step 4: Adding Azure Container Registry hosting package..."); diff --git a/tests/Aspire.Deployment.EndToEnd.Tests/AzureEventHubsDeploymentTests.cs b/tests/Aspire.Deployment.EndToEnd.Tests/AzureEventHubsDeploymentTests.cs index 384332ec323..3da83c3ca5e 100644 --- a/tests/Aspire.Deployment.EndToEnd.Tests/AzureEventHubsDeploymentTests.cs +++ b/tests/Aspire.Deployment.EndToEnd.Tests/AzureEventHubsDeploymentTests.cs @@ -63,10 +63,6 @@ private async Task DeployAzureEventHubsResourceCore(CancellationToken cancellati using var terminal = DeploymentE2ETestHelpers.CreateTestTerminal(); var pendingRun = terminal.RunAsync(cancellationToken); - // Pattern searchers for aspire init - var waitingForInitComplete = new CellPatternSearcher() - .Find("Aspire initialization complete"); - // Pattern searchers for aspire add prompts // Integration selection prompt appears when multiple packages match the search term var waitingForIntegrationSelectionPrompt = new CellPatternSearcher() @@ -96,15 +92,7 @@ private async Task DeployAzureEventHubsResourceCore(CancellationToken cancellati // Step 3: Create single-file AppHost using aspire init output.WriteLine("Step 3: Creating single-file AppHost with aspire init..."); - sequenceBuilder.Type("aspire init --language csharp") - .Enter() - // NuGet.config prompt may or may not appear depending on environment. - // Wait a moment then press Enter to dismiss if present, then wait for completion. - .Wait(TimeSpan.FromSeconds(5)) - .Enter() // Dismiss NuGet.config prompt if present (no-op if already auto-accepted) - .WaitUntil(s => waitingForInitComplete.Search(s).Count > 0, TimeSpan.FromMinutes(2)) - .DeclineAgentInitPrompt() - .WaitForSuccessPrompt(counter, TimeSpan.FromMinutes(2)); + sequenceBuilder.AspireInit(counter); // Step 4a: Add Aspire.Hosting.Azure.ContainerApps package (for managed identity support) // This command triggers TWO prompts in sequence: diff --git a/tests/Aspire.Deployment.EndToEnd.Tests/AzureKeyVaultDeploymentTests.cs b/tests/Aspire.Deployment.EndToEnd.Tests/AzureKeyVaultDeploymentTests.cs index e194eff4a91..ab868d6b2b2 100644 --- a/tests/Aspire.Deployment.EndToEnd.Tests/AzureKeyVaultDeploymentTests.cs +++ b/tests/Aspire.Deployment.EndToEnd.Tests/AzureKeyVaultDeploymentTests.cs @@ -63,10 +63,6 @@ private async Task DeployAzureKeyVaultResourceCore(CancellationToken cancellatio using var terminal = DeploymentE2ETestHelpers.CreateTestTerminal(); var pendingRun = terminal.RunAsync(cancellationToken); - // Pattern searchers for aspire init - var waitingForInitComplete = new CellPatternSearcher() - .Find("Aspire initialization complete"); - // Pattern searchers for aspire add prompts // Integration selection prompt appears when multiple packages match the search term var waitingForIntegrationSelectionPrompt = new CellPatternSearcher() @@ -96,15 +92,7 @@ private async Task DeployAzureKeyVaultResourceCore(CancellationToken cancellatio // Step 3: Create single-file AppHost using aspire init output.WriteLine("Step 3: Creating single-file AppHost with aspire init..."); - sequenceBuilder.Type("aspire init --language csharp") - .Enter() - // NuGet.config prompt may or may not appear depending on environment. - // Wait a moment then press Enter to dismiss if present, then wait for completion. - .Wait(TimeSpan.FromSeconds(5)) - .Enter() // Dismiss NuGet.config prompt if present (no-op if already auto-accepted) - .WaitUntil(s => waitingForInitComplete.Search(s).Count > 0, TimeSpan.FromMinutes(2)) - .DeclineAgentInitPrompt() - .WaitForSuccessPrompt(counter, TimeSpan.FromMinutes(2)); + sequenceBuilder.AspireInit(counter); // Step 4a: Add Aspire.Hosting.Azure.ContainerApps package (for managed identity support) // This command triggers TWO prompts in sequence: diff --git a/tests/Aspire.Deployment.EndToEnd.Tests/AzureLogAnalyticsDeploymentTests.cs b/tests/Aspire.Deployment.EndToEnd.Tests/AzureLogAnalyticsDeploymentTests.cs index 0bb01c02aa0..7255b54f6ce 100644 --- a/tests/Aspire.Deployment.EndToEnd.Tests/AzureLogAnalyticsDeploymentTests.cs +++ b/tests/Aspire.Deployment.EndToEnd.Tests/AzureLogAnalyticsDeploymentTests.cs @@ -63,10 +63,6 @@ private async Task DeployAzureLogAnalyticsResourceCore(CancellationToken cancell using var terminal = DeploymentE2ETestHelpers.CreateTestTerminal(); var pendingRun = terminal.RunAsync(cancellationToken); - // Pattern searchers for aspire init - var waitingForInitComplete = new CellPatternSearcher() - .Find("Aspire initialization complete"); - // Pattern searchers for aspire add prompts var waitingForAddVersionSelectionPrompt = new CellPatternSearcher() .Find("(based on NuGet.config)"); @@ -91,15 +87,7 @@ private async Task DeployAzureLogAnalyticsResourceCore(CancellationToken cancell // Step 3: Create single-file AppHost using aspire init output.WriteLine("Step 3: Creating single-file AppHost with aspire init..."); - sequenceBuilder.Type("aspire init --language csharp") - .Enter() - // NuGet.config prompt may or may not appear depending on environment. - // Wait a moment then press Enter to dismiss if present, then wait for completion. - .Wait(TimeSpan.FromSeconds(5)) - .Enter() // Dismiss NuGet.config prompt if present (no-op if already auto-accepted) - .WaitUntil(s => waitingForInitComplete.Search(s).Count > 0, TimeSpan.FromMinutes(2)) - .DeclineAgentInitPrompt() - .WaitForSuccessPrompt(counter, TimeSpan.FromMinutes(2)); + sequenceBuilder.AspireInit(counter); // Step 4: Add Aspire.Hosting.Azure.OperationalInsights package output.WriteLine("Step 4: Adding Azure Log Analytics hosting package..."); diff --git a/tests/Aspire.Deployment.EndToEnd.Tests/AzureServiceBusDeploymentTests.cs b/tests/Aspire.Deployment.EndToEnd.Tests/AzureServiceBusDeploymentTests.cs index 81aa0439027..b5a1f86ebc5 100644 --- a/tests/Aspire.Deployment.EndToEnd.Tests/AzureServiceBusDeploymentTests.cs +++ b/tests/Aspire.Deployment.EndToEnd.Tests/AzureServiceBusDeploymentTests.cs @@ -63,10 +63,6 @@ private async Task DeployAzureServiceBusResourceCore(CancellationToken cancellat using var terminal = DeploymentE2ETestHelpers.CreateTestTerminal(); var pendingRun = terminal.RunAsync(cancellationToken); - // Pattern searchers for aspire init - var waitingForInitComplete = new CellPatternSearcher() - .Find("Aspire initialization complete"); - // Pattern searchers for aspire add prompts // Integration selection prompt appears when multiple packages match the search term var waitingForIntegrationSelectionPrompt = new CellPatternSearcher() @@ -96,15 +92,7 @@ private async Task DeployAzureServiceBusResourceCore(CancellationToken cancellat // Step 3: Create single-file AppHost using aspire init output.WriteLine("Step 3: Creating single-file AppHost with aspire init..."); - sequenceBuilder.Type("aspire init --language csharp") - .Enter() - // NuGet.config prompt may or may not appear depending on environment. - // Wait a moment then press Enter to dismiss if present, then wait for completion. - .Wait(TimeSpan.FromSeconds(5)) - .Enter() // Dismiss NuGet.config prompt if present (no-op if already auto-accepted) - .WaitUntil(s => waitingForInitComplete.Search(s).Count > 0, TimeSpan.FromMinutes(2)) - .DeclineAgentInitPrompt() - .WaitForSuccessPrompt(counter, TimeSpan.FromMinutes(2)); + sequenceBuilder.AspireInit(counter); // Step 4a: Add Aspire.Hosting.Azure.ContainerApps package (for managed identity support) // This command triggers TWO prompts in sequence: diff --git a/tests/Aspire.Deployment.EndToEnd.Tests/AzureStorageDeploymentTests.cs b/tests/Aspire.Deployment.EndToEnd.Tests/AzureStorageDeploymentTests.cs index 0534a78822f..274533792d6 100644 --- a/tests/Aspire.Deployment.EndToEnd.Tests/AzureStorageDeploymentTests.cs +++ b/tests/Aspire.Deployment.EndToEnd.Tests/AzureStorageDeploymentTests.cs @@ -63,10 +63,6 @@ private async Task DeployAzureStorageResourceCore(CancellationToken cancellation using var terminal = DeploymentE2ETestHelpers.CreateTestTerminal(); var pendingRun = terminal.RunAsync(cancellationToken); - // Pattern searchers for aspire init - var waitingForInitComplete = new CellPatternSearcher() - .Find("Aspire initialization complete"); - // Pattern searchers for aspire add prompts // Integration selection prompt appears when multiple packages match the search term var waitingForIntegrationSelectionPrompt = new CellPatternSearcher() @@ -96,15 +92,7 @@ private async Task DeployAzureStorageResourceCore(CancellationToken cancellation // Step 3: Create single-file AppHost using aspire init output.WriteLine("Step 3: Creating single-file AppHost with aspire init..."); - sequenceBuilder.Type("aspire init --language csharp") - .Enter() - // NuGet.config prompt may or may not appear depending on environment. - // Wait a moment then press Enter to dismiss if present, then wait for completion. - .Wait(TimeSpan.FromSeconds(5)) - .Enter() // Dismiss NuGet.config prompt if present (no-op if already auto-accepted) - .WaitUntil(s => waitingForInitComplete.Search(s).Count > 0, TimeSpan.FromMinutes(2)) - .DeclineAgentInitPrompt() - .WaitForSuccessPrompt(counter, TimeSpan.FromMinutes(2)); + sequenceBuilder.AspireInit(counter); // Step 4a: Add Aspire.Hosting.Azure.ContainerApps package (for managed identity support) // This command triggers TWO prompts in sequence: diff --git a/tests/Aspire.Deployment.EndToEnd.Tests/Helpers/DeploymentE2ETestHelpers.cs b/tests/Aspire.Deployment.EndToEnd.Tests/Helpers/DeploymentE2ETestHelpers.cs index ad0eb8a7f7a..8333e96b5bc 100644 --- a/tests/Aspire.Deployment.EndToEnd.Tests/Helpers/DeploymentE2ETestHelpers.cs +++ b/tests/Aspire.Deployment.EndToEnd.Tests/Helpers/DeploymentE2ETestHelpers.cs @@ -174,27 +174,4 @@ internal static Hex1bTerminalInputSequenceBuilder SourceAspireCliEnvironment( .WaitForSuccessPrompt(counter); } - /// - /// Runs aspire init and handles the NuGet.config and agent init prompts. - /// The agent init prompt is declined so the command exits cleanly. - /// - internal static Hex1bTerminalInputSequenceBuilder RunAspireInit( - this Hex1bTerminalInputSequenceBuilder builder, - SequenceCounter counter) - { - var waitingForInitComplete = new CellPatternSearcher() - .Find("Aspire initialization complete"); - - return builder - .Type("aspire init") - .Enter() - // NuGet.config prompt may or may not appear depending on environment. - // Wait a moment then press Enter to dismiss if present. - .Wait(TimeSpan.FromSeconds(5)) - .Enter() - .WaitUntil(s => waitingForInitComplete.Search(s).Count > 0, TimeSpan.FromMinutes(2)) - .DeclineAgentInitPrompt() - .WaitForSuccessPrompt(counter, TimeSpan.FromMinutes(2)); - } - } diff --git a/tests/Aspire.Deployment.EndToEnd.Tests/VnetKeyVaultInfraDeploymentTests.cs b/tests/Aspire.Deployment.EndToEnd.Tests/VnetKeyVaultInfraDeploymentTests.cs index 4d8d8931326..9fe92fa31c0 100644 --- a/tests/Aspire.Deployment.EndToEnd.Tests/VnetKeyVaultInfraDeploymentTests.cs +++ b/tests/Aspire.Deployment.EndToEnd.Tests/VnetKeyVaultInfraDeploymentTests.cs @@ -61,9 +61,6 @@ private async Task DeployVnetKeyVaultInfrastructureCore(CancellationToken cancel using var terminal = DeploymentE2ETestHelpers.CreateTestTerminal(); var pendingRun = terminal.RunAsync(cancellationToken); - var waitingForInitComplete = new CellPatternSearcher() - .Find("Aspire initialization complete"); - var waitingForVersionSelectionPrompt = new CellPatternSearcher() .Find("(based on NuGet.config)"); @@ -85,13 +82,7 @@ private async Task DeployVnetKeyVaultInfrastructureCore(CancellationToken cancel // Step 3: Create single-file AppHost using aspire init output.WriteLine("Step 3: Creating single-file AppHost with aspire init..."); - sequenceBuilder.Type("aspire init --language csharp") - .Enter() - .Wait(TimeSpan.FromSeconds(5)) - .Enter() - .WaitUntil(s => waitingForInitComplete.Search(s).Count > 0, TimeSpan.FromMinutes(2)) - .DeclineAgentInitPrompt() - .WaitForSuccessPrompt(counter, TimeSpan.FromMinutes(2)); + sequenceBuilder.AspireInit(counter); // Step 4a: Add Aspire.Hosting.Azure.AppContainers output.WriteLine("Step 4a: Adding Azure Container Apps hosting package..."); diff --git a/tests/Aspire.Deployment.EndToEnd.Tests/VnetSqlServerInfraDeploymentTests.cs b/tests/Aspire.Deployment.EndToEnd.Tests/VnetSqlServerInfraDeploymentTests.cs index 3e65252a628..f85d99b5d76 100644 --- a/tests/Aspire.Deployment.EndToEnd.Tests/VnetSqlServerInfraDeploymentTests.cs +++ b/tests/Aspire.Deployment.EndToEnd.Tests/VnetSqlServerInfraDeploymentTests.cs @@ -61,9 +61,6 @@ private async Task DeployVnetSqlServerInfrastructureCore(CancellationToken cance using var terminal = DeploymentE2ETestHelpers.CreateTestTerminal(); var pendingRun = terminal.RunAsync(cancellationToken); - var waitingForInitComplete = new CellPatternSearcher() - .Find("Aspire initialization complete"); - var waitingForVersionSelectionPrompt = new CellPatternSearcher() .Find("(based on NuGet.config)"); @@ -85,13 +82,7 @@ private async Task DeployVnetSqlServerInfrastructureCore(CancellationToken cance // Step 3: Create single-file AppHost using aspire init output.WriteLine("Step 3: Creating single-file AppHost with aspire init..."); - sequenceBuilder.Type("aspire init --language csharp") - .Enter() - .Wait(TimeSpan.FromSeconds(5)) - .Enter() - .WaitUntil(s => waitingForInitComplete.Search(s).Count > 0, TimeSpan.FromMinutes(2)) - .DeclineAgentInitPrompt() - .WaitForSuccessPrompt(counter, TimeSpan.FromMinutes(2)); + sequenceBuilder.AspireInit(counter); // Step 4a: Add Aspire.Hosting.Azure.AppContainers output.WriteLine("Step 4a: Adding Azure Container Apps hosting package..."); diff --git a/tests/Aspire.Deployment.EndToEnd.Tests/VnetStorageBlobInfraDeploymentTests.cs b/tests/Aspire.Deployment.EndToEnd.Tests/VnetStorageBlobInfraDeploymentTests.cs index 01e1138e91b..c1f1fe63c15 100644 --- a/tests/Aspire.Deployment.EndToEnd.Tests/VnetStorageBlobInfraDeploymentTests.cs +++ b/tests/Aspire.Deployment.EndToEnd.Tests/VnetStorageBlobInfraDeploymentTests.cs @@ -61,9 +61,6 @@ private async Task DeployVnetStorageBlobInfrastructureCore(CancellationToken can using var terminal = DeploymentE2ETestHelpers.CreateTestTerminal(); var pendingRun = terminal.RunAsync(cancellationToken); - var waitingForInitComplete = new CellPatternSearcher() - .Find("Aspire initialization complete"); - var waitingForVersionSelectionPrompt = new CellPatternSearcher() .Find("(based on NuGet.config)"); @@ -86,13 +83,7 @@ private async Task DeployVnetStorageBlobInfrastructureCore(CancellationToken can // Step 3: Create single-file AppHost using aspire init output.WriteLine("Step 3: Creating single-file AppHost with aspire init..."); - sequenceBuilder.Type("aspire init --language csharp") - .Enter() - .Wait(TimeSpan.FromSeconds(5)) - .Enter() - .WaitUntil(s => waitingForInitComplete.Search(s).Count > 0, TimeSpan.FromMinutes(2)) - .DeclineAgentInitPrompt() - .WaitForSuccessPrompt(counter, TimeSpan.FromMinutes(2)); + sequenceBuilder.AspireInit(counter); // Step 4a: Add Aspire.Hosting.Azure.AppContainers output.WriteLine("Step 4a: Adding Azure Container Apps hosting package..."); diff --git a/tests/Aspire.Hosting.Analyzers.Tests/Aspire.Hosting.Analyzers.Tests.csproj b/tests/Aspire.Hosting.Analyzers.Tests/Aspire.Hosting.Analyzers.Tests.csproj index 3d0b8dd918e..6ff40b49e13 100644 --- a/tests/Aspire.Hosting.Analyzers.Tests/Aspire.Hosting.Analyzers.Tests.csproj +++ b/tests/Aspire.Hosting.Analyzers.Tests/Aspire.Hosting.Analyzers.Tests.csproj @@ -7,6 +7,7 @@ + diff --git a/tests/Aspire.Hosting.CodeGeneration.Go.Tests/Snapshots/TwoPassScanningGeneratedAspire.verified.go b/tests/Aspire.Hosting.CodeGeneration.Go.Tests/Snapshots/TwoPassScanningGeneratedAspire.verified.go index 5205679851e..d1963bf455d 100644 --- a/tests/Aspire.Hosting.CodeGeneration.Go.Tests/Snapshots/TwoPassScanningGeneratedAspire.verified.go +++ b/tests/Aspire.Hosting.CodeGeneration.Go.Tests/Snapshots/TwoPassScanningGeneratedAspire.verified.go @@ -2580,6 +2580,207 @@ func (s *ContainerResource) WithContainerRegistry(registry *IResource) (*IResour return result.(*IResource), nil } +// WithBindMount adds a bind mount +func (s *ContainerResource) WithBindMount(source string, target string, isReadOnly bool) (*ContainerResource, error) { + reqArgs := map[string]any{ + "builder": SerializeValue(s.Handle()), + } + reqArgs["source"] = SerializeValue(source) + reqArgs["target"] = SerializeValue(target) + reqArgs["isReadOnly"] = SerializeValue(isReadOnly) + result, err := s.Client().InvokeCapability("Aspire.Hosting/withBindMount", reqArgs) + if err != nil { + return nil, err + } + return result.(*ContainerResource), nil +} + +// WithEntrypoint sets the container entrypoint +func (s *ContainerResource) WithEntrypoint(entrypoint string) (*ContainerResource, error) { + reqArgs := map[string]any{ + "builder": SerializeValue(s.Handle()), + } + reqArgs["entrypoint"] = SerializeValue(entrypoint) + result, err := s.Client().InvokeCapability("Aspire.Hosting/withEntrypoint", reqArgs) + if err != nil { + return nil, err + } + return result.(*ContainerResource), nil +} + +// WithImageTag sets the container image tag +func (s *ContainerResource) WithImageTag(tag string) (*ContainerResource, error) { + reqArgs := map[string]any{ + "builder": SerializeValue(s.Handle()), + } + reqArgs["tag"] = SerializeValue(tag) + result, err := s.Client().InvokeCapability("Aspire.Hosting/withImageTag", reqArgs) + if err != nil { + return nil, err + } + return result.(*ContainerResource), nil +} + +// WithImageRegistry sets the container image registry +func (s *ContainerResource) WithImageRegistry(registry string) (*ContainerResource, error) { + reqArgs := map[string]any{ + "builder": SerializeValue(s.Handle()), + } + reqArgs["registry"] = SerializeValue(registry) + result, err := s.Client().InvokeCapability("Aspire.Hosting/withImageRegistry", reqArgs) + if err != nil { + return nil, err + } + return result.(*ContainerResource), nil +} + +// WithImage sets the container image +func (s *ContainerResource) WithImage(image string, tag string) (*ContainerResource, error) { + reqArgs := map[string]any{ + "builder": SerializeValue(s.Handle()), + } + reqArgs["image"] = SerializeValue(image) + reqArgs["tag"] = SerializeValue(tag) + result, err := s.Client().InvokeCapability("Aspire.Hosting/withImage", reqArgs) + if err != nil { + return nil, err + } + return result.(*ContainerResource), nil +} + +// WithImageSHA256 sets the image SHA256 digest +func (s *ContainerResource) WithImageSHA256(sha256 string) (*ContainerResource, error) { + reqArgs := map[string]any{ + "builder": SerializeValue(s.Handle()), + } + reqArgs["sha256"] = SerializeValue(sha256) + result, err := s.Client().InvokeCapability("Aspire.Hosting/withImageSHA256", reqArgs) + if err != nil { + return nil, err + } + return result.(*ContainerResource), nil +} + +// WithContainerRuntimeArgs adds runtime arguments for the container +func (s *ContainerResource) WithContainerRuntimeArgs(args []string) (*ContainerResource, error) { + reqArgs := map[string]any{ + "builder": SerializeValue(s.Handle()), + } + reqArgs["args"] = SerializeValue(args) + result, err := s.Client().InvokeCapability("Aspire.Hosting/withContainerRuntimeArgs", reqArgs) + if err != nil { + return nil, err + } + return result.(*ContainerResource), nil +} + +// WithLifetime sets the lifetime behavior of the container resource +func (s *ContainerResource) WithLifetime(lifetime ContainerLifetime) (*ContainerResource, error) { + reqArgs := map[string]any{ + "builder": SerializeValue(s.Handle()), + } + reqArgs["lifetime"] = SerializeValue(lifetime) + result, err := s.Client().InvokeCapability("Aspire.Hosting/withLifetime", reqArgs) + if err != nil { + return nil, err + } + return result.(*ContainerResource), nil +} + +// WithImagePullPolicy sets the container image pull policy +func (s *ContainerResource) WithImagePullPolicy(pullPolicy ImagePullPolicy) (*ContainerResource, error) { + reqArgs := map[string]any{ + "builder": SerializeValue(s.Handle()), + } + reqArgs["pullPolicy"] = SerializeValue(pullPolicy) + result, err := s.Client().InvokeCapability("Aspire.Hosting/withImagePullPolicy", reqArgs) + if err != nil { + return nil, err + } + return result.(*ContainerResource), nil +} + +// PublishAsContainer configures the resource to be published as a container +func (s *ContainerResource) PublishAsContainer() (*ContainerResource, error) { + reqArgs := map[string]any{ + "builder": SerializeValue(s.Handle()), + } + result, err := s.Client().InvokeCapability("Aspire.Hosting/publishAsContainer", reqArgs) + if err != nil { + return nil, err + } + return result.(*ContainerResource), nil +} + +// WithDockerfile configures the resource to use a Dockerfile +func (s *ContainerResource) WithDockerfile(contextPath string, dockerfilePath string, stage string) (*ContainerResource, error) { + reqArgs := map[string]any{ + "builder": SerializeValue(s.Handle()), + } + reqArgs["contextPath"] = SerializeValue(contextPath) + reqArgs["dockerfilePath"] = SerializeValue(dockerfilePath) + reqArgs["stage"] = SerializeValue(stage) + result, err := s.Client().InvokeCapability("Aspire.Hosting/withDockerfile", reqArgs) + if err != nil { + return nil, err + } + return result.(*ContainerResource), nil +} + +// WithContainerName sets the container name +func (s *ContainerResource) WithContainerName(name string) (*ContainerResource, error) { + reqArgs := map[string]any{ + "builder": SerializeValue(s.Handle()), + } + reqArgs["name"] = SerializeValue(name) + result, err := s.Client().InvokeCapability("Aspire.Hosting/withContainerName", reqArgs) + if err != nil { + return nil, err + } + return result.(*ContainerResource), nil +} + +// WithBuildArg adds a build argument from a parameter resource +func (s *ContainerResource) WithBuildArg(name string, value *ParameterResource) (*ContainerResource, error) { + reqArgs := map[string]any{ + "builder": SerializeValue(s.Handle()), + } + reqArgs["name"] = SerializeValue(name) + reqArgs["value"] = SerializeValue(value) + result, err := s.Client().InvokeCapability("Aspire.Hosting/withBuildArg", reqArgs) + if err != nil { + return nil, err + } + return result.(*ContainerResource), nil +} + +// WithBuildSecret adds a build secret from a parameter resource +func (s *ContainerResource) WithBuildSecret(name string, value *ParameterResource) (*ContainerResource, error) { + reqArgs := map[string]any{ + "builder": SerializeValue(s.Handle()), + } + reqArgs["name"] = SerializeValue(name) + reqArgs["value"] = SerializeValue(value) + result, err := s.Client().InvokeCapability("Aspire.Hosting/withBuildSecret", reqArgs) + if err != nil { + return nil, err + } + return result.(*ContainerResource), nil +} + +// WithEndpointProxySupport configures endpoint proxy support +func (s *ContainerResource) WithEndpointProxySupport(proxyEnabled bool) (*ContainerResource, error) { + reqArgs := map[string]any{ + "builder": SerializeValue(s.Handle()), + } + reqArgs["proxyEnabled"] = SerializeValue(proxyEnabled) + result, err := s.Client().InvokeCapability("Aspire.Hosting/withEndpointProxySupport", reqArgs) + if err != nil { + return nil, err + } + return result.(*ContainerResource), nil +} + // WithDockerfileBaseImage sets the base image for a Dockerfile build func (s *ContainerResource) WithDockerfileBaseImage(buildImage string, runtimeImage string) (*IResource, error) { reqArgs := map[string]any{ @@ -2594,6 +2795,19 @@ func (s *ContainerResource) WithDockerfileBaseImage(buildImage string, runtimeIm return result.(*IResource), nil } +// WithContainerNetworkAlias adds a network alias for the container +func (s *ContainerResource) WithContainerNetworkAlias(alias string) (*ContainerResource, error) { + reqArgs := map[string]any{ + "builder": SerializeValue(s.Handle()), + } + reqArgs["alias"] = SerializeValue(alias) + result, err := s.Client().InvokeCapability("Aspire.Hosting/withContainerNetworkAlias", reqArgs) + if err != nil { + return nil, err + } + return result.(*ContainerResource), nil +} + // WithMcpServer configures an MCP server endpoint on the resource func (s *ContainerResource) WithMcpServer(path string, endpointName string) (*IResourceWithEndpoints, error) { reqArgs := map[string]any{ @@ -2633,6 +2847,18 @@ func (s *ContainerResource) WithOtlpExporterProtocol(protocol OtlpProtocol) (*IR return result.(*IResourceWithEnvironment), nil } +// PublishAsConnectionString publishes the resource as a connection string +func (s *ContainerResource) PublishAsConnectionString() (*ContainerResource, error) { + reqArgs := map[string]any{ + "builder": SerializeValue(s.Handle()), + } + result, err := s.Client().InvokeCapability("Aspire.Hosting/publishAsConnectionString", reqArgs) + if err != nil { + return nil, err + } + return result.(*ContainerResource), nil +} + // WithRequiredCommand adds a required command dependency func (s *ContainerResource) WithRequiredCommand(command string, helpLink string) (*IResource, error) { reqArgs := map[string]any{ @@ -3394,6 +3620,21 @@ func (s *ContainerResource) WithPipelineConfiguration(callback func(...any) any) return result.(*IResource), nil } +// WithVolume adds a volume +func (s *ContainerResource) WithVolume(target string, name string, isReadOnly bool) (*ContainerResource, error) { + reqArgs := map[string]any{ + "resource": SerializeValue(s.Handle()), + } + reqArgs["target"] = SerializeValue(target) + reqArgs["name"] = SerializeValue(name) + reqArgs["isReadOnly"] = SerializeValue(isReadOnly) + result, err := s.Client().InvokeCapability("Aspire.Hosting/withVolume", reqArgs) + if err != nil { + return nil, err + } + return result.(*ContainerResource), nil +} + // GetResourceName gets the resource name func (s *ContainerResource) GetResourceName() (*string, error) { reqArgs := map[string]any{ @@ -5256,6 +5497,59 @@ func (s *ExecutableResource) WithDockerfileBaseImage(buildImage string, runtimeI return result.(*IResource), nil } +// PublishAsDockerFile publishes the executable as a Docker container +func (s *ExecutableResource) PublishAsDockerFile() (*ExecutableResource, error) { + reqArgs := map[string]any{ + "builder": SerializeValue(s.Handle()), + } + result, err := s.Client().InvokeCapability("Aspire.Hosting/publishAsDockerFile", reqArgs) + if err != nil { + return nil, err + } + return result.(*ExecutableResource), nil +} + +// PublishAsDockerFileWithConfigure publishes an executable as a Docker file with optional container configuration +func (s *ExecutableResource) PublishAsDockerFileWithConfigure(configure func(...any) any) (*ExecutableResource, error) { + reqArgs := map[string]any{ + "builder": SerializeValue(s.Handle()), + } + if configure != nil { + reqArgs["configure"] = RegisterCallback(configure) + } + result, err := s.Client().InvokeCapability("Aspire.Hosting/publishAsDockerFileWithConfigure", reqArgs) + if err != nil { + return nil, err + } + return result.(*ExecutableResource), nil +} + +// WithExecutableCommand sets the executable command +func (s *ExecutableResource) WithExecutableCommand(command string) (*ExecutableResource, error) { + reqArgs := map[string]any{ + "builder": SerializeValue(s.Handle()), + } + reqArgs["command"] = SerializeValue(command) + result, err := s.Client().InvokeCapability("Aspire.Hosting/withExecutableCommand", reqArgs) + if err != nil { + return nil, err + } + return result.(*ExecutableResource), nil +} + +// WithWorkingDirectory sets the executable working directory +func (s *ExecutableResource) WithWorkingDirectory(workingDirectory string) (*ExecutableResource, error) { + reqArgs := map[string]any{ + "builder": SerializeValue(s.Handle()), + } + reqArgs["workingDirectory"] = SerializeValue(workingDirectory) + result, err := s.Client().InvokeCapability("Aspire.Hosting/withWorkingDirectory", reqArgs) + if err != nil { + return nil, err + } + return result.(*ExecutableResource), nil +} + // WithMcpServer configures an MCP server endpoint on the resource func (s *ExecutableResource) WithMcpServer(path string, endpointName string) (*IResourceWithEndpoints, error) { reqArgs := map[string]any{ @@ -8251,6 +8545,46 @@ func (s *ProjectResource) WithOtlpExporterProtocol(protocol OtlpProtocol) (*IRes return result.(*IResourceWithEnvironment), nil } +// WithReplicas sets the number of replicas +func (s *ProjectResource) WithReplicas(replicas float64) (*ProjectResource, error) { + reqArgs := map[string]any{ + "builder": SerializeValue(s.Handle()), + } + reqArgs["replicas"] = SerializeValue(replicas) + result, err := s.Client().InvokeCapability("Aspire.Hosting/withReplicas", reqArgs) + if err != nil { + return nil, err + } + return result.(*ProjectResource), nil +} + +// DisableForwardedHeaders disables forwarded headers for the project +func (s *ProjectResource) DisableForwardedHeaders() (*ProjectResource, error) { + reqArgs := map[string]any{ + "builder": SerializeValue(s.Handle()), + } + result, err := s.Client().InvokeCapability("Aspire.Hosting/disableForwardedHeaders", reqArgs) + if err != nil { + return nil, err + } + return result.(*ProjectResource), nil +} + +// PublishAsDockerFile publishes a project as a Docker file with optional container configuration +func (s *ProjectResource) PublishAsDockerFile(configure func(...any) any) (*ProjectResource, error) { + reqArgs := map[string]any{ + "builder": SerializeValue(s.Handle()), + } + if configure != nil { + reqArgs["configure"] = RegisterCallback(configure) + } + result, err := s.Client().InvokeCapability("Aspire.Hosting/publishProjectAsDockerFileWithConfigure", reqArgs) + if err != nil { + return nil, err + } + return result.(*ProjectResource), nil +} + // WithRequiredCommand adds a required command dependency func (s *ProjectResource) WithRequiredCommand(command string, helpLink string) (*IResource, error) { reqArgs := map[string]any{ diff --git a/tests/Aspire.Hosting.CodeGeneration.Java.Tests/Snapshots/TwoPassScanningGeneratedAspire.verified.java b/tests/Aspire.Hosting.CodeGeneration.Java.Tests/Snapshots/TwoPassScanningGeneratedAspire.verified.java index e9977c1d198..f3e4b6a0274 100644 --- a/tests/Aspire.Hosting.CodeGeneration.Java.Tests/Snapshots/TwoPassScanningGeneratedAspire.verified.java +++ b/tests/Aspire.Hosting.CodeGeneration.Java.Tests/Snapshots/TwoPassScanningGeneratedAspire.verified.java @@ -2156,6 +2156,140 @@ public IResource withContainerRegistry(IResource registry) { return (IResource) getClient().invokeCapability("Aspire.Hosting/withContainerRegistry", reqArgs); } + /** Adds a bind mount */ + public ContainerResource withBindMount(String source, String target, Boolean isReadOnly) { + Map reqArgs = new HashMap<>(); + reqArgs.put("builder", AspireClient.serializeValue(getHandle())); + reqArgs.put("source", AspireClient.serializeValue(source)); + reqArgs.put("target", AspireClient.serializeValue(target)); + if (isReadOnly != null) { + reqArgs.put("isReadOnly", AspireClient.serializeValue(isReadOnly)); + } + return (ContainerResource) getClient().invokeCapability("Aspire.Hosting/withBindMount", reqArgs); + } + + /** Sets the container entrypoint */ + public ContainerResource withEntrypoint(String entrypoint) { + Map reqArgs = new HashMap<>(); + reqArgs.put("builder", AspireClient.serializeValue(getHandle())); + reqArgs.put("entrypoint", AspireClient.serializeValue(entrypoint)); + return (ContainerResource) getClient().invokeCapability("Aspire.Hosting/withEntrypoint", reqArgs); + } + + /** Sets the container image tag */ + public ContainerResource withImageTag(String tag) { + Map reqArgs = new HashMap<>(); + reqArgs.put("builder", AspireClient.serializeValue(getHandle())); + reqArgs.put("tag", AspireClient.serializeValue(tag)); + return (ContainerResource) getClient().invokeCapability("Aspire.Hosting/withImageTag", reqArgs); + } + + /** Sets the container image registry */ + public ContainerResource withImageRegistry(String registry) { + Map reqArgs = new HashMap<>(); + reqArgs.put("builder", AspireClient.serializeValue(getHandle())); + reqArgs.put("registry", AspireClient.serializeValue(registry)); + return (ContainerResource) getClient().invokeCapability("Aspire.Hosting/withImageRegistry", reqArgs); + } + + /** Sets the container image */ + public ContainerResource withImage(String image, String tag) { + Map reqArgs = new HashMap<>(); + reqArgs.put("builder", AspireClient.serializeValue(getHandle())); + reqArgs.put("image", AspireClient.serializeValue(image)); + if (tag != null) { + reqArgs.put("tag", AspireClient.serializeValue(tag)); + } + return (ContainerResource) getClient().invokeCapability("Aspire.Hosting/withImage", reqArgs); + } + + /** Sets the image SHA256 digest */ + public ContainerResource withImageSHA256(String sha256) { + Map reqArgs = new HashMap<>(); + reqArgs.put("builder", AspireClient.serializeValue(getHandle())); + reqArgs.put("sha256", AspireClient.serializeValue(sha256)); + return (ContainerResource) getClient().invokeCapability("Aspire.Hosting/withImageSHA256", reqArgs); + } + + /** Adds runtime arguments for the container */ + public ContainerResource withContainerRuntimeArgs(String[] args) { + Map reqArgs = new HashMap<>(); + reqArgs.put("builder", AspireClient.serializeValue(getHandle())); + reqArgs.put("args", AspireClient.serializeValue(args)); + return (ContainerResource) getClient().invokeCapability("Aspire.Hosting/withContainerRuntimeArgs", reqArgs); + } + + /** Sets the lifetime behavior of the container resource */ + public ContainerResource withLifetime(ContainerLifetime lifetime) { + Map reqArgs = new HashMap<>(); + reqArgs.put("builder", AspireClient.serializeValue(getHandle())); + reqArgs.put("lifetime", AspireClient.serializeValue(lifetime)); + return (ContainerResource) getClient().invokeCapability("Aspire.Hosting/withLifetime", reqArgs); + } + + /** Sets the container image pull policy */ + public ContainerResource withImagePullPolicy(ImagePullPolicy pullPolicy) { + Map reqArgs = new HashMap<>(); + reqArgs.put("builder", AspireClient.serializeValue(getHandle())); + reqArgs.put("pullPolicy", AspireClient.serializeValue(pullPolicy)); + return (ContainerResource) getClient().invokeCapability("Aspire.Hosting/withImagePullPolicy", reqArgs); + } + + /** Configures the resource to be published as a container */ + public ContainerResource publishAsContainer() { + Map reqArgs = new HashMap<>(); + reqArgs.put("builder", AspireClient.serializeValue(getHandle())); + return (ContainerResource) getClient().invokeCapability("Aspire.Hosting/publishAsContainer", reqArgs); + } + + /** Configures the resource to use a Dockerfile */ + public ContainerResource withDockerfile(String contextPath, String dockerfilePath, String stage) { + Map reqArgs = new HashMap<>(); + reqArgs.put("builder", AspireClient.serializeValue(getHandle())); + reqArgs.put("contextPath", AspireClient.serializeValue(contextPath)); + if (dockerfilePath != null) { + reqArgs.put("dockerfilePath", AspireClient.serializeValue(dockerfilePath)); + } + if (stage != null) { + reqArgs.put("stage", AspireClient.serializeValue(stage)); + } + return (ContainerResource) getClient().invokeCapability("Aspire.Hosting/withDockerfile", reqArgs); + } + + /** Sets the container name */ + public ContainerResource withContainerName(String name) { + Map reqArgs = new HashMap<>(); + reqArgs.put("builder", AspireClient.serializeValue(getHandle())); + reqArgs.put("name", AspireClient.serializeValue(name)); + return (ContainerResource) getClient().invokeCapability("Aspire.Hosting/withContainerName", reqArgs); + } + + /** Adds a build argument from a parameter resource */ + public ContainerResource withBuildArg(String name, ParameterResource value) { + Map reqArgs = new HashMap<>(); + reqArgs.put("builder", AspireClient.serializeValue(getHandle())); + reqArgs.put("name", AspireClient.serializeValue(name)); + reqArgs.put("value", AspireClient.serializeValue(value)); + return (ContainerResource) getClient().invokeCapability("Aspire.Hosting/withBuildArg", reqArgs); + } + + /** Adds a build secret from a parameter resource */ + public ContainerResource withBuildSecret(String name, ParameterResource value) { + Map reqArgs = new HashMap<>(); + reqArgs.put("builder", AspireClient.serializeValue(getHandle())); + reqArgs.put("name", AspireClient.serializeValue(name)); + reqArgs.put("value", AspireClient.serializeValue(value)); + return (ContainerResource) getClient().invokeCapability("Aspire.Hosting/withBuildSecret", reqArgs); + } + + /** Configures endpoint proxy support */ + public ContainerResource withEndpointProxySupport(boolean proxyEnabled) { + Map reqArgs = new HashMap<>(); + reqArgs.put("builder", AspireClient.serializeValue(getHandle())); + reqArgs.put("proxyEnabled", AspireClient.serializeValue(proxyEnabled)); + return (ContainerResource) getClient().invokeCapability("Aspire.Hosting/withEndpointProxySupport", reqArgs); + } + /** Sets the base image for a Dockerfile build */ public IResource withDockerfileBaseImage(String buildImage, String runtimeImage) { Map reqArgs = new HashMap<>(); @@ -2169,6 +2303,14 @@ public IResource withDockerfileBaseImage(String buildImage, String runtimeImage) return (IResource) getClient().invokeCapability("Aspire.Hosting/withDockerfileBaseImage", reqArgs); } + /** Adds a network alias for the container */ + public ContainerResource withContainerNetworkAlias(String alias) { + Map reqArgs = new HashMap<>(); + reqArgs.put("builder", AspireClient.serializeValue(getHandle())); + reqArgs.put("alias", AspireClient.serializeValue(alias)); + return (ContainerResource) getClient().invokeCapability("Aspire.Hosting/withContainerNetworkAlias", reqArgs); + } + /** Configures an MCP server endpoint on the resource */ public IResourceWithEndpoints withMcpServer(String path, String endpointName) { Map reqArgs = new HashMap<>(); @@ -2197,6 +2339,13 @@ public IResourceWithEnvironment withOtlpExporterProtocol(OtlpProtocol protocol) return (IResourceWithEnvironment) getClient().invokeCapability("Aspire.Hosting/withOtlpExporterProtocol", reqArgs); } + /** Publishes the resource as a connection string */ + public ContainerResource publishAsConnectionString() { + Map reqArgs = new HashMap<>(); + reqArgs.put("builder", AspireClient.serializeValue(getHandle())); + return (ContainerResource) getClient().invokeCapability("Aspire.Hosting/publishAsConnectionString", reqArgs); + } + /** Adds a required command dependency */ public IResource withRequiredCommand(String command, String helpLink) { Map reqArgs = new HashMap<>(); @@ -2771,6 +2920,20 @@ public IResource withPipelineConfiguration(Function callback) return (IResource) getClient().invokeCapability("Aspire.Hosting/withPipelineConfiguration", reqArgs); } + /** Adds a volume */ + public ContainerResource withVolume(String target, String name, Boolean isReadOnly) { + Map reqArgs = new HashMap<>(); + reqArgs.put("resource", AspireClient.serializeValue(getHandle())); + reqArgs.put("target", AspireClient.serializeValue(target)); + if (name != null) { + reqArgs.put("name", AspireClient.serializeValue(name)); + } + if (isReadOnly != null) { + reqArgs.put("isReadOnly", AspireClient.serializeValue(isReadOnly)); + } + return (ContainerResource) getClient().invokeCapability("Aspire.Hosting/withVolume", reqArgs); + } + /** Gets the resource name */ public String getResourceName() { Map reqArgs = new HashMap<>(); @@ -4054,6 +4217,39 @@ public IResource withDockerfileBaseImage(String buildImage, String runtimeImage) return (IResource) getClient().invokeCapability("Aspire.Hosting/withDockerfileBaseImage", reqArgs); } + /** Publishes the executable as a Docker container */ + public ExecutableResource publishAsDockerFile() { + Map reqArgs = new HashMap<>(); + reqArgs.put("builder", AspireClient.serializeValue(getHandle())); + return (ExecutableResource) getClient().invokeCapability("Aspire.Hosting/publishAsDockerFile", reqArgs); + } + + /** Publishes an executable as a Docker file with optional container configuration */ + public ExecutableResource publishAsDockerFileWithConfigure(Function configure) { + Map reqArgs = new HashMap<>(); + reqArgs.put("builder", AspireClient.serializeValue(getHandle())); + if (configure != null) { + reqArgs.put("configure", getClient().registerCallback(configure)); + } + return (ExecutableResource) getClient().invokeCapability("Aspire.Hosting/publishAsDockerFileWithConfigure", reqArgs); + } + + /** Sets the executable command */ + public ExecutableResource withExecutableCommand(String command) { + Map reqArgs = new HashMap<>(); + reqArgs.put("builder", AspireClient.serializeValue(getHandle())); + reqArgs.put("command", AspireClient.serializeValue(command)); + return (ExecutableResource) getClient().invokeCapability("Aspire.Hosting/withExecutableCommand", reqArgs); + } + + /** Sets the executable working directory */ + public ExecutableResource withWorkingDirectory(String workingDirectory) { + Map reqArgs = new HashMap<>(); + reqArgs.put("builder", AspireClient.serializeValue(getHandle())); + reqArgs.put("workingDirectory", AspireClient.serializeValue(workingDirectory)); + return (ExecutableResource) getClient().invokeCapability("Aspire.Hosting/withWorkingDirectory", reqArgs); + } + /** Configures an MCP server endpoint on the resource */ public IResourceWithEndpoints withMcpServer(String path, String endpointName) { Map reqArgs = new HashMap<>(); @@ -6154,6 +6350,31 @@ public IResourceWithEnvironment withOtlpExporterProtocol(OtlpProtocol protocol) return (IResourceWithEnvironment) getClient().invokeCapability("Aspire.Hosting/withOtlpExporterProtocol", reqArgs); } + /** Sets the number of replicas */ + public ProjectResource withReplicas(double replicas) { + Map reqArgs = new HashMap<>(); + reqArgs.put("builder", AspireClient.serializeValue(getHandle())); + reqArgs.put("replicas", AspireClient.serializeValue(replicas)); + return (ProjectResource) getClient().invokeCapability("Aspire.Hosting/withReplicas", reqArgs); + } + + /** Disables forwarded headers for the project */ + public ProjectResource disableForwardedHeaders() { + Map reqArgs = new HashMap<>(); + reqArgs.put("builder", AspireClient.serializeValue(getHandle())); + return (ProjectResource) getClient().invokeCapability("Aspire.Hosting/disableForwardedHeaders", reqArgs); + } + + /** Publishes a project as a Docker file with optional container configuration */ + public ProjectResource publishAsDockerFile(Function configure) { + Map reqArgs = new HashMap<>(); + reqArgs.put("builder", AspireClient.serializeValue(getHandle())); + if (configure != null) { + reqArgs.put("configure", getClient().registerCallback(configure)); + } + return (ProjectResource) getClient().invokeCapability("Aspire.Hosting/publishProjectAsDockerFileWithConfigure", reqArgs); + } + /** Adds a required command dependency */ public IResource withRequiredCommand(String command, String helpLink) { Map reqArgs = new HashMap<>(); diff --git a/tests/Aspire.Hosting.CodeGeneration.Python.Tests/Snapshots/TwoPassScanningGeneratedAspire.verified.py b/tests/Aspire.Hosting.CodeGeneration.Python.Tests/Snapshots/TwoPassScanningGeneratedAspire.verified.py index b8594ebb9ad..1ec0aae3a77 100644 --- a/tests/Aspire.Hosting.CodeGeneration.Python.Tests/Snapshots/TwoPassScanningGeneratedAspire.verified.py +++ b/tests/Aspire.Hosting.CodeGeneration.Python.Tests/Snapshots/TwoPassScanningGeneratedAspire.verified.py @@ -1434,6 +1434,105 @@ def with_container_registry(self, registry: IResource) -> IResource: args["registry"] = serialize_value(registry) return self._client.invoke_capability("Aspire.Hosting/withContainerRegistry", args) + def with_bind_mount(self, source: str, target: str, is_read_only: bool = False) -> ContainerResource: + """Adds a bind mount""" + args: Dict[str, Any] = { "builder": serialize_value(self._handle) } + args["source"] = serialize_value(source) + args["target"] = serialize_value(target) + args["isReadOnly"] = serialize_value(is_read_only) + return self._client.invoke_capability("Aspire.Hosting/withBindMount", args) + + def with_entrypoint(self, entrypoint: str) -> ContainerResource: + """Sets the container entrypoint""" + args: Dict[str, Any] = { "builder": serialize_value(self._handle) } + args["entrypoint"] = serialize_value(entrypoint) + return self._client.invoke_capability("Aspire.Hosting/withEntrypoint", args) + + def with_image_tag(self, tag: str) -> ContainerResource: + """Sets the container image tag""" + args: Dict[str, Any] = { "builder": serialize_value(self._handle) } + args["tag"] = serialize_value(tag) + return self._client.invoke_capability("Aspire.Hosting/withImageTag", args) + + def with_image_registry(self, registry: str) -> ContainerResource: + """Sets the container image registry""" + args: Dict[str, Any] = { "builder": serialize_value(self._handle) } + args["registry"] = serialize_value(registry) + return self._client.invoke_capability("Aspire.Hosting/withImageRegistry", args) + + def with_image(self, image: str, tag: str | None = None) -> ContainerResource: + """Sets the container image""" + args: Dict[str, Any] = { "builder": serialize_value(self._handle) } + args["image"] = serialize_value(image) + if tag is not None: + args["tag"] = serialize_value(tag) + return self._client.invoke_capability("Aspire.Hosting/withImage", args) + + def with_image_sha256(self, sha256: str) -> ContainerResource: + """Sets the image SHA256 digest""" + args: Dict[str, Any] = { "builder": serialize_value(self._handle) } + args["sha256"] = serialize_value(sha256) + return self._client.invoke_capability("Aspire.Hosting/withImageSHA256", args) + + def with_container_runtime_args(self, args: list[str]) -> ContainerResource: + """Adds runtime arguments for the container""" + args: Dict[str, Any] = { "builder": serialize_value(self._handle) } + args["args"] = serialize_value(args) + return self._client.invoke_capability("Aspire.Hosting/withContainerRuntimeArgs", args) + + def with_lifetime(self, lifetime: ContainerLifetime) -> ContainerResource: + """Sets the lifetime behavior of the container resource""" + args: Dict[str, Any] = { "builder": serialize_value(self._handle) } + args["lifetime"] = serialize_value(lifetime) + return self._client.invoke_capability("Aspire.Hosting/withLifetime", args) + + def with_image_pull_policy(self, pull_policy: ImagePullPolicy) -> ContainerResource: + """Sets the container image pull policy""" + args: Dict[str, Any] = { "builder": serialize_value(self._handle) } + args["pullPolicy"] = serialize_value(pull_policy) + return self._client.invoke_capability("Aspire.Hosting/withImagePullPolicy", args) + + def publish_as_container(self) -> ContainerResource: + """Configures the resource to be published as a container""" + args: Dict[str, Any] = { "builder": serialize_value(self._handle) } + return self._client.invoke_capability("Aspire.Hosting/publishAsContainer", args) + + def with_dockerfile(self, context_path: str, dockerfile_path: str | None = None, stage: str | None = None) -> ContainerResource: + """Configures the resource to use a Dockerfile""" + args: Dict[str, Any] = { "builder": serialize_value(self._handle) } + args["contextPath"] = serialize_value(context_path) + if dockerfile_path is not None: + args["dockerfilePath"] = serialize_value(dockerfile_path) + if stage is not None: + args["stage"] = serialize_value(stage) + return self._client.invoke_capability("Aspire.Hosting/withDockerfile", args) + + def with_container_name(self, name: str) -> ContainerResource: + """Sets the container name""" + args: Dict[str, Any] = { "builder": serialize_value(self._handle) } + args["name"] = serialize_value(name) + return self._client.invoke_capability("Aspire.Hosting/withContainerName", args) + + def with_build_arg(self, name: str, value: ParameterResource) -> ContainerResource: + """Adds a build argument from a parameter resource""" + args: Dict[str, Any] = { "builder": serialize_value(self._handle) } + args["name"] = serialize_value(name) + args["value"] = serialize_value(value) + return self._client.invoke_capability("Aspire.Hosting/withBuildArg", args) + + def with_build_secret(self, name: str, value: ParameterResource) -> ContainerResource: + """Adds a build secret from a parameter resource""" + args: Dict[str, Any] = { "builder": serialize_value(self._handle) } + args["name"] = serialize_value(name) + args["value"] = serialize_value(value) + return self._client.invoke_capability("Aspire.Hosting/withBuildSecret", args) + + def with_endpoint_proxy_support(self, proxy_enabled: bool) -> ContainerResource: + """Configures endpoint proxy support""" + args: Dict[str, Any] = { "builder": serialize_value(self._handle) } + args["proxyEnabled"] = serialize_value(proxy_enabled) + return self._client.invoke_capability("Aspire.Hosting/withEndpointProxySupport", args) + def with_dockerfile_base_image(self, build_image: str | None = None, runtime_image: str | None = None) -> IResource: """Sets the base image for a Dockerfile build""" args: Dict[str, Any] = { "builder": serialize_value(self._handle) } @@ -1443,6 +1542,12 @@ def with_dockerfile_base_image(self, build_image: str | None = None, runtime_ima args["runtimeImage"] = serialize_value(runtime_image) return self._client.invoke_capability("Aspire.Hosting/withDockerfileBaseImage", args) + def with_container_network_alias(self, alias: str) -> ContainerResource: + """Adds a network alias for the container""" + args: Dict[str, Any] = { "builder": serialize_value(self._handle) } + args["alias"] = serialize_value(alias) + return self._client.invoke_capability("Aspire.Hosting/withContainerNetworkAlias", args) + def with_mcp_server(self, path: str = "/mcp", endpoint_name: str | None = None) -> IResourceWithEndpoints: """Configures an MCP server endpoint on the resource""" args: Dict[str, Any] = { "builder": serialize_value(self._handle) } @@ -1462,6 +1567,11 @@ def with_otlp_exporter_protocol(self, protocol: OtlpProtocol) -> IResourceWithEn args["protocol"] = serialize_value(protocol) return self._client.invoke_capability("Aspire.Hosting/withOtlpExporterProtocol", args) + def publish_as_connection_string(self) -> ContainerResource: + """Publishes the resource as a connection string""" + args: Dict[str, Any] = { "builder": serialize_value(self._handle) } + return self._client.invoke_capability("Aspire.Hosting/publishAsConnectionString", args) + def with_required_command(self, command: str, help_link: str | None = None) -> IResource: """Adds a required command dependency""" args: Dict[str, Any] = { "builder": serialize_value(self._handle) } @@ -1883,6 +1993,15 @@ def with_pipeline_configuration(self, callback: Callable[[PipelineConfigurationC args["callback"] = callback_id return self._client.invoke_capability("Aspire.Hosting/withPipelineConfiguration", args) + def with_volume(self, target: str, name: str | None = None, is_read_only: bool = False) -> ContainerResource: + """Adds a volume""" + args: Dict[str, Any] = { "resource": serialize_value(self._handle) } + args["target"] = serialize_value(target) + if name is not None: + args["name"] = serialize_value(name) + args["isReadOnly"] = serialize_value(is_read_only) + return self._client.invoke_capability("Aspire.Hosting/withVolume", args) + def get_resource_name(self) -> str: """Gets the resource name""" args: Dict[str, Any] = { "resource": serialize_value(self._handle) } @@ -2826,6 +2945,31 @@ def with_dockerfile_base_image(self, build_image: str | None = None, runtime_ima args["runtimeImage"] = serialize_value(runtime_image) return self._client.invoke_capability("Aspire.Hosting/withDockerfileBaseImage", args) + def publish_as_docker_file(self) -> ExecutableResource: + """Publishes the executable as a Docker container""" + args: Dict[str, Any] = { "builder": serialize_value(self._handle) } + return self._client.invoke_capability("Aspire.Hosting/publishAsDockerFile", args) + + def publish_as_docker_file_with_configure(self, configure: Callable[[ContainerResource], None]) -> ExecutableResource: + """Publishes an executable as a Docker file with optional container configuration""" + args: Dict[str, Any] = { "builder": serialize_value(self._handle) } + configure_id = register_callback(configure) if configure is not None else None + if configure_id is not None: + args["configure"] = configure_id + return self._client.invoke_capability("Aspire.Hosting/publishAsDockerFileWithConfigure", args) + + def with_executable_command(self, command: str) -> ExecutableResource: + """Sets the executable command""" + args: Dict[str, Any] = { "builder": serialize_value(self._handle) } + args["command"] = serialize_value(command) + return self._client.invoke_capability("Aspire.Hosting/withExecutableCommand", args) + + def with_working_directory(self, working_directory: str) -> ExecutableResource: + """Sets the executable working directory""" + args: Dict[str, Any] = { "builder": serialize_value(self._handle) } + args["workingDirectory"] = serialize_value(working_directory) + return self._client.invoke_capability("Aspire.Hosting/withWorkingDirectory", args) + def with_mcp_server(self, path: str = "/mcp", endpoint_name: str | None = None) -> IResourceWithEndpoints: """Configures an MCP server endpoint on the resource""" args: Dict[str, Any] = { "builder": serialize_value(self._handle) } @@ -4385,6 +4529,25 @@ def with_otlp_exporter_protocol(self, protocol: OtlpProtocol) -> IResourceWithEn args["protocol"] = serialize_value(protocol) return self._client.invoke_capability("Aspire.Hosting/withOtlpExporterProtocol", args) + def with_replicas(self, replicas: float) -> ProjectResource: + """Sets the number of replicas""" + args: Dict[str, Any] = { "builder": serialize_value(self._handle) } + args["replicas"] = serialize_value(replicas) + return self._client.invoke_capability("Aspire.Hosting/withReplicas", args) + + def disable_forwarded_headers(self) -> ProjectResource: + """Disables forwarded headers for the project""" + args: Dict[str, Any] = { "builder": serialize_value(self._handle) } + return self._client.invoke_capability("Aspire.Hosting/disableForwardedHeaders", args) + + def publish_as_docker_file(self, configure: Callable[[ContainerResource], None] | None = None) -> ProjectResource: + """Publishes a project as a Docker file with optional container configuration""" + args: Dict[str, Any] = { "builder": serialize_value(self._handle) } + configure_id = register_callback(configure) if configure is not None else None + if configure_id is not None: + args["configure"] = configure_id + return self._client.invoke_capability("Aspire.Hosting/publishProjectAsDockerFileWithConfigure", args) + def with_required_command(self, command: str, help_link: str | None = None) -> IResource: """Adds a required command dependency""" args: Dict[str, Any] = { "builder": serialize_value(self._handle) } @@ -4961,7 +5124,14 @@ class ReferenceExpression(HandleWrapperBase): def __init__(self, handle: Handle, client: AspireClient): super().__init__(handle, client) - pass + def get_value(self, cancellation_token: CancellationToken) -> str: + """Gets the resolved string value of the reference expression asynchronously""" + args: Dict[str, Any] = { "context": serialize_value(self._handle) } + cancellation_token_id = register_cancellation(cancellation_token, self._client) if cancellation_token is not None else None + if cancellation_token_id is not None: + args["cancellationToken"] = cancellation_token_id + return self._client.invoke_capability("Aspire.Hosting.ApplicationModel/getValue", args) + class ReferenceExpressionBuilder(HandleWrapperBase): def __init__(self, handle: Handle, client: AspireClient): diff --git a/tests/Aspire.Hosting.CodeGeneration.Rust.Tests/Snapshots/TwoPassScanningGeneratedAspire.verified.rs b/tests/Aspire.Hosting.CodeGeneration.Rust.Tests/Snapshots/TwoPassScanningGeneratedAspire.verified.rs index 22cba9c57d9..5ec2aeaf225 100644 --- a/tests/Aspire.Hosting.CodeGeneration.Rust.Tests/Snapshots/TwoPassScanningGeneratedAspire.verified.rs +++ b/tests/Aspire.Hosting.CodeGeneration.Rust.Tests/Snapshots/TwoPassScanningGeneratedAspire.verified.rs @@ -2555,6 +2555,170 @@ impl ContainerResource { Ok(IResource::new(handle, self.client.clone())) } + /// Adds a bind mount + pub fn with_bind_mount(&self, source: &str, target: &str, is_read_only: Option) -> Result> { + let mut args: HashMap = HashMap::new(); + args.insert("builder".to_string(), self.handle.to_json()); + args.insert("source".to_string(), serde_json::to_value(&source).unwrap_or(Value::Null)); + args.insert("target".to_string(), serde_json::to_value(&target).unwrap_or(Value::Null)); + if let Some(ref v) = is_read_only { + args.insert("isReadOnly".to_string(), serde_json::to_value(v).unwrap_or(Value::Null)); + } + let result = self.client.invoke_capability("Aspire.Hosting/withBindMount", args)?; + let handle: Handle = serde_json::from_value(result)?; + Ok(ContainerResource::new(handle, self.client.clone())) + } + + /// Sets the container entrypoint + pub fn with_entrypoint(&self, entrypoint: &str) -> Result> { + let mut args: HashMap = HashMap::new(); + args.insert("builder".to_string(), self.handle.to_json()); + args.insert("entrypoint".to_string(), serde_json::to_value(&entrypoint).unwrap_or(Value::Null)); + let result = self.client.invoke_capability("Aspire.Hosting/withEntrypoint", args)?; + let handle: Handle = serde_json::from_value(result)?; + Ok(ContainerResource::new(handle, self.client.clone())) + } + + /// Sets the container image tag + pub fn with_image_tag(&self, tag: &str) -> Result> { + let mut args: HashMap = HashMap::new(); + args.insert("builder".to_string(), self.handle.to_json()); + args.insert("tag".to_string(), serde_json::to_value(&tag).unwrap_or(Value::Null)); + let result = self.client.invoke_capability("Aspire.Hosting/withImageTag", args)?; + let handle: Handle = serde_json::from_value(result)?; + Ok(ContainerResource::new(handle, self.client.clone())) + } + + /// Sets the container image registry + pub fn with_image_registry(&self, registry: &str) -> Result> { + let mut args: HashMap = HashMap::new(); + args.insert("builder".to_string(), self.handle.to_json()); + args.insert("registry".to_string(), serde_json::to_value(®istry).unwrap_or(Value::Null)); + let result = self.client.invoke_capability("Aspire.Hosting/withImageRegistry", args)?; + let handle: Handle = serde_json::from_value(result)?; + Ok(ContainerResource::new(handle, self.client.clone())) + } + + /// Sets the container image + pub fn with_image(&self, image: &str, tag: Option<&str>) -> Result> { + let mut args: HashMap = HashMap::new(); + args.insert("builder".to_string(), self.handle.to_json()); + args.insert("image".to_string(), serde_json::to_value(&image).unwrap_or(Value::Null)); + if let Some(ref v) = tag { + args.insert("tag".to_string(), serde_json::to_value(v).unwrap_or(Value::Null)); + } + let result = self.client.invoke_capability("Aspire.Hosting/withImage", args)?; + let handle: Handle = serde_json::from_value(result)?; + Ok(ContainerResource::new(handle, self.client.clone())) + } + + /// Sets the image SHA256 digest + pub fn with_image_sha256(&self, sha256: &str) -> Result> { + let mut args: HashMap = HashMap::new(); + args.insert("builder".to_string(), self.handle.to_json()); + args.insert("sha256".to_string(), serde_json::to_value(&sha256).unwrap_or(Value::Null)); + let result = self.client.invoke_capability("Aspire.Hosting/withImageSHA256", args)?; + let handle: Handle = serde_json::from_value(result)?; + Ok(ContainerResource::new(handle, self.client.clone())) + } + + /// Adds runtime arguments for the container + pub fn with_container_runtime_args(&self, args: Vec) -> Result> { + let mut args: HashMap = HashMap::new(); + args.insert("builder".to_string(), self.handle.to_json()); + args.insert("args".to_string(), serde_json::to_value(&args).unwrap_or(Value::Null)); + let result = self.client.invoke_capability("Aspire.Hosting/withContainerRuntimeArgs", args)?; + let handle: Handle = serde_json::from_value(result)?; + Ok(ContainerResource::new(handle, self.client.clone())) + } + + /// Sets the lifetime behavior of the container resource + pub fn with_lifetime(&self, lifetime: ContainerLifetime) -> Result> { + let mut args: HashMap = HashMap::new(); + args.insert("builder".to_string(), self.handle.to_json()); + args.insert("lifetime".to_string(), serde_json::to_value(&lifetime).unwrap_or(Value::Null)); + let result = self.client.invoke_capability("Aspire.Hosting/withLifetime", args)?; + let handle: Handle = serde_json::from_value(result)?; + Ok(ContainerResource::new(handle, self.client.clone())) + } + + /// Sets the container image pull policy + pub fn with_image_pull_policy(&self, pull_policy: ImagePullPolicy) -> Result> { + let mut args: HashMap = HashMap::new(); + args.insert("builder".to_string(), self.handle.to_json()); + args.insert("pullPolicy".to_string(), serde_json::to_value(&pull_policy).unwrap_or(Value::Null)); + let result = self.client.invoke_capability("Aspire.Hosting/withImagePullPolicy", args)?; + let handle: Handle = serde_json::from_value(result)?; + Ok(ContainerResource::new(handle, self.client.clone())) + } + + /// Configures the resource to be published as a container + pub fn publish_as_container(&self) -> Result> { + let mut args: HashMap = HashMap::new(); + args.insert("builder".to_string(), self.handle.to_json()); + let result = self.client.invoke_capability("Aspire.Hosting/publishAsContainer", args)?; + let handle: Handle = serde_json::from_value(result)?; + Ok(ContainerResource::new(handle, self.client.clone())) + } + + /// Configures the resource to use a Dockerfile + pub fn with_dockerfile(&self, context_path: &str, dockerfile_path: Option<&str>, stage: Option<&str>) -> Result> { + let mut args: HashMap = HashMap::new(); + args.insert("builder".to_string(), self.handle.to_json()); + args.insert("contextPath".to_string(), serde_json::to_value(&context_path).unwrap_or(Value::Null)); + if let Some(ref v) = dockerfile_path { + args.insert("dockerfilePath".to_string(), serde_json::to_value(v).unwrap_or(Value::Null)); + } + if let Some(ref v) = stage { + args.insert("stage".to_string(), serde_json::to_value(v).unwrap_or(Value::Null)); + } + let result = self.client.invoke_capability("Aspire.Hosting/withDockerfile", args)?; + let handle: Handle = serde_json::from_value(result)?; + Ok(ContainerResource::new(handle, self.client.clone())) + } + + /// Sets the container name + pub fn with_container_name(&self, name: &str) -> Result> { + let mut args: HashMap = HashMap::new(); + args.insert("builder".to_string(), self.handle.to_json()); + args.insert("name".to_string(), serde_json::to_value(&name).unwrap_or(Value::Null)); + let result = self.client.invoke_capability("Aspire.Hosting/withContainerName", args)?; + let handle: Handle = serde_json::from_value(result)?; + Ok(ContainerResource::new(handle, self.client.clone())) + } + + /// Adds a build argument from a parameter resource + pub fn with_build_arg(&self, name: &str, value: &ParameterResource) -> Result> { + let mut args: HashMap = HashMap::new(); + args.insert("builder".to_string(), self.handle.to_json()); + args.insert("name".to_string(), serde_json::to_value(&name).unwrap_or(Value::Null)); + args.insert("value".to_string(), value.handle().to_json()); + let result = self.client.invoke_capability("Aspire.Hosting/withBuildArg", args)?; + let handle: Handle = serde_json::from_value(result)?; + Ok(ContainerResource::new(handle, self.client.clone())) + } + + /// Adds a build secret from a parameter resource + pub fn with_build_secret(&self, name: &str, value: &ParameterResource) -> Result> { + let mut args: HashMap = HashMap::new(); + args.insert("builder".to_string(), self.handle.to_json()); + args.insert("name".to_string(), serde_json::to_value(&name).unwrap_or(Value::Null)); + args.insert("value".to_string(), value.handle().to_json()); + let result = self.client.invoke_capability("Aspire.Hosting/withBuildSecret", args)?; + let handle: Handle = serde_json::from_value(result)?; + Ok(ContainerResource::new(handle, self.client.clone())) + } + + /// Configures endpoint proxy support + pub fn with_endpoint_proxy_support(&self, proxy_enabled: bool) -> Result> { + let mut args: HashMap = HashMap::new(); + args.insert("builder".to_string(), self.handle.to_json()); + args.insert("proxyEnabled".to_string(), serde_json::to_value(&proxy_enabled).unwrap_or(Value::Null)); + let result = self.client.invoke_capability("Aspire.Hosting/withEndpointProxySupport", args)?; + let handle: Handle = serde_json::from_value(result)?; + Ok(ContainerResource::new(handle, self.client.clone())) + } + /// Sets the base image for a Dockerfile build pub fn with_dockerfile_base_image(&self, build_image: Option<&str>, runtime_image: Option<&str>) -> Result> { let mut args: HashMap = HashMap::new(); @@ -2570,6 +2734,16 @@ impl ContainerResource { Ok(IResource::new(handle, self.client.clone())) } + /// Adds a network alias for the container + pub fn with_container_network_alias(&self, alias: &str) -> Result> { + let mut args: HashMap = HashMap::new(); + args.insert("builder".to_string(), self.handle.to_json()); + args.insert("alias".to_string(), serde_json::to_value(&alias).unwrap_or(Value::Null)); + let result = self.client.invoke_capability("Aspire.Hosting/withContainerNetworkAlias", args)?; + let handle: Handle = serde_json::from_value(result)?; + Ok(ContainerResource::new(handle, self.client.clone())) + } + /// Configures an MCP server endpoint on the resource pub fn with_mcp_server(&self, path: Option<&str>, endpoint_name: Option<&str>) -> Result> { let mut args: HashMap = HashMap::new(); @@ -2604,6 +2778,15 @@ impl ContainerResource { Ok(IResourceWithEnvironment::new(handle, self.client.clone())) } + /// Publishes the resource as a connection string + pub fn publish_as_connection_string(&self) -> Result> { + let mut args: HashMap = HashMap::new(); + args.insert("builder".to_string(), self.handle.to_json()); + let result = self.client.invoke_capability("Aspire.Hosting/publishAsConnectionString", args)?; + let handle: Handle = serde_json::from_value(result)?; + Ok(ContainerResource::new(handle, self.client.clone())) + } + /// Adds a required command dependency pub fn with_required_command(&self, command: &str, help_link: Option<&str>) -> Result> { let mut args: HashMap = HashMap::new(); @@ -3272,6 +3455,22 @@ impl ContainerResource { Ok(IResource::new(handle, self.client.clone())) } + /// Adds a volume + pub fn with_volume(&self, target: &str, name: Option<&str>, is_read_only: Option) -> Result> { + let mut args: HashMap = HashMap::new(); + args.insert("resource".to_string(), self.handle.to_json()); + args.insert("target".to_string(), serde_json::to_value(&target).unwrap_or(Value::Null)); + if let Some(ref v) = name { + args.insert("name".to_string(), serde_json::to_value(v).unwrap_or(Value::Null)); + } + if let Some(ref v) = is_read_only { + args.insert("isReadOnly".to_string(), serde_json::to_value(v).unwrap_or(Value::Null)); + } + let result = self.client.invoke_capability("Aspire.Hosting/withVolume", args)?; + let handle: Handle = serde_json::from_value(result)?; + Ok(ContainerResource::new(handle, self.client.clone())) + } + /// Gets the resource name pub fn get_resource_name(&self) -> Result> { let mut args: HashMap = HashMap::new(); @@ -4945,6 +5144,46 @@ impl ExecutableResource { Ok(IResource::new(handle, self.client.clone())) } + /// Publishes the executable as a Docker container + pub fn publish_as_docker_file(&self) -> Result> { + let mut args: HashMap = HashMap::new(); + args.insert("builder".to_string(), self.handle.to_json()); + let result = self.client.invoke_capability("Aspire.Hosting/publishAsDockerFile", args)?; + let handle: Handle = serde_json::from_value(result)?; + Ok(ExecutableResource::new(handle, self.client.clone())) + } + + /// Publishes an executable as a Docker file with optional container configuration + pub fn publish_as_docker_file_with_configure(&self, configure: impl Fn(Vec) -> Value + Send + Sync + 'static) -> Result> { + let mut args: HashMap = HashMap::new(); + args.insert("builder".to_string(), self.handle.to_json()); + let callback_id = register_callback(configure); + args.insert("configure".to_string(), Value::String(callback_id)); + let result = self.client.invoke_capability("Aspire.Hosting/publishAsDockerFileWithConfigure", args)?; + let handle: Handle = serde_json::from_value(result)?; + Ok(ExecutableResource::new(handle, self.client.clone())) + } + + /// Sets the executable command + pub fn with_executable_command(&self, command: &str) -> Result> { + let mut args: HashMap = HashMap::new(); + args.insert("builder".to_string(), self.handle.to_json()); + args.insert("command".to_string(), serde_json::to_value(&command).unwrap_or(Value::Null)); + let result = self.client.invoke_capability("Aspire.Hosting/withExecutableCommand", args)?; + let handle: Handle = serde_json::from_value(result)?; + Ok(ExecutableResource::new(handle, self.client.clone())) + } + + /// Sets the executable working directory + pub fn with_working_directory(&self, working_directory: &str) -> Result> { + let mut args: HashMap = HashMap::new(); + args.insert("builder".to_string(), self.handle.to_json()); + args.insert("workingDirectory".to_string(), serde_json::to_value(&working_directory).unwrap_or(Value::Null)); + let result = self.client.invoke_capability("Aspire.Hosting/withWorkingDirectory", args)?; + let handle: Handle = serde_json::from_value(result)?; + Ok(ExecutableResource::new(handle, self.client.clone())) + } + /// Configures an MCP server endpoint on the resource pub fn with_mcp_server(&self, path: Option<&str>, endpoint_name: Option<&str>) -> Result> { let mut args: HashMap = HashMap::new(); @@ -7832,6 +8071,36 @@ impl ProjectResource { Ok(IResourceWithEnvironment::new(handle, self.client.clone())) } + /// Sets the number of replicas + pub fn with_replicas(&self, replicas: f64) -> Result> { + let mut args: HashMap = HashMap::new(); + args.insert("builder".to_string(), self.handle.to_json()); + args.insert("replicas".to_string(), serde_json::to_value(&replicas).unwrap_or(Value::Null)); + let result = self.client.invoke_capability("Aspire.Hosting/withReplicas", args)?; + let handle: Handle = serde_json::from_value(result)?; + Ok(ProjectResource::new(handle, self.client.clone())) + } + + /// Disables forwarded headers for the project + pub fn disable_forwarded_headers(&self) -> Result> { + let mut args: HashMap = HashMap::new(); + args.insert("builder".to_string(), self.handle.to_json()); + let result = self.client.invoke_capability("Aspire.Hosting/disableForwardedHeaders", args)?; + let handle: Handle = serde_json::from_value(result)?; + Ok(ProjectResource::new(handle, self.client.clone())) + } + + /// Publishes a project as a Docker file with optional container configuration + pub fn publish_as_docker_file(&self, configure: impl Fn(Vec) -> Value + Send + Sync + 'static) -> Result> { + let mut args: HashMap = HashMap::new(); + args.insert("builder".to_string(), self.handle.to_json()); + let callback_id = register_callback(configure); + args.insert("configure".to_string(), Value::String(callback_id)); + let result = self.client.invoke_capability("Aspire.Hosting/publishProjectAsDockerFileWithConfigure", args)?; + let handle: Handle = serde_json::from_value(result)?; + Ok(ProjectResource::new(handle, self.client.clone())) + } + /// Adds a required command dependency pub fn with_required_command(&self, command: &str, help_link: Option<&str>) -> Result> { let mut args: HashMap = HashMap::new(); diff --git a/tests/Aspire.Hosting.CodeGeneration.TypeScript.Tests/Aspire.Hosting.CodeGeneration.TypeScript.Tests.csproj b/tests/Aspire.Hosting.CodeGeneration.TypeScript.Tests/Aspire.Hosting.CodeGeneration.TypeScript.Tests.csproj index 8f8f276a0f7..6193224150a 100644 --- a/tests/Aspire.Hosting.CodeGeneration.TypeScript.Tests/Aspire.Hosting.CodeGeneration.TypeScript.Tests.csproj +++ b/tests/Aspire.Hosting.CodeGeneration.TypeScript.Tests/Aspire.Hosting.CodeGeneration.TypeScript.Tests.csproj @@ -7,6 +7,7 @@ + diff --git a/tests/Aspire.Hosting.CodeGeneration.TypeScript.Tests/AtsTypeScriptCodeGeneratorTests.cs b/tests/Aspire.Hosting.CodeGeneration.TypeScript.Tests/AtsTypeScriptCodeGeneratorTests.cs index 2ab0dab222d..699c8d26459 100644 --- a/tests/Aspire.Hosting.CodeGeneration.TypeScript.Tests/AtsTypeScriptCodeGeneratorTests.cs +++ b/tests/Aspire.Hosting.CodeGeneration.TypeScript.Tests/AtsTypeScriptCodeGeneratorTests.cs @@ -50,6 +50,17 @@ await Verify(files["aspire.ts"], extension: "ts") .UseFileName("AtsGeneratedAspire"); } + [Fact] + public void GenerateDistributedApplication_WithHostingTypes_KeepsReferenceExpressionInBaseTs() + { + var atsContext = CreateContextFromBothAssemblies(); + + var files = _generator.GenerateDistributedApplication(atsContext); + + Assert.DoesNotContain("export class ReferenceExpression {", files["aspire.ts"]); + Assert.Contains("registerHandleWrapper('Aspire.Hosting/Aspire.Hosting.ApplicationModel.ReferenceExpression'", files["base.ts"]); + } + [Fact] public void GenerateDistributedApplication_WithTestTypes_IncludesCapabilities() { @@ -965,6 +976,19 @@ public void Scanner_InstanceMethod_HasCorrectCapabilityKind() Assert.Equal(AtsCapabilityKind.InstanceMethod, getValueAsync.CapabilityKind); } + [Fact] + public void Scanner_ReferenceExpressionGetValueAsync_IsExported() + { + var capabilities = ScanCapabilitiesFromHostingAssembly(); + + var getValueAsync = capabilities.FirstOrDefault(c => + c.CapabilityId == "Aspire.Hosting.ApplicationModel/getValue" && + c.TargetTypeId == AtsConstants.ReferenceExpressionTypeId); + + Assert.NotNull(getValueAsync); + Assert.Equal(AtsCapabilityKind.InstanceMethod, getValueAsync.CapabilityKind); + } + [Fact] public void Scanner_ExtensionMethod_HasCorrectCapabilityKind() { @@ -1319,4 +1343,63 @@ private static int CountOccurrences(string text, string pattern) } return count; } + + // ===== JavaScript Assembly Expansion Tests ===== + + [Fact] + public void Scanner_WithNpm_ExpandsToAllJavaScriptResourceTypes() + { + // Verify that withNpm (constrained to JavaScriptAppResource) expands to all three + // concrete JS resource types: JavaScriptAppResource, NodeAppResource, ViteAppResource. + // This is a regression test for capability ID expansion where concrete types + // were not registered under their own type ID in the compatibility map. + var hostingAssembly = typeof(DistributedApplication).Assembly; + var jsAssembly = typeof(Aspire.Hosting.JavaScript.JavaScriptAppResource).Assembly; + + var result = AtsCapabilityScanner.ScanAssemblies([hostingAssembly, jsAssembly]); + + var withNpm = result.Capabilities + .FirstOrDefault(c => c.CapabilityId == "Aspire.Hosting.JavaScript/withNpm"); + Assert.NotNull(withNpm); + + var expandedTypeIds = withNpm.ExpandedTargetTypes.Select(t => t.TypeId).ToList(); + + // All three JS resource types should be present + var javaScriptAppTypeId = AtsTypeMapping.DeriveTypeId(typeof(Aspire.Hosting.JavaScript.JavaScriptAppResource)); + var nodeAppTypeId = AtsTypeMapping.DeriveTypeId(typeof(Aspire.Hosting.JavaScript.NodeAppResource)); + var viteAppTypeId = AtsTypeMapping.DeriveTypeId(typeof(Aspire.Hosting.JavaScript.ViteAppResource)); + + Assert.Contains(javaScriptAppTypeId, expandedTypeIds); + Assert.Contains(nodeAppTypeId, expandedTypeIds); + Assert.Contains(viteAppTypeId, expandedTypeIds); + } + + [Theory] + [InlineData("withNpm")] + [InlineData("withBun")] + [InlineData("withYarn")] + [InlineData("withPnpm")] + public void Scanner_PackageManagerMethods_ExpandToAllJavaScriptResourceTypes(string methodName) + { + // Verify all package manager methods expand to the known JS resource types. + // Assert the minimum expected set rather than an exact count so the test + // remains valid when new JavaScriptAppResource-derived types are added. + var hostingAssembly = typeof(DistributedApplication).Assembly; + var jsAssembly = typeof(Aspire.Hosting.JavaScript.JavaScriptAppResource).Assembly; + + var result = AtsCapabilityScanner.ScanAssemblies([hostingAssembly, jsAssembly]); + + var capability = result.Capabilities + .FirstOrDefault(c => c.CapabilityId == $"Aspire.Hosting.JavaScript/{methodName}"); + Assert.NotNull(capability); + + var expandedTypeIds = capability.ExpandedTargetTypes.Select(t => t.TypeId).ToList(); + Assert.True(expandedTypeIds.Count >= 3, $"Expected at least 3 expanded types but found {expandedTypeIds.Count}"); + Assert.Contains(expandedTypeIds, + id => id.Contains(nameof(JavaScript.JavaScriptAppResource), StringComparison.Ordinal) + && !id.Contains("NodeApp", StringComparison.Ordinal) + && !id.Contains("ViteApp", StringComparison.Ordinal)); + Assert.Contains(expandedTypeIds, id => id.Contains(nameof(JavaScript.NodeAppResource), StringComparison.Ordinal)); + Assert.Contains(expandedTypeIds, id => id.Contains(nameof(JavaScript.ViteAppResource), StringComparison.Ordinal)); + } } diff --git a/tests/Aspire.Hosting.CodeGeneration.TypeScript.Tests/Snapshots/TwoPassScanningGeneratedAspire.verified.ts b/tests/Aspire.Hosting.CodeGeneration.TypeScript.Tests/Snapshots/TwoPassScanningGeneratedAspire.verified.ts index c563cdcd06a..7370a025c12 100644 --- a/tests/Aspire.Hosting.CodeGeneration.TypeScript.Tests/Snapshots/TwoPassScanningGeneratedAspire.verified.ts +++ b/tests/Aspire.Hosting.CodeGeneration.TypeScript.Tests/Snapshots/TwoPassScanningGeneratedAspire.verified.ts @@ -4024,6 +4024,239 @@ export class ContainerResource extends ResourceBuilderBase { + const rpcArgs: Record = { builder: this._handle, source, target }; + if (isReadOnly !== undefined) rpcArgs.isReadOnly = isReadOnly; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withBindMount', + rpcArgs + ); + return new ContainerResource(result, this._client); + } + + /** Adds a bind mount */ + withBindMount(source: string, target: string, options?: WithBindMountOptions): ContainerResourcePromise { + const isReadOnly = options?.isReadOnly; + return new ContainerResourcePromise(this._withBindMountInternal(source, target, isReadOnly)); + } + + /** @internal */ + private async _withEntrypointInternal(entrypoint: string): Promise { + const rpcArgs: Record = { builder: this._handle, entrypoint }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withEntrypoint', + rpcArgs + ); + return new ContainerResource(result, this._client); + } + + /** Sets the container entrypoint */ + withEntrypoint(entrypoint: string): ContainerResourcePromise { + return new ContainerResourcePromise(this._withEntrypointInternal(entrypoint)); + } + + /** @internal */ + private async _withImageTagInternal(tag: string): Promise { + const rpcArgs: Record = { builder: this._handle, tag }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withImageTag', + rpcArgs + ); + return new ContainerResource(result, this._client); + } + + /** Sets the container image tag */ + withImageTag(tag: string): ContainerResourcePromise { + return new ContainerResourcePromise(this._withImageTagInternal(tag)); + } + + /** @internal */ + private async _withImageRegistryInternal(registry: string): Promise { + const rpcArgs: Record = { builder: this._handle, registry }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withImageRegistry', + rpcArgs + ); + return new ContainerResource(result, this._client); + } + + /** Sets the container image registry */ + withImageRegistry(registry: string): ContainerResourcePromise { + return new ContainerResourcePromise(this._withImageRegistryInternal(registry)); + } + + /** @internal */ + private async _withImageInternal(image: string, tag?: string): Promise { + const rpcArgs: Record = { builder: this._handle, image }; + if (tag !== undefined) rpcArgs.tag = tag; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withImage', + rpcArgs + ); + return new ContainerResource(result, this._client); + } + + /** Sets the container image */ + withImage(image: string, options?: WithImageOptions): ContainerResourcePromise { + const tag = options?.tag; + return new ContainerResourcePromise(this._withImageInternal(image, tag)); + } + + /** @internal */ + private async _withImageSHA256Internal(sha256: string): Promise { + const rpcArgs: Record = { builder: this._handle, sha256 }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withImageSHA256', + rpcArgs + ); + return new ContainerResource(result, this._client); + } + + /** Sets the image SHA256 digest */ + withImageSHA256(sha256: string): ContainerResourcePromise { + return new ContainerResourcePromise(this._withImageSHA256Internal(sha256)); + } + + /** @internal */ + private async _withContainerRuntimeArgsInternal(args: string[]): Promise { + const rpcArgs: Record = { builder: this._handle, args }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withContainerRuntimeArgs', + rpcArgs + ); + return new ContainerResource(result, this._client); + } + + /** Adds runtime arguments for the container */ + withContainerRuntimeArgs(args: string[]): ContainerResourcePromise { + return new ContainerResourcePromise(this._withContainerRuntimeArgsInternal(args)); + } + + /** @internal */ + private async _withLifetimeInternal(lifetime: ContainerLifetime): Promise { + const rpcArgs: Record = { builder: this._handle, lifetime }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withLifetime', + rpcArgs + ); + return new ContainerResource(result, this._client); + } + + /** Sets the lifetime behavior of the container resource */ + withLifetime(lifetime: ContainerLifetime): ContainerResourcePromise { + return new ContainerResourcePromise(this._withLifetimeInternal(lifetime)); + } + + /** @internal */ + private async _withImagePullPolicyInternal(pullPolicy: ImagePullPolicy): Promise { + const rpcArgs: Record = { builder: this._handle, pullPolicy }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withImagePullPolicy', + rpcArgs + ); + return new ContainerResource(result, this._client); + } + + /** Sets the container image pull policy */ + withImagePullPolicy(pullPolicy: ImagePullPolicy): ContainerResourcePromise { + return new ContainerResourcePromise(this._withImagePullPolicyInternal(pullPolicy)); + } + + /** @internal */ + private async _publishAsContainerInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/publishAsContainer', + rpcArgs + ); + return new ContainerResource(result, this._client); + } + + /** Configures the resource to be published as a container */ + publishAsContainer(): ContainerResourcePromise { + return new ContainerResourcePromise(this._publishAsContainerInternal()); + } + + /** @internal */ + private async _withDockerfileInternal(contextPath: string, dockerfilePath?: string, stage?: string): Promise { + const rpcArgs: Record = { builder: this._handle, contextPath }; + if (dockerfilePath !== undefined) rpcArgs.dockerfilePath = dockerfilePath; + if (stage !== undefined) rpcArgs.stage = stage; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withDockerfile', + rpcArgs + ); + return new ContainerResource(result, this._client); + } + + /** Configures the resource to use a Dockerfile */ + withDockerfile(contextPath: string, options?: WithDockerfileOptions): ContainerResourcePromise { + const dockerfilePath = options?.dockerfilePath; + const stage = options?.stage; + return new ContainerResourcePromise(this._withDockerfileInternal(contextPath, dockerfilePath, stage)); + } + + /** @internal */ + private async _withContainerNameInternal(name: string): Promise { + const rpcArgs: Record = { builder: this._handle, name }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withContainerName', + rpcArgs + ); + return new ContainerResource(result, this._client); + } + + /** Sets the container name */ + withContainerName(name: string): ContainerResourcePromise { + return new ContainerResourcePromise(this._withContainerNameInternal(name)); + } + + /** @internal */ + private async _withBuildArgInternal(name: string, value: ParameterResource): Promise { + const rpcArgs: Record = { builder: this._handle, name, value }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withBuildArg', + rpcArgs + ); + return new ContainerResource(result, this._client); + } + + /** Adds a build argument from a parameter resource */ + withBuildArg(name: string, value: ParameterResource): ContainerResourcePromise { + return new ContainerResourcePromise(this._withBuildArgInternal(name, value)); + } + + /** @internal */ + private async _withBuildSecretInternal(name: string, value: ParameterResource): Promise { + const rpcArgs: Record = { builder: this._handle, name, value }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withBuildSecret', + rpcArgs + ); + return new ContainerResource(result, this._client); + } + + /** Adds a build secret from a parameter resource */ + withBuildSecret(name: string, value: ParameterResource): ContainerResourcePromise { + return new ContainerResourcePromise(this._withBuildSecretInternal(name, value)); + } + + /** @internal */ + private async _withEndpointProxySupportInternal(proxyEnabled: boolean): Promise { + const rpcArgs: Record = { builder: this._handle, proxyEnabled }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withEndpointProxySupport', + rpcArgs + ); + return new ContainerResource(result, this._client); + } + + /** Configures endpoint proxy support */ + withEndpointProxySupport(proxyEnabled: boolean): ContainerResourcePromise { + return new ContainerResourcePromise(this._withEndpointProxySupportInternal(proxyEnabled)); + } + /** @internal */ private async _withDockerfileBaseImageInternal(buildImage?: string, runtimeImage?: string): Promise { const rpcArgs: Record = { builder: this._handle }; @@ -4043,6 +4276,21 @@ export class ContainerResource extends ResourceBuilderBase { + const rpcArgs: Record = { builder: this._handle, alias }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withContainerNetworkAlias', + rpcArgs + ); + return new ContainerResource(result, this._client); + } + + /** Adds a network alias for the container */ + withContainerNetworkAlias(alias: string): ContainerResourcePromise { + return new ContainerResourcePromise(this._withContainerNetworkAliasInternal(alias)); + } + /** @internal */ private async _withMcpServerInternal(path?: string, endpointName?: string): Promise { const rpcArgs: Record = { builder: this._handle }; @@ -4092,6 +4340,21 @@ export class ContainerResource extends ResourceBuilderBase { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/publishAsConnectionString', + rpcArgs + ); + return new ContainerResource(result, this._client); + } + + /** Publishes the resource as a connection string */ + publishAsConnectionString(): ContainerResourcePromise { + return new ContainerResourcePromise(this._publishAsConnectionStringInternal()); + } + /** @internal */ private async _withRequiredCommandInternal(command: string, helpLink?: string): Promise { const rpcArgs: Record = { builder: this._handle, command }; @@ -5022,6 +5285,25 @@ export class ContainerResource extends ResourceBuilderBase { + const rpcArgs: Record = { resource: this._handle, target }; + if (name !== undefined) rpcArgs.name = name; + if (isReadOnly !== undefined) rpcArgs.isReadOnly = isReadOnly; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withVolume', + rpcArgs + ); + return new ContainerResource(result, this._client); + } + + /** Adds a volume */ + withVolume(target: string, options?: WithVolumeOptions): ContainerResourcePromise { + const name = options?.name; + const isReadOnly = options?.isReadOnly; + return new ContainerResourcePromise(this._withVolumeInternal(target, name, isReadOnly)); + } + /** Gets the resource name */ async getResourceName(): Promise { const rpcArgs: Record = { resource: this._handle }; @@ -5303,11 +5585,91 @@ export class ContainerResourcePromise implements PromiseLike return new ContainerResourcePromise(this._promise.then(obj => obj.withContainerRegistry(registry))); } + /** Adds a bind mount */ + withBindMount(source: string, target: string, options?: WithBindMountOptions): ContainerResourcePromise { + return new ContainerResourcePromise(this._promise.then(obj => obj.withBindMount(source, target, options))); + } + + /** Sets the container entrypoint */ + withEntrypoint(entrypoint: string): ContainerResourcePromise { + return new ContainerResourcePromise(this._promise.then(obj => obj.withEntrypoint(entrypoint))); + } + + /** Sets the container image tag */ + withImageTag(tag: string): ContainerResourcePromise { + return new ContainerResourcePromise(this._promise.then(obj => obj.withImageTag(tag))); + } + + /** Sets the container image registry */ + withImageRegistry(registry: string): ContainerResourcePromise { + return new ContainerResourcePromise(this._promise.then(obj => obj.withImageRegistry(registry))); + } + + /** Sets the container image */ + withImage(image: string, options?: WithImageOptions): ContainerResourcePromise { + return new ContainerResourcePromise(this._promise.then(obj => obj.withImage(image, options))); + } + + /** Sets the image SHA256 digest */ + withImageSHA256(sha256: string): ContainerResourcePromise { + return new ContainerResourcePromise(this._promise.then(obj => obj.withImageSHA256(sha256))); + } + + /** Adds runtime arguments for the container */ + withContainerRuntimeArgs(args: string[]): ContainerResourcePromise { + return new ContainerResourcePromise(this._promise.then(obj => obj.withContainerRuntimeArgs(args))); + } + + /** Sets the lifetime behavior of the container resource */ + withLifetime(lifetime: ContainerLifetime): ContainerResourcePromise { + return new ContainerResourcePromise(this._promise.then(obj => obj.withLifetime(lifetime))); + } + + /** Sets the container image pull policy */ + withImagePullPolicy(pullPolicy: ImagePullPolicy): ContainerResourcePromise { + return new ContainerResourcePromise(this._promise.then(obj => obj.withImagePullPolicy(pullPolicy))); + } + + /** Configures the resource to be published as a container */ + publishAsContainer(): ContainerResourcePromise { + return new ContainerResourcePromise(this._promise.then(obj => obj.publishAsContainer())); + } + + /** Configures the resource to use a Dockerfile */ + withDockerfile(contextPath: string, options?: WithDockerfileOptions): ContainerResourcePromise { + return new ContainerResourcePromise(this._promise.then(obj => obj.withDockerfile(contextPath, options))); + } + + /** Sets the container name */ + withContainerName(name: string): ContainerResourcePromise { + return new ContainerResourcePromise(this._promise.then(obj => obj.withContainerName(name))); + } + + /** Adds a build argument from a parameter resource */ + withBuildArg(name: string, value: ParameterResource): ContainerResourcePromise { + return new ContainerResourcePromise(this._promise.then(obj => obj.withBuildArg(name, value))); + } + + /** Adds a build secret from a parameter resource */ + withBuildSecret(name: string, value: ParameterResource): ContainerResourcePromise { + return new ContainerResourcePromise(this._promise.then(obj => obj.withBuildSecret(name, value))); + } + + /** Configures endpoint proxy support */ + withEndpointProxySupport(proxyEnabled: boolean): ContainerResourcePromise { + return new ContainerResourcePromise(this._promise.then(obj => obj.withEndpointProxySupport(proxyEnabled))); + } + /** Sets the base image for a Dockerfile build */ withDockerfileBaseImage(options?: WithDockerfileBaseImageOptions): ContainerResourcePromise { return new ContainerResourcePromise(this._promise.then(obj => obj.withDockerfileBaseImage(options))); } + /** Adds a network alias for the container */ + withContainerNetworkAlias(alias: string): ContainerResourcePromise { + return new ContainerResourcePromise(this._promise.then(obj => obj.withContainerNetworkAlias(alias))); + } + /** Configures an MCP server endpoint on the resource */ withMcpServer(options?: WithMcpServerOptions): ContainerResourcePromise { return new ContainerResourcePromise(this._promise.then(obj => obj.withMcpServer(options))); @@ -5323,6 +5685,11 @@ export class ContainerResourcePromise implements PromiseLike return new ContainerResourcePromise(this._promise.then(obj => obj.withOtlpExporterProtocol(protocol))); } + /** Publishes the resource as a connection string */ + publishAsConnectionString(): ContainerResourcePromise { + return new ContainerResourcePromise(this._promise.then(obj => obj.publishAsConnectionString())); + } + /** Adds a required command dependency */ withRequiredCommand(command: string, options?: WithRequiredCommandOptions): ContainerResourcePromise { return new ContainerResourcePromise(this._promise.then(obj => obj.withRequiredCommand(command, options))); @@ -5588,6 +5955,11 @@ export class ContainerResourcePromise implements PromiseLike return new ContainerResourcePromise(this._promise.then(obj => obj.withPipelineConfiguration(callback))); } + /** Adds a volume */ + withVolume(target: string, options?: WithVolumeOptions): ContainerResourcePromise { + return new ContainerResourcePromise(this._promise.then(obj => obj.withVolume(target, options))); + } + /** Gets the resource name */ getResourceName(): Promise { return this._promise.then(obj => obj.getResourceName()); @@ -9345,6 +9717,71 @@ export class ExecutableResource extends ResourceBuilderBase { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/publishAsDockerFile', + rpcArgs + ); + return new ExecutableResource(result, this._client); + } + + /** Publishes the executable as a Docker container */ + publishAsDockerFile(): ExecutableResourcePromise { + return new ExecutableResourcePromise(this._publishAsDockerFileInternal()); + } + + /** @internal */ + private async _publishAsDockerFileWithConfigureInternal(configure: (obj: ContainerResource) => Promise): Promise { + const configureId = registerCallback(async (objData: unknown) => { + const objHandle = wrapIfHandle(objData) as ContainerResourceHandle; + const obj = new ContainerResource(objHandle, this._client); + await configure(obj); + }); + const rpcArgs: Record = { builder: this._handle, configure: configureId }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/publishAsDockerFileWithConfigure', + rpcArgs + ); + return new ExecutableResource(result, this._client); + } + + /** Publishes an executable as a Docker file with optional container configuration */ + publishAsDockerFileWithConfigure(configure: (obj: ContainerResource) => Promise): ExecutableResourcePromise { + return new ExecutableResourcePromise(this._publishAsDockerFileWithConfigureInternal(configure)); + } + + /** @internal */ + private async _withExecutableCommandInternal(command: string): Promise { + const rpcArgs: Record = { builder: this._handle, command }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withExecutableCommand', + rpcArgs + ); + return new ExecutableResource(result, this._client); + } + + /** Sets the executable command */ + withExecutableCommand(command: string): ExecutableResourcePromise { + return new ExecutableResourcePromise(this._withExecutableCommandInternal(command)); + } + + /** @internal */ + private async _withWorkingDirectoryInternal(workingDirectory: string): Promise { + const rpcArgs: Record = { builder: this._handle, workingDirectory }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withWorkingDirectory', + rpcArgs + ); + return new ExecutableResource(result, this._client); + } + + /** Sets the executable working directory */ + withWorkingDirectory(workingDirectory: string): ExecutableResourcePromise { + return new ExecutableResourcePromise(this._withWorkingDirectoryInternal(workingDirectory)); + } + /** @internal */ private async _withMcpServerInternal(path?: string, endpointName?: string): Promise { const rpcArgs: Record = { builder: this._handle }; @@ -10610,6 +11047,26 @@ export class ExecutableResourcePromise implements PromiseLike obj.withDockerfileBaseImage(options))); } + /** Publishes the executable as a Docker container */ + publishAsDockerFile(): ExecutableResourcePromise { + return new ExecutableResourcePromise(this._promise.then(obj => obj.publishAsDockerFile())); + } + + /** Publishes an executable as a Docker file with optional container configuration */ + publishAsDockerFileWithConfigure(configure: (obj: ContainerResource) => Promise): ExecutableResourcePromise { + return new ExecutableResourcePromise(this._promise.then(obj => obj.publishAsDockerFileWithConfigure(configure))); + } + + /** Sets the executable command */ + withExecutableCommand(command: string): ExecutableResourcePromise { + return new ExecutableResourcePromise(this._promise.then(obj => obj.withExecutableCommand(command))); + } + + /** Sets the executable working directory */ + withWorkingDirectory(workingDirectory: string): ExecutableResourcePromise { + return new ExecutableResourcePromise(this._promise.then(obj => obj.withWorkingDirectory(workingDirectory))); + } + /** Configures an MCP server endpoint on the resource */ withMcpServer(options?: WithMcpServerOptions): ExecutableResourcePromise { return new ExecutableResourcePromise(this._promise.then(obj => obj.withMcpServer(options))); @@ -12626,6 +13083,58 @@ export class ProjectResource extends ResourceBuilderBase return new ProjectResourcePromise(this._withOtlpExporterProtocolInternal(protocol)); } + /** @internal */ + private async _withReplicasInternal(replicas: number): Promise { + const rpcArgs: Record = { builder: this._handle, replicas }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/withReplicas', + rpcArgs + ); + return new ProjectResource(result, this._client); + } + + /** Sets the number of replicas */ + withReplicas(replicas: number): ProjectResourcePromise { + return new ProjectResourcePromise(this._withReplicasInternal(replicas)); + } + + /** @internal */ + private async _disableForwardedHeadersInternal(): Promise { + const rpcArgs: Record = { builder: this._handle }; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/disableForwardedHeaders', + rpcArgs + ); + return new ProjectResource(result, this._client); + } + + /** Disables forwarded headers for the project */ + disableForwardedHeaders(): ProjectResourcePromise { + return new ProjectResourcePromise(this._disableForwardedHeadersInternal()); + } + + /** @internal */ + private async _publishAsDockerFileInternal(configure?: (obj: ContainerResource) => Promise): Promise { + const configureId = configure ? registerCallback(async (objData: unknown) => { + const objHandle = wrapIfHandle(objData) as ContainerResourceHandle; + const obj = new ContainerResource(objHandle, this._client); + await configure(obj); + }) : undefined; + const rpcArgs: Record = { builder: this._handle }; + if (configure !== undefined) rpcArgs.configure = configureId; + const result = await this._client.invokeCapability( + 'Aspire.Hosting/publishProjectAsDockerFileWithConfigure', + rpcArgs + ); + return new ProjectResource(result, this._client); + } + + /** Publishes a project as a Docker file with optional container configuration */ + publishAsDockerFile(options?: PublishAsDockerFileOptions): ProjectResourcePromise { + const configure = options?.configure; + return new ProjectResourcePromise(this._publishAsDockerFileInternal(configure)); + } + /** @internal */ private async _withRequiredCommandInternal(command: string, helpLink?: string): Promise { const rpcArgs: Record = { builder: this._handle, command }; @@ -13872,6 +14381,21 @@ export class ProjectResourcePromise implements PromiseLike { return new ProjectResourcePromise(this._promise.then(obj => obj.withOtlpExporterProtocol(protocol))); } + /** Sets the number of replicas */ + withReplicas(replicas: number): ProjectResourcePromise { + return new ProjectResourcePromise(this._promise.then(obj => obj.withReplicas(replicas))); + } + + /** Disables forwarded headers for the project */ + disableForwardedHeaders(): ProjectResourcePromise { + return new ProjectResourcePromise(this._promise.then(obj => obj.disableForwardedHeaders())); + } + + /** Publishes a project as a Docker file with optional container configuration */ + publishAsDockerFile(options?: PublishAsDockerFileOptions): ProjectResourcePromise { + return new ProjectResourcePromise(this._promise.then(obj => obj.publishAsDockerFile(options))); + } + /** Adds a required command dependency */ withRequiredCommand(command: string, options?: WithRequiredCommandOptions): ProjectResourcePromise { return new ProjectResourcePromise(this._promise.then(obj => obj.withRequiredCommand(command, options))); diff --git a/tests/Aspire.Hosting.RemoteHost.Tests/CapabilityDispatcherTests.cs b/tests/Aspire.Hosting.RemoteHost.Tests/CapabilityDispatcherTests.cs index e096b6706aa..5f98d18e16a 100644 --- a/tests/Aspire.Hosting.RemoteHost.Tests/CapabilityDispatcherTests.cs +++ b/tests/Aspire.Hosting.RemoteHost.Tests/CapabilityDispatcherTests.cs @@ -543,6 +543,38 @@ public void Invoke_AsyncInstanceMethod() Assert.Equal("TEST", result.GetValue()); } + [Fact] + public void Invoke_ValueTaskInstanceMethod() + { + var handles = new HandleRegistry(); + var dispatcher = new CapabilityDispatcher(handles, CreateTestMarshaller(handles), [typeof(TestTypeWithMethods).Assembly]); + + var context = new TestTypeWithMethods(); + var handleId = handles.Register(context, "Aspire.Hosting.RemoteHost.Tests/Aspire.Hosting.RemoteHost.Tests.TestTypeWithMethods"); + var args = new JsonObject + { + ["context"] = new JsonObject { ["$handle"] = handleId }, + ["input"] = "value-task" + }; + + var result = dispatcher.Invoke("Aspire.Hosting.RemoteHost.Tests/TestTypeWithMethods.processValueTaskAsync", args); + + Assert.NotNull(result); + Assert.Equal("VALUE-TASK", result.GetValue()); + } + + [Fact] + public void Invoke_StaticValueTaskMethod() + { + var dispatcher = CreateDispatcher(typeof(TestCapabilities).Assembly); + var args = new JsonObject { ["value"] = "value-task" }; + + var result = dispatcher.Invoke("Aspire.Hosting.RemoteHost.Tests/asyncValueTaskWithResult", args); + + Assert.NotNull(result); + Assert.Equal("VALUE-TASK", result.GetValue()); + } + [Fact] public void Constructor_SkipsNonPublicMethods() { @@ -678,6 +710,31 @@ public void Invoke_SyncCapabilityWithBackgroundThreadOptIn_RunsOnBackgroundThrea Assert.NotEqual(callerThreadId, result.GetValue()); } + [Fact] + public void Invoke_ValueTaskCapabilityWithBackgroundThreadOptIn_RunsInline() + { + var dispatcher = CreateDispatcher(typeof(TestCapabilitiesWithBackgroundThreadDispatch).Assembly); + var callerThreadId = Environment.CurrentManagedThreadId; + + var result = dispatcher.Invoke("Aspire.Hosting.RemoteHost.Tests/valueTaskBackgroundThreadProbe", null); + + Assert.NotNull(result); + Assert.Equal(callerThreadId, result.GetValue()); + } + + [Fact] + public void Invoke_NonGenericValueTaskCapabilityWithBackgroundThreadOptIn_RunsInline() + { + var dispatcher = CreateDispatcher(typeof(TestCapabilitiesWithBackgroundThreadDispatch).Assembly); + var callerThreadId = Environment.CurrentManagedThreadId; + + TestCapabilitiesWithBackgroundThreadDispatch.ResetLastObservedThreadId(); + + dispatcher.Invoke("Aspire.Hosting.RemoteHost.Tests/nonGenericValueTaskBackgroundThreadProbe", null); + + Assert.Equal(callerThreadId, TestCapabilitiesWithBackgroundThreadDispatch.LastObservedThreadId); + } + [Fact] public void Invoke_MethodWithoutCallbackFactory_ThrowsForCallbackParameter() { @@ -1398,6 +1455,13 @@ public static async Task AsyncWithResult(string value) return value.ToUpperInvariant(); } + [AspireExport("asyncValueTaskWithResult", Description = "Async method returning ValueTask")] + public static async ValueTask AsyncValueTaskWithResult(string value) + { + await Task.Delay(1); + return value.ToUpperInvariant(); + } + [AspireExport("asyncThrows", Description = "Async method that throws")] public static async Task AsyncThrows(string value) { @@ -1485,6 +1549,12 @@ public async Task ProcessAsync(string input) return input.ToUpperInvariant(); } + public async ValueTask ProcessValueTaskAsync(string input) + { + await Task.Delay(1); + return input.ToUpperInvariant(); + } + // This should NOT be exposed - private method #pragma warning disable IDE0051 // Remove unused private member - testing that private methods are not exposed private void PrivateMethod() @@ -1540,6 +1610,13 @@ public static int WithAsyncCallback(Func> callback) internal static class TestCapabilitiesWithBackgroundThreadDispatch { + public static int LastObservedThreadId { get; private set; } + + public static void ResetLastObservedThreadId() + { + LastObservedThreadId = 0; + } + [AspireExport("syncInlineThreadProbe", Description = "Captures the current thread for inline sync invocation")] public static int SyncInlineThreadProbe() { @@ -1551,6 +1628,19 @@ public static int SyncBackgroundThreadProbe() { return Environment.CurrentManagedThreadId; } + + [AspireExport("valueTaskBackgroundThreadProbe", Description = "Captures the current thread for ValueTask invocation", RunSyncOnBackgroundThread = true)] + public static ValueTask ValueTaskBackgroundThreadProbe() + { + return ValueTask.FromResult(Environment.CurrentManagedThreadId); + } + + [AspireExport("nonGenericValueTaskBackgroundThreadProbe", Description = "Captures the current thread for ValueTask invocation", RunSyncOnBackgroundThread = true)] + public static ValueTask NonGenericValueTaskBackgroundThreadProbe() + { + LastObservedThreadId = Environment.CurrentManagedThreadId; + return ValueTask.CompletedTask; + } } /// diff --git a/tests/Aspire.Hosting.Tests/Aspire.Hosting.Tests.csproj b/tests/Aspire.Hosting.Tests/Aspire.Hosting.Tests.csproj index a58c98f730f..9794b3cd827 100644 --- a/tests/Aspire.Hosting.Tests/Aspire.Hosting.Tests.csproj +++ b/tests/Aspire.Hosting.Tests/Aspire.Hosting.Tests.csproj @@ -38,6 +38,7 @@ + diff --git a/tests/Aspire.Hosting.Tests/Dashboard/DashboardResourceTests.cs b/tests/Aspire.Hosting.Tests/Dashboard/DashboardResourceTests.cs index 98af383ae6e..1b4c919007c 100644 --- a/tests/Aspire.Hosting.Tests/Dashboard/DashboardResourceTests.cs +++ b/tests/Aspire.Hosting.Tests/Dashboard/DashboardResourceTests.cs @@ -119,6 +119,11 @@ public async Task DashboardDoesNotAddResource_ConfiguresExistingDashboard(string .ToList(); Assert.Collection(config, + e => + { + Assert.Equal(KnownConfigNames.DashboardApiEnabled, e.Key); + Assert.Equal("true", e.Value); + }, e => { Assert.Equal(KnownConfigNames.DashboardMcpEndpointUrl, e.Key); diff --git a/tests/Aspire.Hosting.Tests/Dcp/DcpExecutorTests.cs b/tests/Aspire.Hosting.Tests/Dcp/DcpExecutorTests.cs index 009866ef293..40b0ec36703 100644 --- a/tests/Aspire.Hosting.Tests/Dcp/DcpExecutorTests.cs +++ b/tests/Aspire.Hosting.Tests/Dcp/DcpExecutorTests.cs @@ -1421,6 +1421,39 @@ public async Task ProjectLaunchConfiguration_Populated_WhenLaunchProfileSpecifie Assert.Equal("http", plc.LaunchProfile); } + [Theory] + [InlineData("Debug", ExecutableLaunchMode.Debug)] + [InlineData("NoDebug", ExecutableLaunchMode.NoDebug)] + public async Task ProjectLaunchConfiguration_RespectsDebugSessionRunMode(string runMode, string expectedMode) + { + var builder = DistributedApplication.CreateBuilder(); + builder.AddProject("proj", launchProfileName: "http"); + + using var app = builder.Build(); + var model = app.Services.GetRequiredService(); + + var kubernetes = new TestKubernetesService(); + var configBuilder = new ConfigurationBuilder(); + configBuilder.AddInMemoryCollection(new Dictionary + { + [KnownConfigNames.DashboardOtlpGrpcEndpointUrl] = "http://localhost", + ["AppHost:BrowserToken"] = "token", + ["AppHost:OtlpApiKey"] = "otlp-key", + [DcpExecutor.DebugSessionPortVar] = "12345", + [KnownConfigNames.DebugSessionRunMode] = runMode + }); + var configuration = configBuilder.Build(); + + var executor = CreateAppExecutor(model, configuration: configuration, kubernetesService: kubernetes); + + await executor.RunApplicationAsync(); + + var exe = Assert.Single(kubernetes.CreatedResources.OfType()); + Assert.True(exe.TryGetProjectLaunchConfiguration(out var plc)); + Assert.NotNull(plc); + Assert.Equal(expectedMode, plc!.Mode); + } + [Fact] public async Task ProjectLaunchConfiguration_Disabled_WhenLaunchProfileExcluded_InDebugSession() { diff --git a/tests/Aspire.Hosting.Tests/ExecutionConfigurationGathererTests.cs b/tests/Aspire.Hosting.Tests/ExecutionConfigurationGathererTests.cs index de699dc664d..8f03fe8f1f4 100644 --- a/tests/Aspire.Hosting.Tests/ExecutionConfigurationGathererTests.cs +++ b/tests/Aspire.Hosting.Tests/ExecutionConfigurationGathererTests.cs @@ -4,7 +4,9 @@ #pragma warning disable ASPIRECERTIFICATES001 using System.Collections.Immutable; +using System.Formats.Asn1; using System.Security.Cryptography; +using System.Security.Cryptography.Pkcs; using System.Security.Cryptography.X509Certificates; using Aspire.Hosting.Utils; using Microsoft.Extensions.DependencyInjection; @@ -364,6 +366,236 @@ public async Task CertificateTrustExecutionConfigurationGatherer_WithAppendScope #endregion + #region CreateCustomBundle Tests + + [Fact] + public async Task CreateCustomBundle_RegistersBundleFactory() + { + using var builder = TestDistributedApplicationBuilder.Create(); + var cert = CreateTestCertificate(); + var caCollection = builder.AddCertificateAuthorityCollection("test-ca").WithCertificate(cert); + + var resource = builder.AddContainer("test", "image") + .WithCertificateAuthorityCollection(caCollection) + .WithCertificateTrustConfiguration(ctx => + { + var bundlePath = ctx.CreateCustomBundle((certs, ct) => + Task.FromResult(new byte[] { 1, 2, 3 })); + ctx.EnvironmentVariables["CUSTOM_BUNDLE"] = bundlePath; + return Task.CompletedTask; + }) + .Resource; + + await builder.BuildAsync(); + + var configContextFactory = CreateCertificateTrustConfigurationContextFactory(); + var context = new ExecutionConfigurationGathererContext(); + var gatherer = new CertificateTrustExecutionConfigurationGatherer(configContextFactory); + + await gatherer.GatherAsync(context, resource, NullLogger.Instance, builder.ExecutionContext); + + var metadata = context.AdditionalConfigurationData.OfType().Single(); + Assert.Single(metadata.CustomBundlesFactories); + } + + [Fact] + public async Task CreateCustomBundle_ReturnsReferenceExpressionWithBundlePath() + { + using var builder = TestDistributedApplicationBuilder.Create(); + var cert = CreateTestCertificate(); + var caCollection = builder.AddCertificateAuthorityCollection("test-ca").WithCertificate(cert); + + ReferenceExpression? capturedBundlePath = null; + var resource = builder.AddContainer("test", "image") + .WithCertificateAuthorityCollection(caCollection) + .WithCertificateTrustConfiguration(ctx => + { + capturedBundlePath = ctx.CreateCustomBundle((certs, ct) => + Task.FromResult(new byte[] { 1, 2, 3 })); + return Task.CompletedTask; + }) + .Resource; + + await builder.BuildAsync(); + + var configContextFactory = CreateCertificateTrustConfigurationContextFactory(); + var context = new ExecutionConfigurationGathererContext(); + var gatherer = new CertificateTrustExecutionConfigurationGatherer(configContextFactory); + + await gatherer.GatherAsync(context, resource, NullLogger.Instance, builder.ExecutionContext); + + Assert.NotNull(capturedBundlePath); + var resolvedPath = await capturedBundlePath.GetValueAsync(CancellationToken.None); + Assert.NotNull(resolvedPath); + Assert.Contains("/bundles/", resolvedPath); + Assert.StartsWith("/etc/ssl/certs", resolvedPath); + } + + [Fact] + public async Task CreateCustomBundle_MultipleBundles_AllRegistered() + { + using var builder = TestDistributedApplicationBuilder.Create(); + var cert = CreateTestCertificate(); + var caCollection = builder.AddCertificateAuthorityCollection("test-ca").WithCertificate(cert); + + var resource = builder.AddContainer("test", "image") + .WithCertificateAuthorityCollection(caCollection) + .WithCertificateTrustConfiguration(ctx => + { + var bundle1 = ctx.CreateCustomBundle((certs, ct) => + Task.FromResult(new byte[] { 1 })); + var bundle2 = ctx.CreateCustomBundle((certs, ct) => + Task.FromResult(new byte[] { 2 })); + ctx.EnvironmentVariables["BUNDLE1"] = bundle1; + ctx.EnvironmentVariables["BUNDLE2"] = bundle2; + return Task.CompletedTask; + }) + .Resource; + + await builder.BuildAsync(); + + var configContextFactory = CreateCertificateTrustConfigurationContextFactory(); + var context = new ExecutionConfigurationGathererContext(); + var gatherer = new CertificateTrustExecutionConfigurationGatherer(configContextFactory); + + await gatherer.GatherAsync(context, resource, NullLogger.Instance, builder.ExecutionContext); + + var metadata = context.AdditionalConfigurationData.OfType().Single(); + Assert.Equal(2, metadata.CustomBundlesFactories.Count); + + // Verify each factory has a distinct key + var keys = metadata.CustomBundlesFactories.Keys.ToList(); + Assert.NotEqual(keys[0], keys[1]); + } + + [Fact] + public async Task CreateCustomBundle_Pkcs12BundleFactory_ProducesValidPkcs12() + { + using var builder = TestDistributedApplicationBuilder.Create(); + var cert = CreateTestCertificate(); + var caCollection = builder.AddCertificateAuthorityCollection("test-ca").WithCertificate(cert); + + var resource = builder.AddContainer("test", "image") + .WithCertificateAuthorityCollection(caCollection) + .WithCertificateTrustConfiguration(ctx => + { + var password = string.Empty; + var bundlePath = ctx.CreateCustomBundle((certificates, ct) => + { + var pkcs12Builder = new Pkcs12Builder(); + var safeContents = new Pkcs12SafeContents(); + + // Oracle/Java trust anchor bag attribute OID + var trustAnchorOid = new Oid("2.16.840.1.113894.746875.1.1"); + var asnWriter = new AsnWriter(AsnEncodingRules.DER); + asnWriter.WriteObjectIdentifier("2.5.29.37.0"); + var trustAnchorValue = asnWriter.Encode(); + + for (var i = 0; i < certificates.Count; i++) + { + var publicCert = new X509Certificate2(certificates[i].Export(X509ContentType.Cert)); + var certBag = safeContents.AddCertificate(publicCert); + certBag.Attributes.Add( + new CryptographicAttributeObject( + trustAnchorOid, + new AsnEncodedDataCollection(new AsnEncodedData(trustAnchorOid, trustAnchorValue)))); + } + + pkcs12Builder.AddSafeContentsUnencrypted(safeContents); + pkcs12Builder.SealWithMac(password, HashAlgorithmName.SHA256, iterationCount: 2048); + + return Task.FromResult(pkcs12Builder.Encode()); + }); + ctx.EnvironmentVariables["JAVAX_NET_SSL_TRUSTSTORE"] = bundlePath; + ctx.EnvironmentVariables["JAVAX_NET_SSL_TRUSTSTOREPASSWORD"] = password; + return Task.CompletedTask; + }) + .Resource; + + await builder.BuildAsync(); + + var configContextFactory = CreateCertificateTrustConfigurationContextFactory(); + var context = new ExecutionConfigurationGathererContext(); + var gatherer = new CertificateTrustExecutionConfigurationGatherer(configContextFactory); + + await gatherer.GatherAsync(context, resource, NullLogger.Instance, builder.ExecutionContext); + + var metadata = context.AdditionalConfigurationData.OfType().Single(); + Assert.Single(metadata.CustomBundlesFactories); + + // Invoke the stored factory and validate the PKCS#12 output + var factory = metadata.CustomBundlesFactories.Values.Single(); + var pkcs12Bytes = await factory(metadata.Certificates, CancellationToken.None); + Assert.NotEmpty(pkcs12Bytes); + + var loaded = new X509Certificate2Collection(); + loaded.Import(pkcs12Bytes, string.Empty, X509KeyStorageFlags.DefaultKeySet); + Assert.Single(loaded); + Assert.Equal(cert.Thumbprint, loaded[0].Thumbprint); + Assert.False(loaded[0].HasPrivateKey); + + // Verify the PKCS#12 contains Java trust anchor attributes + var info = Pkcs12Info.Decode(pkcs12Bytes, out _, skipCopy: true); + var bagsWithTrustAnchor = 0; + foreach (var safeContents in info.AuthenticatedSafe) + { + foreach (var bag in safeContents.GetBags()) + { + foreach (CryptographicAttributeObject attr in bag.Attributes) + { + if (attr.Oid.Value == "2.16.840.1.113894.746875.1.1") + { + Assert.Single(attr.Values); + var reader = new AsnReader(attr.Values[0].RawData, AsnEncodingRules.DER); + Assert.Equal("2.5.29.37.0", reader.ReadObjectIdentifier()); + Assert.False(reader.HasData); + bagsWithTrustAnchor++; + break; + } + } + } + } + Assert.Equal(1, bagsWithTrustAnchor); + } + + [Fact] + public async Task CreateCustomBundle_FactoryReceivesCertificatesAndCancellationToken() + { + using var builder = TestDistributedApplicationBuilder.Create(); + var cert = CreateTestCertificate(); + var caCollection = builder.AddCertificateAuthorityCollection("test-ca").WithCertificate(cert); + + var resource = builder.AddContainer("test", "image") + .WithCertificateAuthorityCollection(caCollection) + .WithCertificateTrustConfiguration(ctx => + { + ctx.CreateCustomBundle((certs, ct) => + Task.FromResult(Array.Empty())); + return Task.CompletedTask; + }) + .Resource; + + await builder.BuildAsync(); + + var configContextFactory = CreateCertificateTrustConfigurationContextFactory(); + var context = new ExecutionConfigurationGathererContext(); + var gatherer = new CertificateTrustExecutionConfigurationGatherer(configContextFactory); + + await gatherer.GatherAsync(context, resource, NullLogger.Instance, builder.ExecutionContext); + + var metadata = context.AdditionalConfigurationData.OfType().Single(); + var factory = metadata.CustomBundlesFactories.Values.Single(); + + // Invoke the factory with the certificates from the metadata and verify it receives them + using var cts = new CancellationTokenSource(); + var result = await factory(metadata.Certificates, cts.Token); + Assert.NotNull(result); + Assert.Single(metadata.Certificates); + Assert.Equal(cert.Thumbprint, metadata.Certificates[0].Thumbprint); + } + + #endregion + #region HttpsCertificateExecutionConfigurationGatherer Tests [Fact] @@ -371,7 +603,7 @@ public async Task HttpsCertificateExecutionConfigurationGatherer_WithCertificate { // Arrange using var builder = TestDistributedApplicationBuilder.Create(); - var cert = CreateTestCertificate(); + var cert = CreateTestCertificateWithPrivateKey(); var resource = builder.AddContainer("test", "image") .WithAnnotation(new HttpsCertificateAnnotation { Certificate = cert }) @@ -399,7 +631,7 @@ public async Task HttpsCertificateExecutionConfigurationGatherer_WithPassword_St // Arrange using var builder = TestDistributedApplicationBuilder.Create(); builder.Configuration["Parameters:password"] = "test-password"; - var cert = CreateTestCertificate(); + var cert = CreateTestCertificateWithPrivateKey(); var password = builder.AddParameter("password", secret: true); var resource = builder.AddContainer("test", "image") @@ -477,7 +709,7 @@ public async Task HttpsCertificateExecutionConfigurationGatherer_TracksReference { // Arrange using var builder = TestDistributedApplicationBuilder.Create(); - var cert = CreateTestCertificate(); + var cert = CreateTestCertificateWithPrivateKey(); var resource = builder.AddContainer("test", "image") .WithAnnotation(new HttpsCertificateAnnotation { Certificate = cert }) @@ -512,7 +744,7 @@ public async Task HttpsCertificateExecutionConfigurationGatherer_WithCallback_Ex { // Arrange using var builder = TestDistributedApplicationBuilder.Create(); - var cert = CreateTestCertificate(); + var cert = CreateTestCertificateWithPrivateKey(); var callbackExecuted = false; var resource = builder.AddContainer("test", "image") @@ -540,6 +772,29 @@ public async Task HttpsCertificateExecutionConfigurationGatherer_WithCallback_Ex #endregion private static X509Certificate2 CreateTestCertificate() + { + using var rsa = RSA.Create(2048); + var request = new CertificateRequest( + new X500DistinguishedName("CN=test"), + rsa, + HashAlgorithmName.SHA256, + RSASignaturePadding.Pkcs1); + + // Use Create() instead of CreateSelfSigned() to produce a public-only certificate + // that doesn't touch the macOS keychain (avoids AppleCommonCryptoCryptographicException). + var serialNumber = new byte[16]; + RandomNumberGenerator.Fill(serialNumber); + var generator = X509SignatureGenerator.CreateForRSA(rsa, RSASignaturePadding.Pkcs1); + + return request.Create( + request.SubjectName, + generator, + DateTimeOffset.Now, + DateTimeOffset.Now.AddYears(1), + serialNumber); + } + + private static X509Certificate2 CreateTestCertificateWithPrivateKey() { using var rsa = RSA.Create(2048); var request = new CertificateRequest( @@ -556,7 +811,9 @@ private static Func new CertificateTrustExecutionConfigurationContext { CertificateBundlePath = ReferenceExpression.Create($"/etc/ssl/certs/ca-bundle.crt"), - CertificateDirectoriesPath = ReferenceExpression.Create($"/etc/ssl/certs") + CertificateDirectoriesPath = ReferenceExpression.Create($"/etc/ssl/certs"), + RootCertificatesPath = "/etc/ssl/certs", + IsContainer = true, }; } diff --git a/tests/Aspire.Hosting.Tests/MSBuildTests.cs b/tests/Aspire.Hosting.Tests/MSBuildTests.cs index 7100f876562..8ccefd334d4 100644 --- a/tests/Aspire.Hosting.Tests/MSBuildTests.cs +++ b/tests/Aspire.Hosting.Tests/MSBuildTests.cs @@ -372,6 +372,133 @@ the Aspire.AppHost.SDK targets that will automatically add these references to p Assert.Contains("warning ASPIRE004", output); } + [Fact] + public void AspireExportAnalyzersAreDisabledByDefault() + { + var repoRoot = MSBuildUtils.GetRepoRoot(); + using var tempDirectory = new TestTempDirectory(); + + var projectDirectory = Path.Combine(tempDirectory.Path, "MyHostingExtension"); + Directory.CreateDirectory(projectDirectory); + + File.WriteAllText(Path.Combine(projectDirectory, "MyHostingExtension.csproj"), + $""" + + + + net8.0 + enable + enable + + + + + + + + """); + + File.WriteAllText(Path.Combine(projectDirectory, "Extensions.cs"), + """ + using Aspire.Hosting; + using Aspire.Hosting.ApplicationModel; + + namespace MyHostingExtension; + + public static class CustomResourceExtensions + { + public static IResourceBuilder AddCustomContainer(this IDistributedApplicationBuilder builder) + { + return builder.AddContainer("custom", "custom-image"); + } + } + """); + + CreateExportAnalyzerDirectoryBuildFiles(projectDirectory, repoRoot); + + var output = BuildProject(projectDirectory); + + Assert.DoesNotContain("warning ASPIREEXPORT008", output); + } + + [Fact] + public void AspireExportAnalyzersCanBeEnabledWithMsBuildProperty() + { + var repoRoot = MSBuildUtils.GetRepoRoot(); + using var tempDirectory = new TestTempDirectory(); + + var projectDirectory = Path.Combine(tempDirectory.Path, "MyHostingExtension"); + Directory.CreateDirectory(projectDirectory); + + File.WriteAllText(Path.Combine(projectDirectory, "MyHostingExtension.csproj"), + $""" + + + + net8.0 + enable + enable + + + + + + + + """); + + File.WriteAllText(Path.Combine(projectDirectory, "Extensions.cs"), + """ + using Aspire.Hosting; + using Aspire.Hosting.ApplicationModel; + + namespace MyHostingExtension; + + public static class CustomResourceExtensions + { + public static IResourceBuilder AddCustomContainer(this IDistributedApplicationBuilder builder) + { + return builder.AddContainer("custom", "custom-image"); + } + } + """); + + CreateExportAnalyzerDirectoryBuildFiles(projectDirectory, repoRoot, enableAspireIntegrationAnalyzers: true); + + var output = BuildProject(projectDirectory); + + Assert.Contains("warning ASPIREEXPORT008", output); + } + + private static void CreateExportAnalyzerDirectoryBuildFiles( + string basePath, + string repoRoot, + bool enableAspireIntegrationAnalyzers = false) + { + File.WriteAllText(Path.Combine(basePath, "Directory.Build.props"), + $""" + + + {enableAspireIntegrationAnalyzers.ToString().ToLowerInvariant()} + + + """); + File.WriteAllText(Path.Combine(basePath, "Directory.Build.targets"), + $""" + + + + + + + + """); + } + /// /// Tests that when GenerateAssemblyInfo is set to false, a build error is emitted. /// diff --git a/tests/Infrastructure.Tests/WorkflowScripts/AutoRerunTransientCiFailuresTests.cs b/tests/Infrastructure.Tests/WorkflowScripts/AutoRerunTransientCiFailuresTests.cs index c49947e47aa..68404ba76d5 100644 --- a/tests/Infrastructure.Tests/WorkflowScripts/AutoRerunTransientCiFailuresTests.cs +++ b/tests/Infrastructure.Tests/WorkflowScripts/AutoRerunTransientCiFailuresTests.cs @@ -64,7 +64,7 @@ public async Task SkipsJobsWhoseFailedStepsAreOutsideRetrySafeAllowlist() Assert.Empty(result.RetryableJobs); Assert.Single(result.SkippedJobs); - Assert.Equal("Failed steps are outside the retry-safe allowlist.", result.SkippedJobs[0].Reason); + Assert.Equal("Failed step 'Compile project' is not covered by the retry-safe rerun rules.", result.SkippedJobs[0].Reason); } [Fact] @@ -77,7 +77,7 @@ public async Task SkipsRetrySafeStepsWhenAnnotationsAreGeneric() Assert.Empty(result.RetryableJobs); Assert.Single(result.SkippedJobs); - Assert.Equal("Annotations did not match the transient allowlist.", result.SkippedJobs[0].Reason); + Assert.Equal("Failed step 'Set up .NET Core' did not include a retry-safe transient infrastructure signal in the job annotations.", result.SkippedJobs[0].Reason); } [Theory] @@ -105,7 +105,9 @@ public async Task KeepsMixedFailureVetoWhenIgnoredTestStepsFailAlongsideRetrySaf Assert.Empty(result.RetryableJobs); Assert.Single(result.SkippedJobs); - Assert.Equal("Annotations did not match the transient allowlist.", result.SkippedJobs[0].Reason); + Assert.Equal( + "Failed steps 'Run tests (Windows) | Upload logs, and test results' include a test execution failure, so the job was not retried without a high-confidence infrastructure override.", + result.SkippedJobs[0].Reason); } [Fact] @@ -156,7 +158,9 @@ public async Task DoesNotOverrideWindowsProcessInitializationFailuresWhenTestExe Assert.Empty(result.RetryableJobs); Assert.Single(result.SkippedJobs); - Assert.Equal("Annotations did not match the transient allowlist.", result.SkippedJobs[0].Reason); + Assert.Equal( + "Failed steps 'Run tests (Windows) | Upload logs, and test results | Generate test results summary' include a test execution failure, so the job was not retried without a high-confidence infrastructure override.", + result.SkippedJobs[0].Reason); } [Fact] @@ -171,7 +175,9 @@ public async Task AllowsNarrowLogBasedOverrideForDncengFeedServiceIndexFailuresI "error : Unable to load the service index for source https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public/nuget/v3/index.json."); Assert.Single(result.RetryableJobs); - Assert.Equal("Ignored failed step 'Build test project' matched the feed network failure override allowlist.", result.RetryableJobs[0].Reason); + Assert.Equal( + "Failed step 'Build test project' will be retried because the job log shows a likely transient infrastructure network failure. Matched pattern: /Unable to load the service index for source https:\\/\\/(?:pkgs\\.dev\\.azure\\.com\\/dnceng|dnceng\\.pkgs\\.visualstudio\\.com)\\/public\\/_packaging\\//i.", + result.RetryableJobs[0].Reason); } [Theory] @@ -190,7 +196,44 @@ public async Task AllowsSameFeedOverrideForOtherCiBootstrapBuildAndValidationSte "error : Unable to load the service index for source https://dnceng.pkgs.visualstudio.com/public/_packaging/dotnet9-transport/nuget/v3/index.json."); Assert.Single(result.RetryableJobs); - Assert.Equal($"Ignored failed step '{failedStep}' matched the feed network failure override allowlist.", result.RetryableJobs[0].Reason); + Assert.Equal( + $"Failed step '{failedStep}' will be retried because the job log shows a likely transient infrastructure network failure. Matched pattern: /Unable to load the service index for source https:\\/\\/(?:pkgs\\.dev\\.azure\\.com\\/dnceng|dnceng\\.pkgs\\.visualstudio\\.com)\\/public\\/_packaging\\//i.", + result.RetryableJobs[0].Reason); + } + + [Fact] + [RequiresTools(["node"])] + public async Task AllowsSameNetworkOverrideForBroaderBootstrapStepsOutsideTheOldAllowlist() + { + WorkflowJob job = CreateJob(failedSteps: ["Run ./.github/actions/enumerate-tests"]); + + AnalyzeFailedJobsResult result = await AnalyzeSingleJobAsync( + job, + "Process completed with exit code 1.", + "error : Unable to load the service index for source https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public/nuget/v3/index.json."); + + Assert.Single(result.RetryableJobs); + Assert.Equal( + "Failed step 'Run ./.github/actions/enumerate-tests' will be retried because the job log shows a likely transient infrastructure network failure. Matched pattern: /Unable to load the service index for source https:\\/\\/(?:pkgs\\.dev\\.azure\\.com\\/dnceng|dnceng\\.pkgs\\.visualstudio\\.com)\\/public\\/_packaging\\//i.", + result.RetryableJobs[0].Reason); + } + + [Fact] + [RequiresTools(["node"])] + public async Task DoesNotApplyBroadNetworkOverrideWhenTestExecutionFailed() + { + WorkflowJob job = CreateJob(failedSteps: ["Run tests (Windows)"]); + + AnalyzeFailedJobsResult result = await AnalyzeSingleJobAsync( + job, + "Process completed with exit code 1.", + "error : Unable to load the service index for source https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public/nuget/v3/index.json."); + + Assert.Empty(result.RetryableJobs); + Assert.Single(result.SkippedJobs); + Assert.Equal( + "Failed step 'Run tests (Windows)' includes a test execution failure, so the job was not retried without a high-confidence infrastructure override.", + result.SkippedJobs[0].Reason); } [Fact] @@ -206,7 +249,9 @@ public async Task DoesNotRetryIgnoredBuildStepsWhenTheLogLacksFeedNetworkSignatu Assert.Empty(result.RetryableJobs); Assert.Single(result.SkippedJobs); - Assert.Equal("Annotations did not match the transient allowlist.", result.SkippedJobs[0].Reason); + Assert.Equal( + "Failed step 'Build test project' is only retried when the job shows a high-confidence infrastructure override, and none was found.", + result.SkippedJobs[0].Reason); } [Fact] @@ -266,7 +311,7 @@ public async Task GetCheckRunIdForJobReturnsNullWhenNoCheckRunIdCanBeResolved() [Fact] [RequiresTools(["node"])] - public async Task WorkflowDispatchStaysDryRunEvenWhenRetryableJobsExist() + public async Task ComputeRerunEligibilityDisablesRerunsWhenDryRunIsEnabled() { bool rerunEligible = await InvokeHarnessAsync( "computeRerunEligibility", @@ -356,6 +401,7 @@ public async Task RepresentativeWorkflowFixturesStayAlignedWithCurrentWorkflowDe ], [".github/workflows/tests.yml"] = [ + "- uses: ./.github/actions/enumerate-tests", "name: Final Test Results", ], }; @@ -377,13 +423,18 @@ public async Task WorkflowYamlKeepsDocumentedSafetyRails() string workflowText = await ReadRepoFileAsync(".github/workflows/auto-rerun-transient-ci-failures.yml"); Assert.Contains("workflow_dispatch:", workflowText); + Assert.Contains("dry_run:", workflowText); + Assert.Contains("default: false", workflowText); Assert.Contains("github.event.workflow_run.run_attempt == 1", workflowText); Assert.Contains("needs.analyze-transient-failures.outputs.rerun_eligible == 'true'", workflowText); + Assert.Contains("MANUAL_DRY_RUN", workflowText); + Assert.Contains("function parseManualDryRun()", workflowText); + Assert.Contains("const dryRun = parseManualDryRun();", workflowText); } [Fact] [RequiresTools(["node"])] - public async Task WriteAnalysisSummaryLinksTheAnalyzedWorkflowRun() + public async Task WriteAnalysisSummaryUsesExplicitOutcomeHeadingAndClickableAnalyzedRunLink() { SummaryResult result = await InvokeHarnessAsync( "writeAnalysisSummary", @@ -400,11 +451,18 @@ public async Task WriteAnalysisSummaryLinksTheAnalyzedWorkflowRun() skippedJobs = Array.Empty(), dryRun = false, rerunEligible = true, + sourceRunAttempt = 1, sourceRunUrl = "https://github.com/dotnet/aspire/actions/runs/123" }); - SummaryEvent rawEvent = Assert.Single(result.Events, e => e.Type == "raw"); - Assert.Equal("Source run: [workflow run](https://github.com/dotnet/aspire/actions/runs/123)\n\n", rawEvent.Text); + SummaryEvent headingEvent = Assert.Single(result.Events, e => e.Type == "heading" && e.Level == 1); + Assert.Equal("Rerun eligible", headingEvent.Text); + + SummaryEvent linkEvent = Assert.Single(result.Events, e => e.Type == "link" && e.Text == "workflow run attempt 1"); + Assert.Equal("https://github.com/dotnet/aspire/actions/runs/123/attempts/1", linkEvent.Href); + + SummaryEvent rawEvent = Assert.Single(result.Events, e => e.Type == "raw" && e.Text == "Matched 1 retry-safe job for rerun."); + Assert.Equal("Matched 1 retry-safe job for rerun.", rawEvent.Text); } [Fact] @@ -457,6 +515,10 @@ public async Task RerunMatchedJobsRequestsOneRerunPerSelectedJobAndWritesTheSumm { ["15110"] = "open" }, + commentHtmlUrlByNumber = new Dictionary + { + ["15110"] = "https://github.com/dotnet/aspire/pull/15110#issuecomment-123" + }, latestRunAttempt = 2, sourceRunId = 123, sourceRunAttempt = 1, @@ -496,9 +558,17 @@ public async Task RerunMatchedJobsRequestsOneRerunPerSelectedJobAndWritesTheSumm request.Payload.GetProperty("body").GetString()); }); - SummaryEvent rawEvent = Assert.Single(result.Events, e => e.Type == "raw" && e.Text is not null && e.Text.Contains("Failed attempt:")); - Assert.Contains("Failed attempt: [workflow run attempt 1](https://github.com/dotnet/aspire/actions/runs/123/attempts/1)", rawEvent.Text); - Assert.Contains("Rerun attempt: [workflow run attempt 2](https://github.com/dotnet/aspire/actions/runs/123/attempts/2)", rawEvent.Text); + SummaryEvent headingEvent = Assert.Single(result.Events, e => e.Type == "heading" && e.Level == 1); + Assert.Equal("Rerun requested", headingEvent.Text); + + SummaryEvent failedAttemptLink = Assert.Single(result.Events, e => e.Type == "link" && e.Text == "workflow run attempt 1"); + Assert.Equal("https://github.com/dotnet/aspire/actions/runs/123/attempts/1", failedAttemptLink.Href); + + SummaryEvent rerunAttemptLink = Assert.Single(result.Events, e => e.Type == "link" && e.Text == "workflow run attempt 2"); + Assert.Equal("https://github.com/dotnet/aspire/actions/runs/123/attempts/2", rerunAttemptLink.Href); + + SummaryEvent commentLink = Assert.Single(result.Events, e => e.Type == "link" && e.Text == "PR #15110 comment"); + Assert.Equal("https://github.com/dotnet/aspire/pull/15110#issuecomment-123", commentLink.Href); SummaryEvent tableEvent = Assert.Single(result.Events, e => e.Type == "table"); Assert.Equal("Job", tableEvent.Rows[0][0].GetProperty("data").GetString()); @@ -508,8 +578,7 @@ public async Task RerunMatchedJobsRequestsOneRerunPerSelectedJobAndWritesTheSumm Assert.Equal("Tests / Two", tableEvent.Rows[2][0].GetString()); Assert.Equal("Reason two", tableEvent.Rows[2][1].GetString()); - SummaryEvent commentEvent = Assert.Single(result.Events, e => e.Type == "raw" && e.Text is not null && e.Text.Contains("Posted rerun details to #15110.")); - Assert.Contains("Posted rerun details to #15110.", commentEvent.Text); + Assert.Contains(result.Events, e => e.Type == "raw" && e.Text == "Pull request comments:"); } [Fact] @@ -544,9 +613,12 @@ public async Task RerunMatchedJobsSkipsRerunsWhenAllAssociatedPullRequestsAreClo Assert.Equal("GET /repos/{owner}/{repo}/issues/{issue_number}", request.Route); Assert.Equal(15110, request.Payload.GetProperty("issue_number").GetInt32()); - SummaryEvent skippedHeading = Assert.Single(result.Events, e => e.Type == "heading" && e.Text == "Automatic rerun skipped"); + SummaryEvent skippedHeading = Assert.Single(result.Events, e => e.Type == "heading" && e.Text == "Rerun skipped"); Assert.Equal(1, skippedHeading.Level); + SummaryEvent analyzedRunLink = Assert.Single(result.Events, e => e.Type == "link" && e.Text == "workflow run"); + Assert.Equal("https://github.com/dotnet/aspire/actions/runs/123", analyzedRunLink.Href); + SummaryEvent skippedRaw = Assert.Single(result.Events, e => e.Type == "raw" && e.Text is not null && e.Text.Contains("All associated pull requests are closed.")); Assert.Contains("All associated pull requests are closed. No jobs were rerun.", skippedRaw.Text); } @@ -691,6 +763,7 @@ private sealed class SummaryEvent { public string Type { get; init; } = string.Empty; public string? Text { get; init; } + public string? Href { get; init; } public int? Level { get; init; } public bool? AddEol { get; init; } public JsonElement[][] Rows { get; init; } = []; diff --git a/tests/Infrastructure.Tests/WorkflowScripts/auto-rerun-transient-ci-failures.harness.js b/tests/Infrastructure.Tests/WorkflowScripts/auto-rerun-transient-ci-failures.harness.js index 5f2db9c0afb..50e84244bd5 100644 --- a/tests/Infrastructure.Tests/WorkflowScripts/auto-rerun-transient-ci-failures.harness.js +++ b/tests/Infrastructure.Tests/WorkflowScripts/auto-rerun-transient-ci-failures.harness.js @@ -21,6 +21,16 @@ class SummaryRecorder { return this; } + addLink(text, href) { + this.events.push({ type: 'link', text, href }); + return this; + } + + addBreak() { + this.events.push({ type: 'break' }); + return this; + } + async write() { this.events.push({ type: 'write' }); return this; @@ -111,6 +121,18 @@ function createGitHubRecorder(payload, requests) { }; } + if (route === 'POST /repos/{owner}/{repo}/issues/{issue_number}/comments') { + const issueNumber = String(requestPayload.issue_number); + const htmlUrl = payload.commentHtmlUrlByNumber?.[issueNumber] + ?? `https://github.com/${requestPayload.owner}/${requestPayload.repo}/pull/${issueNumber}#issuecomment-${issueNumber}`; + + return { + data: { + html_url: htmlUrl, + }, + }; + } + return { data: {} }; }, }; diff --git a/tests/Shared/Hex1bTestHelpers.cs b/tests/Shared/Hex1bTestHelpers.cs index 6baa44baf6c..e9e2787d5de 100644 --- a/tests/Shared/Hex1bTestHelpers.cs +++ b/tests/Shared/Hex1bTestHelpers.cs @@ -497,6 +497,34 @@ internal static Hex1bTerminalInputSequenceBuilder AspireNew( return builder.DeclineAgentInitPrompt(counter); } + /// + /// Runs aspire init --language csharp and handles the NuGet.config and agent init prompts. + /// Explicitly waits for the NuGet.config prompt (or init completion) rather than using a blind timer, + /// then declines the agent init prompt so the command exits cleanly. + /// + internal static Hex1bTerminalInputSequenceBuilder AspireInit( + this Hex1bTerminalInputSequenceBuilder builder, + SequenceCounter counter) + { + var waitingForNuGetConfigPrompt = new CellPatternSearcher() + .Find("NuGet.config"); + + var waitingForInitComplete = new CellPatternSearcher() + .Find("Aspire initialization complete"); + + return builder + .Type("aspire init --language csharp") + .Enter() + // NuGet.config prompt may or may not appear depending on environment. + // Wait for either the NuGet.config prompt or init completion. + .WaitUntil(s => waitingForNuGetConfigPrompt.Search(s).Count > 0 + || waitingForInitComplete.Search(s).Count > 0, TimeSpan.FromMinutes(2)) + .Enter() // Dismiss NuGet.config prompt if present + .WaitUntil(s => waitingForInitComplete.Search(s).Count > 0, TimeSpan.FromMinutes(2)) + .DeclineAgentInitPrompt() + .WaitForSuccessPrompt(counter, TimeSpan.FromMinutes(2)); + } + /// /// Installs the Aspire CLI Bundle from a specific pull request's artifacts. /// The bundle is a self-contained distribution that includes: