Skip to content

Commit cf79809

Browse files
committed
fix: finalize primary dx path follow-ups
1 parent 8e8bb0b commit cf79809

File tree

2 files changed

+77
-20
lines changed

2 files changed

+77
-20
lines changed

docs/articles/getting-started.md

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Getting Started
22

3-
Get a hybrid desktop app running in under five minutes — a native Avalonia window hosting your web frontend, with type-safe bridge calls between C# and JavaScript.
3+
Get a hybrid desktop app running in under five minutes — a native Avalonia window hosting your web frontend so you can start building product features right away.
44

55
## The main path
66

@@ -51,6 +51,12 @@ fulora dev
5151

5252
You'll see a native window open with your app inside, ready for normal product work.
5353

54+
After these three steps, you have:
55+
56+
- A native desktop window hosting your web app
57+
- A web frontend and native host already wired together
58+
- Fulora services ready for normal app development
59+
5460
Alternatively, use `dotnet new` directly:
5561

5662
```bash
@@ -59,13 +65,17 @@ cd MyApp
5965
dotnet run --project MyApp.Desktop
6066
```
6167

62-
## What you'll end up with
68+
## Fulora services already use the bridge underneath
69+
70+
When you use `fulora new`, you mostly work with app-level services and UI code first. Under the hood, those services talk across the Fulora bridge for you.
71+
72+
- Your frontend still runs inside a native WebView
73+
- Your native code still runs in-process in C#
74+
- Fulora services use generated bridge contracts underneath, so app code can stay focused on product features
6375

64-
After the three steps above, you have a native desktop window hosting your web app, with Fulora services ready for normal app development.
76+
This means you can start by building screens and calling services, then learn the bridge layer when you need custom native capabilities or plugin work.
6577

66-
- The **UI** runs inside a native WebView
67-
- The **backend** runs in-process in C#
68-
- Fulora connects them with generated bridge contracts underneath
78+
If you want the mental model, it looks like this:
6979

7080
```
7181
┌───────────────────────────────────┐
@@ -84,16 +94,6 @@ After the three steps above, you have a native desktop window hosting your web a
8494
└───────────────────────────────────┘
8595
```
8696

87-
## Fulora services already use the bridge underneath
88-
89-
When you use `fulora new`, you mostly work with app-level services and UI code first. Under the hood, those services talk across the Fulora bridge for you.
90-
91-
- Your frontend still runs inside a native WebView
92-
- Your native code still runs in-process in C#
93-
- Fulora services use generated bridge contracts underneath, so app code can stay focused on product features
94-
95-
This means you can start by building screens and calling services, then learn the bridge layer when you need custom native capabilities or plugin work.
96-
9797
## Manual path: add Fulora to an existing Avalonia app
9898

9999
If you already have an Avalonia project or need full control over the setup.

tests/Agibuild.Fulora.UnitTests/AppDistributionTests.cs

Lines changed: 61 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -461,25 +461,82 @@ public void PackageCommand_profile_defaults_allow_explicit_false_notarize_overri
461461
}
462462

463463
[Fact]
464-
public void PackageCommand_profile_defaults_allow_explicit_runtime_and_channel_overrides()
464+
public void PackageCommand_profile_defaults_apply_when_options_are_implicit()
465465
{
466466
var command = PackageCommand.Create();
467467
var runtimeOption = Assert.IsType<Option<string>>(command.Options.Single(o => o.Name == "--runtime"));
468468
var channelOption = Assert.IsType<Option<string>>(command.Options.Single(o => o.Name == "--channel"));
469-
var profile = PackageProfileDefaults.Resolve("desktop-public");
469+
var notarizeOption = Assert.IsType<Option<bool>>(command.Options.Single(o => o.Name == "--notarize"));
470+
var profile = PackageProfileDefaults.Resolve("mac-notarized");
471+
var root = new RootCommand("test");
472+
root.Subcommands.Add(command);
473+
var parseResult = root.Parse("package --profile mac-notarized");
474+
475+
var runtimeResult = parseResult.GetResult(runtimeOption);
476+
var channelResult = parseResult.GetResult(channelOption);
477+
var notarizeResult = parseResult.GetResult(notarizeOption);
478+
479+
Assert.NotNull(runtimeResult);
480+
Assert.NotNull(channelResult);
481+
Assert.NotNull(notarizeResult);
482+
Assert.True(runtimeResult!.Implicit);
483+
Assert.True(channelResult!.Implicit);
484+
Assert.True(notarizeResult!.Implicit);
485+
Assert.Equal("osx-arm64", PackageCommand.GetValue(runtimeOption, parseResult, profile.Runtime));
486+
Assert.Equal("stable", PackageCommand.GetValue(channelOption, parseResult, profile.Channel));
487+
Assert.True(PackageCommand.GetValue(notarizeOption, parseResult, profile.Notarize));
488+
}
489+
490+
[Fact]
491+
public void PackageCommand_profile_defaults_allow_explicit_runtime_channel_and_notarize_overrides()
492+
{
493+
var command = PackageCommand.Create();
494+
var runtimeOption = Assert.IsType<Option<string>>(command.Options.Single(o => o.Name == "--runtime"));
495+
var channelOption = Assert.IsType<Option<string>>(command.Options.Single(o => o.Name == "--channel"));
496+
var notarizeOption = Assert.IsType<Option<bool>>(command.Options.Single(o => o.Name == "--notarize"));
497+
var profile = PackageProfileDefaults.Resolve("mac-notarized");
470498
var root = new RootCommand("test");
471499
root.Subcommands.Add(command);
472-
var parseResult = root.Parse("package --profile desktop-public --runtime linux-x64 --channel preview");
500+
var parseResult = root.Parse("package --profile mac-notarized --runtime osx-x64 --channel preview --notarize false");
473501

474502
var runtimeResult = parseResult.GetResult(runtimeOption);
475503
var channelResult = parseResult.GetResult(channelOption);
504+
var notarizeResult = parseResult.GetResult(notarizeOption);
476505

477506
Assert.NotNull(runtimeResult);
478507
Assert.NotNull(channelResult);
508+
Assert.NotNull(notarizeResult);
479509
Assert.False(runtimeResult!.Implicit);
480510
Assert.False(channelResult!.Implicit);
481-
Assert.Equal("linux-x64", PackageCommand.GetValue(runtimeOption, parseResult, profile.Runtime));
511+
Assert.False(notarizeResult!.Implicit);
512+
Assert.Equal("osx-x64", PackageCommand.GetValue(runtimeOption, parseResult, profile.Runtime));
482513
Assert.Equal("preview", PackageCommand.GetValue(channelOption, parseResult, profile.Channel));
514+
Assert.False(PackageCommand.GetValue(notarizeOption, parseResult, profile.Notarize));
515+
}
516+
517+
[Fact]
518+
public void PackageCommand_try_resolve_profile_reports_unknown_profiles()
519+
{
520+
using var stderr = new StringWriter();
521+
var previousError = Console.Error;
522+
Console.SetError(stderr);
523+
524+
try
525+
{
526+
var resolved = PackageCommand.TryResolveProfile("unknown-profile", out var profile);
527+
528+
Assert.False(resolved);
529+
Assert.Equal(string.Empty, profile.Name);
530+
Assert.Equal("stable", profile.Channel);
531+
Assert.Null(profile.Runtime);
532+
Assert.False(profile.Notarize);
533+
Assert.Contains("Unknown package profile 'unknown-profile'.", stderr.ToString(), StringComparison.Ordinal);
534+
Assert.Contains("desktop-internal, desktop-public, mac-notarized", stderr.ToString(), StringComparison.Ordinal);
535+
}
536+
finally
537+
{
538+
Console.SetError(previousError);
539+
}
483540
}
484541

485542
[Fact]

0 commit comments

Comments
 (0)