Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions .github/workflows/generate-ats-diffs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,15 @@ jobs:
run: ./dotnet.sh build src/Aspire.Cli/Aspire.Cli.csproj --configuration Release

- name: Discover and dump ATS capabilities
env:
ASPIRE_REPO_ROOT: ${{ github.workspace }}
run: |
ASPIRE_CLI="./dotnet.sh run --no-build --project src/Aspire.Cli/Aspire.Cli.csproj --configuration Release -- --nologo"
FAILURES=0

# Dump core Aspire.Hosting capabilities (no integration argument)
echo "::group::Aspire.Hosting (core)"
if ! $ASPIRE_CLI sdk dump --ci -o src/Aspire.Hosting/api/Aspire.Hosting.ats.txt; then
if ! $ASPIRE_CLI sdk dump --format ci -o src/Aspire.Hosting/api/Aspire.Hosting.ats.txt; then
echo "::error::Failed to dump core Aspire.Hosting capabilities"
exit 1
fi
Expand Down Expand Up @@ -61,7 +63,7 @@ jobs:
if [ -f "$csproj" ]; then
echo "::group::$proj_name"
mkdir -p "$proj/api"
if ! $ASPIRE_CLI sdk dump --ci "$csproj" -o "$proj/api/$proj_name.ats.txt"; then
if ! $ASPIRE_CLI sdk dump --format ci "$csproj" -o "$proj/api/$proj_name.ats.txt"; then
echo "::error::Failed to dump ATS capabilities for $proj_name"
FAILURES=$((FAILURES + 1))
fi
Expand Down
Original file line number Diff line number Diff line change
@@ -1 +1 @@
C67863A907D78BB59660D5A50F35F651038B645DD4F0E664C2E5B7DDA765F717
55EDF8F87C54643AFA1348DDF04FFCAA63F2591775B2B2792B2A3DE7EEE738BB

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -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.
*
Expand All @@ -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!,
Expand All @@ -107,6 +161,9 @@ export class ReferenceExpression {
if (this._handle) {
return `ReferenceExpression(handle)`;
}
if (this.isConditional) {
return `ReferenceExpression(conditional)`;
}
return `ReferenceExpression(${this._format})`;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,19 @@ const tunnel4 = await builder.addDevTunnel("get-endpoint-tunnel");
await tunnel4.withTunnelReference(web4Endpoint);
const _tunnelEndpoint = await tunnel4.getTunnelEndpoint(web4Endpoint);

// Test 9: Chained configuration
// Test 9: addDevTunnel with the dedicated polyglot parameters
const tunnel5 = await builder.addDevTunnel("configured-tunnel", {
tunnelId: "configured-tunnel-id",
allowAnonymous: true,
description: "Configured by the polyglot validation app",
labels: ["validation", "polyglot"]
});
const web5 = await builder.addContainer("web5", "nginx")
.withHttpEndpoint({ port: 9090 });
const web5Endpoint = await web5.getEndpoint("http");
await tunnel5.withTunnelReferenceAnonymous(web5Endpoint, true);

// Test 10: Chained configuration
await builder.addDevTunnel("chained-tunnel")
.withAnonymousAccess();

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"appHostPath": "../apphost.ts",
"language": "typescript/nodejs",
"packages": {
"Aspire.Hosting.Foundry": ""
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
DE722F4CC472CDD941E57780B800FF7D4A8BFD3EAE29E5192958620B186DCE67
Loading
Loading