Skip to content
Open
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
4 changes: 2 additions & 2 deletions Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -87,8 +87,8 @@
<PackageVersion Include="RavenDB.Client" Version="6.2.1" />
<PackageVersion Include="RavenDB.TestDriver" Version="6.2.1" />
<PackageVersion Include="YamlDotNet" Version="16.3.0" />
<PackageVersion Include="SurrealDb.MinimalApis.Extensions" Version="0.9.0" />
<PackageVersion Include="SurrealDb.Net" Version="0.9.0" />
<PackageVersion Include="SurrealDb.MinimalApis.Extensions" Version="0.10.2" />
<PackageVersion Include="SurrealDb.Net" Version="0.10.2" />
<PackageVersion Include="Swashbuckle.AspNetCore" Version="7.3.1" />
<PackageVersion Include="Microsoft.PowerShell.SDK" Version="7.4.10" />
<PackageVersion Include="ModelContextProtocol" Version="0.4.0-preview.3" />
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,19 @@
using SurrealDb.Net.Models;
using System.ComponentModel.DataAnnotations.Schema;

namespace CommunityToolkit.Aspire.Hosting.SurrealDb.ApiService.Models;

[Table(Table)]
public class Todo : Record
{
internal const string Table = "todo";

[Column("title")]
public string? Title { get; set; }

[Column("due_by")]
public DateOnly? DueBy { get; set; } = null;

[Column("is_complete")]
public bool IsComplete { get; set; } = false;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
using Bogus;

namespace CommunityToolkit.Aspire.Hosting.SurrealDb.ApiService.Models;

/// <summary>
/// Faker test class to generate fake <see cref="Todo"/> objects.
/// </summary>
public class TodoFaker : Faker<Todo>
{
public TodoFaker()
{
RuleFor(o => o.Title, f => f.Lorem.Sentence());
RuleFor(o => o.DueBy, f => f.Date.FutureDateOnly());
RuleFor(o => o.IsComplete, f => f.Random.Bool());
}
}
Original file line number Diff line number Diff line change
@@ -1,36 +1,43 @@
using SurrealDb.Net.Models;
using System.ComponentModel.DataAnnotations.Schema;

namespace CommunityToolkit.Aspire.Hosting.SurrealDb.ApiService.Models;

/// <summary>
/// Weather forecast model.
/// </summary>
[Table(Table)]
public class WeatherForecast : Record
{
internal const string Table = "weatherForecast";

/// <summary>
/// Date of the weather forecast.
/// </summary>
[Column("date")]
public DateTime Date { get; set; }

/// <summary>
/// Country of the weather forecast.
/// </summary>
[Column("country")]
public string? Country { get; set; }

/// <summary>
/// Temperature in Celsius.
/// </summary>
[Column("temperature_c")]
public int TemperatureC { get; set; }

/// <summary>
/// Temperature in Fahrenheit.
/// </summary>
[Column("temperature_f")]
public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);

/// <summary>
/// Summary of the weather forecast.
/// </summary>
[Column("summary")]
public string? Summary { get; set; }
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
namespace CommunityToolkit.Aspire.Hosting.SurrealDb.ApiService.Models;

/// <summary>
/// Faker test class to generate fake WeatherForecast objects.
/// Faker test class to generate fake <see cref="WeatherForecast"/> objects.
/// </summary>
public class WeatherForecastFaker : Faker<WeatherForecast>
{
Expand All @@ -21,9 +21,6 @@ public class WeatherForecastFaker : Faker<WeatherForecast>
"Scorching"
};

/// <summary>
/// Constructor
/// </summary>
public WeatherForecastFaker()
{
RuleFor(o => o.Date, f => f.Date.Recent());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,37 +2,51 @@
using SurrealDb.Net;

var builder = WebApplication.CreateBuilder(args);
var configuration = builder.Configuration;

builder.AddServiceDefaults();

builder.AddSurrealClient("db", settings =>
{
settings.Options!.NamingPolicy = "CamelCase";
});
builder.AddSurrealClient("db");

var app = builder.Build();

app.MapDefaultEndpoints();

app.MapGroup("/api")
.MapSurrealEndpoints<WeatherForecast>(
.MapSurrealEndpoints<WeatherForecast, SurrealDbSession>(
"/weatherForecast",
new() { EnableMutations = false }
)
.MapSurrealEndpoints<Todo>("/todo");
.MapSurrealEndpoints<Todo, SurrealDbSession>("/todo");

app.MapPost("/init", InitializeDbAsync);

app.Run();

Task InitializeDbAsync(ISurrealDbClient surrealDbClient)
async Task InitializeDbAsync()
{
const int initialCount = 5;
var weatherForecasts = new WeatherForecastFaker().Generate(initialCount);

var tasks = weatherForecasts.Select(weatherForecast =>
surrealDbClient.Create(WeatherForecast.Table, weatherForecast)
var todos = new TodoFaker().Generate(initialCount);

var surrealDbClient = new SurrealDbClient(
SurrealDbOptions
.Create()
.FromConnectionString(configuration.GetConnectionString("db")!)
.Build()
);

return Task.WhenAll(tasks);
var weatherForecastTasks = weatherForecasts.Select(async weatherForecast => {
await surrealDbClient.Create(WeatherForecast.Table, weatherForecast);
return Task.CompletedTask;
});

var todoTasks = todos.Select(async todo => {
await surrealDbClient.Create(Todo.Table, todo);
return Task.CompletedTask;
});

await Task.WhenAll(weatherForecastTasks.Concat(todoTasks));

await surrealDbClient.DisposeAsync();
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,8 @@ import { createBuilder } from "./.modules/aspire.js";
const builder = await createBuilder();

let primary = await builder.addSurrealServer("primary", {
port: 18000,
path: "memory",
strictMode: true,
port: 18000,
path: "memory",
});

primary = await primary.withDataVolume({ name: "surreal-primary-data" });
Expand All @@ -14,22 +13,22 @@ primary = await primary.withSurrealist({ containerName: "surrealist-primary" });
primary = await primary.withSurrealDbOtlpExporter();

let appNamespace = await primary.addNamespace("appns", {
namespaceName: "polyglotNs",
namespaceName: "polyglotNs",
});
appNamespace = await appNamespace.withCreationScript(
"DEFINE NAMESPACE IF NOT EXISTS `polyglotNs`;",
"DEFINE NAMESPACE IF NOT EXISTS `polyglotNs`;",
);

let appDatabase = await appNamespace.addDatabase("appdb", {
databaseName: "polyglotDb",
databaseName: "polyglotDb",
});
appDatabase = await appDatabase.withCreationScript(
"DEFINE DATABASE IF NOT EXISTS `polyglotDb`;",
"DEFINE DATABASE IF NOT EXISTS `polyglotDb`;",
);

let mounted = await builder.addSurrealServer("mounted", {
port: 18001,
path: "memory",
port: 18001,
path: "memory",
});
mounted = await mounted.withDataBindMount("./data");
mounted = await mounted.withInitFiles("./seed.surql");
Expand All @@ -43,13 +42,13 @@ const _primaryConnectionString = await primary.connectionStringExpression();

const _namespaceParent = await appNamespace.parent();
const _namespaceConnectionString =
await appNamespace.connectionStringExpression();
await appNamespace.connectionStringExpression();
const _namespaceName = await appNamespace.namespaceName();
const _namespaceParentName = await _namespaceParent.name();

const _databaseParent = await appDatabase.parent();
const _databaseConnectionString =
await appDatabase.connectionStringExpression();
await appDatabase.connectionStringExpression();
const _databaseName = await appDatabase.databaseName();
const _databaseParentName = await _databaseParent.name();
const _databaseServerName = await (await _databaseParent.parent()).name();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<Project Sdk="Aspire.AppHost.Sdk/13.3.0">
<Project Sdk="Aspire.AppHost.Sdk/13.3.5">

<PropertyGroup>
<OutputType>Exe</OutputType>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,33 +4,33 @@

bool strictMode = false;

var db = builder.AddSurrealServer("surreal", strictMode: strictMode)
var db = builder.AddSurrealServer("surreal")
.WithSurrealist()
.AddNamespace("ns")
.AddDatabase("db");

if (strictMode)
{
#pragma warning disable CTASPIRE002 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
db.WithCreationScript(
$"""
DEFINE DATABASE IF NOT EXISTS {nameof(db)};
USE DATABASE {nameof(db)};

DEFINE TABLE todo;
DEFINE FIELD title ON todo TYPE string;
DEFINE FIELD dueBy ON todo TYPE datetime;
DEFINE FIELD isComplete ON todo TYPE bool;

DEFINE TABLE weatherForecast;
DEFINE FIELD date ON weatherForecast TYPE datetime;
DEFINE FIELD country ON weatherForecast TYPE string;
DEFINE FIELD temperatureC ON weatherForecast TYPE number;
DEFINE FIELD summary ON weatherForecast TYPE string;
"""
);
string strictSuffix = strictMode ? " STRICT" : string.Empty;
db.WithCreationScript(
$"""
DEFINE DATABASE IF NOT EXISTS {nameof(db)}{strictSuffix};
USE DATABASE {nameof(db)};

DEFINE TABLE todo;
DEFINE FIELD title ON todo TYPE string;
DEFINE FIELD due_by ON todo TYPE datetime;
DEFINE FIELD is_complete ON todo TYPE bool;

DEFINE TABLE weatherForecast;
DEFINE FIELD date ON weatherForecast TYPE datetime;
DEFINE FIELD country ON weatherForecast TYPE string;
DEFINE FIELD temperature_c ON weatherForecast TYPE number;
DEFINE FIELD temperature_f ON weatherForecast TYPE number;
DEFINE FIELD summary ON weatherForecast TYPE string;
"""
);
#pragma warning restore CTASPIRE002 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
}


builder.AddProject<CommunityToolkit_Aspire_Hosting_SurrealDb_ApiService>("apiservice")
.WithReference(db)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ public static class SurrealDbBuilderExtensions
/// <param name="password">The parameter used to provide the administrator password for the SurrealDB resource. If <see langword="null"/> a random password will be generated.</param>
/// <param name="port">The host port for the SurrealDB instance.</param>
/// <param name="path">Sets the path for storing data. If no argument is given, the default of <c>memory</c> for non-persistent storage in memory is assumed.</param>
/// <param name="strictMode">Whether strict mode is enabled on the server.</param>
/// <returns>A reference to the <see cref="IResourceBuilder{T}"/>.</returns>
/// <remarks>
/// <example>
Expand All @@ -58,8 +57,7 @@ public static IResourceBuilder<SurrealDbServerResource> AddSurrealServer(
IResourceBuilder<ParameterResource>? userName = null,
IResourceBuilder<ParameterResource>? password = null,
int? port = null,
string path = "memory",
bool strictMode = false
string path = "memory"
)
{
ArgumentNullException.ThrowIfNull(builder);
Expand All @@ -70,10 +68,6 @@ public static IResourceBuilder<SurrealDbServerResource> AddSurrealServer(
"start",
path
};
if (strictMode)
{
args.Add("--strict");
}

// The password must be at least 8 characters long and contain characters from three of the following four sets: Uppercase letters, Lowercase letters, Base 10 digits, and Symbols
var passwordParameter = password?.Resource ?? ParameterResourceBuilderExtensions.CreateDefaultPasswordParameter(builder, $"{name}-password", minLower: 1, minUpper: 1, minNumeric: 1);
Expand All @@ -97,11 +91,6 @@ public static IResourceBuilder<SurrealDbServerResource> AddSurrealServer(
.WithArgs([.. args])
.OnResourceReady(async (_, @event, ct) =>
{
if (!strictMode)
{
return;
}

var connectionString = await surrealServer.GetConnectionStringAsync(ct).ConfigureAwait(false);
if (connectionString is null)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,13 @@ internal sealed class SurrealDbContainerImageTags
public const string Registry = "docker.io";
/// <summary>surrealdb/surrealdb</summary>
public const string Image = "surrealdb/surrealdb";
/// <summary>v2.4</summary>
public const string Tag = "v2.4";
/// <summary>v3.0</summary>
public const string Tag = "v3.0";

/// <summary>docker.io</summary>
public const string SurrealistRegistry = "docker.io";
/// <summary>surrealdb/surrealist</summary>
public const string SurrealistImage = "surrealdb/surrealist";
/// <summary>3.6.9</summary>
public const string SurrealistTag = "3.6.9";
/// <summary>3.8.3</summary>
public const string SurrealistTag = "3.8.3";
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@ public sealed class SurrealDbClientSettings
/// Gets or sets the Service lifetime to register services under.
/// </summary>
/// <value>
/// The default value is <see langword="ServiceLifetime.Singleton"/>.
/// The default value is <see cref="ServiceLifetime.Scoped"/>.
/// </value>
public ServiceLifetime Lifetime { get; set; } = ServiceLifetime.Singleton;
public ServiceLifetime Lifetime { get; set; } = ServiceLifetime.Scoped;
Comment thread
Odonno marked this conversation as resolved.

/// <summary>
/// Gets or sets a boolean value that indicates whether the SurrealDB health check is disabled or not.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,11 @@ public async Task ApiServiceStartsAndRespondsOk()
await fixture.ResourceNotificationService.WaitForResourceHealthyAsync(resourceName).WaitAsync(TimeSpan.FromMinutes(1));
var httpClient = fixture.CreateHttpClient(resourceName);

var todoResponse = await httpClient.GetAsync("/api/todo");
Assert.Equal(HttpStatusCode.OK, todoResponse.StatusCode);

var initResponse = await httpClient.PostAsync("/init", null);
Assert.Equal(HttpStatusCode.OK, initResponse.StatusCode);

var todoResponse = await httpClient.GetAsync("/api/todo");
Assert.Equal(HttpStatusCode.OK, todoResponse.StatusCode);

var weatherForecastResponse = await httpClient.GetAsync("/api/weatherForecast");
Assert.Equal(HttpStatusCode.OK, weatherForecastResponse.StatusCode);
Expand Down
Loading
Loading